From: Bastien Guerry Date: Tue, 12 Nov 2013 13:06:26 +0000 (+0100) Subject: Merge Org version 8.2.3a. X-Git-Tag: emacs-24.3.90~173^2^2~42^2~45^2~387^2~857 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=271672fad74cdbc9065d23d6e6cee1b8540f571b;p=emacs.git Merge Org version 8.2.3a. --- diff --git a/doc/misc/ChangeLog b/doc/misc/ChangeLog index 1396fc12f43..976922a3978 100644 --- a/doc/misc/ChangeLog +++ b/doc/misc/ChangeLog @@ -1,3 +1,483 @@ +2013-11-12 Aaron Ecay + + * org.texi (Exporting code blocks): Document the 'inline-only + setting for `org-export-babel-evaluate'. Document how :var + introduces code block dependencies. + +2013-11-12 Achim Gratz + + * org.texi (Header arguments): Document header-args[:lang] + properties and remove deprecated old-style properties from + documentation. + + * org.texi (Agenda commands): Remove footnote from @tsubheading + and add a sentence with the reference instead. + +2013-11-12 Bastien Guerry + + * org.texi (Catching invisible edits): + * org.texi (Plain lists, Plain lists): + * org.texi (Advanced configuration): + * org.texi (Tag groups): + * org.texi (Conventions): + * org.texi (Checkboxes, Radio lists): + * org.texi (Top, Summary, Exporting): + * org.texi (In-buffer settings): Fix typos. + + * org.texi (Refile and copy): Document `org-copy' and `C-3 C-c + C-w'. Add an index entry for `org-refile-keep'. + + * org.texi (Plain lists): Add an index entry for sorting plain + list. Document sorting by checked status for check lists. + + * org.texi (Publishing options): Fix old variable names. + + * org.texi (Orgstruct mode): Fix suggested setting of + `orgstruct-heading-prefix-regexp'. + + * org.texi (Export settings): Document + `org-export-allow-bind-keywords'. + + * org.texi (History and Acknowledgments): Small rephrasing. + + * org.texi (Template elements): Add a footnote about tags accepted + in a year datetree. + + * org.texi (Beamer export, @LaTeX{} and PDF export) + (Header and sectioning, @LaTeX{} specific attributes): Enhance + style. + + * org.texi (Agenda commands): Add a footnote about dragging agenda + lines: it does not persist and it does not change the .org files. + + * org.texi (Agenda commands): Add a table heading for dragging + agenda lines forward/backward. + + * org.texi (Agenda commands): Add documentation for + `org-agenda-bulk-toggle' and `org-agenda-bulk-toggle-all'. + + * org.texi (Publishing options): Update the list of options. + (Simple example, Complex example): Fix the examples. + + * org.texi (Formula syntax for Calc): Don't use a bold font the + warning. + + * org.texi (Other built-in back-ends): New section. + + * org.texi (Editing source code): Document + `org-edit-src-auto-save-idle-delay' and + `org-edit-src-turn-on-auto-save'. + + * org.texi (External links): Document contributed link types + separately. + + * org.texi (Closing items): Document + `org-closed-keep-when-no-todo'. + + * org.texi (Export back-ends): Rename from "Export formats". + (The Export Dispatcher): Remove reference to + `org-export-run-in-background'. + (Export settings): Minor rewrites. + (ASCII/Latin-1/UTF-8 export): Update variable's name. + (In-buffer settings): Add #+HTML_HEAD_EXTRA. + + * org.texi (Export in foreign buffers): New section. + (Exporting): Remove documentation about converting the selected + region. + + * org.texi (Advanced configuration): Put the filter valid types in + a table. Use @lisp and @smalllisp. + + * org.texi: Use @code{nil} instead of nil. Update the maintainer + contact info. + + * org.texi (Exporting): Better introductory sentence. Add a note + about conversion commands. + (Feedback, Orgstruct mode, Built-in table editor) + (Built-in table editor, Orgtbl mode, Updating the table) + (Property syntax, Capturing column view, Capture) + (Agenda files, Agenda commands, CDLaTeX mode, CDLaTeX mode) + (Exporting, Extending ODT export) + (Working with @LaTeX{} math snippets, dir, Customization) + (Radio tables, A @LaTeX{} example, Pulling from MobileOrg): + Uniformly use @kbd{M-x command RET}. + + * org.texi (Filtering/limiting agenda items): New subsection. + Document the use of `org-agenda-max-*' options and + `org-agenda-limit-interactively' from the agenda. + (Agenda commands): Move details about filtering commands to + the new section, only include a summary here. + (Customizing tables in ODT export) + (System-wide header arguments, Conflicts, Dynamic blocks): Use + spaces for indentation. + + * org.texi (Emphasis and monospace): Mention `org-emphasis-alist'. + + * org.texi (Links in HTML export, Images in HTML export) + (post): Fix syntax within #+ATTR_*. + (Tables in HTML export): Document `org-html-table-row-tags' + and use `org-html-table-default-attributes' instead of + `org-html-table-tag'. + + * org.texi (Publishing action, Publishing options) + (Publishing links): Major rewrite. Enhance explanations for + `org-org-publish-to-org'. Remove reference to + `org-export-run-in-background'. + + * org.texi: Fix many small typos. Use #+NAME instead of + #+TBLNAME. Use @smalllisp instead of @example. + (Special symbols): Add index? + (HTML preamble and postamble): Don't mention obsolete use of + opt-plist. + (JavaScript support): Don't mention the org-jsinfo.el file as it + has been merged with ox-html.el. + + * org.texi (Installation, Feedback, Setting Options) + (Code evaluation security, org-crypt.el): Use @lisp instead of + @example. + (Agenda commands): Use @table instead of @example. + + * org.texi (Adding hyperlink types): New appendix. + + * org.texi (ODT export commands, Extending ODT export) + (Applying custom styles, Images in ODT export) + (Labels and captions in ODT export) + (Literal examples in ODT export) + (Configuring a document converter) + (Working with OpenDocument style files) + (Customizing tables in ODT export) + (Validating OpenDocument XML): Fix options names. + + * org.texi (History and Acknowledgments): Update acknowledgments + to Nicolas. Add Nicolas Goaziou to the list of contributors. + + * org.texi (System-wide header arguments): Don't use "customizing" + for setting a variable. Also remove comments. + + * org.texi (Weekly/daily agenda): Add `org-agenda-start-day' and + `org-agenda-start-on-weekday' to the variable index and document + them. + + * org.texi (Sparse trees, Agenda commands) + (@LaTeX{} fragments, Selective export, Export options) + (The export dispatcher, ASCII/Latin-1/UTF-8 export) + (HTML Export commands, @LaTeX{}/PDF export commands) + (iCalendar export, Publishing options, Triggering publication) + (In-buffer settings): Update to reflect changes from the new + export engine. + + * org.texi (Matching tags and properties): More examples. Explain + group tags expansion as regular expressions. + + * org.texi (Tag groups): New section. + + * org.texi (Setting tags): Tiny formatting fixes. + + * org.texi (Plain lists, Checkboxes): Use non-obsolete variable + names. + + * org.texi (Storing searches): Add "agenda" and "agenda*" to the + concept index. Include example for these agenda views. + (Special agenda views): Mention the "agenda*" agenda view. + + * org.texi (Repeated tasks): Document how to ignore a repeater + when using both a scheduled and a deadline timetamp. + + * org.texi (Global and local cycling): Wrap in a new subsection. + (Initial visibility, Catching invisible edits): New subsections. + + * org.texi (Visibility cycling): Mention that + `org-agenda-inhibit-startup' will prevent visibility setting when + the agenda opens an Org file for the first time. + + * org.texi (Org syntax): New section. + + * org.texi (Orgstruct mode): Document + `orgstruct-heading-prefix-regexp'. + + * org.texi (Speeding up your agendas): New section. + + * org.texi (Installation): When installing Org from ELPA, users + should do this from an Emacs session where no .org file has been + visited. + + * org.texi (CSS support, In-buffer settings): Update HTML options + names. + + * org.texi (Structure editing): Update documentation for + `org-insert-heading-or-item'. + (Plain lists, Relative timer): Update index entry. + + * org.texi (JavaScript support): Update variable names. + + * org.texi (comments): Minor formatting fix. + + * org.texi (@LaTeX{} fragments): Minor enhancement. + + * org.texi: Update the list contributions. + + * org.texi (Agenda commands): Exporting the agenda to an .org file + will not copy the subtrees and the inherited tags. Document + `org-agenda-filter-by-regexp'. + + * org.texi (Publishing action, Complex example): Fix names of + publishing functions. + + * org.texi (Top, Exporting): Delete references to Freemind. + (Freemind export): Delete section. + + * org.texi (Top, Exporting): Delete references to the XOXO export. + (XOXO export): Delete section. + + * org.texi (Capture): Mention that org-remember.el is not + supported anymore. + + * org.texi (Top, Exporting, Beamer class export): Delete + references to the TaskJuggler export. + (History and Acknowledgments): Mention that the TaskJuggler has + been rewritten by Nicolas and now lives in the contrib/ directory + of Org's distribution. Mention that Jambunathan rewrote the HTML + exporter. Remove Jambunathan from my own acknowledgments. + (TaskJuggler export): Delete. + + * org.texi (HTML preamble and postamble) + (Tables in HTML export, Images in HTML export) + (Math formatting in HTML export, CSS support) + (@LaTeX{} and PDF export, Publishing options): Fix the names of + the HTML export and publishing options. + + * org.texi (Literal examples, Export options) + (@LaTeX{} and PDF export, Header and sectioning) + (Publishing options): Fix LaTeX options names. + + * org.texi (Export options, CSS support, In-buffer settings): Fix + references to HTML_LINK_* and HTML_STYLE keywords. + + * org.texi (Export options, In-buffer settings): Fix references to + #+SELECT_TAGS and #+EXCLUDE_TAGS and remove reference to #+XSLT. + + * org.texi (Top, Markup, Initial text, Images and tables) + (@LaTeX{} fragments, @LaTeX{} fragments, Exporting) + (Export options, JavaScript support, Beamer class export): Remove + references to the DocBook export, which has been deleted. + (History and Acknowledgments): Mention that DocBook has been + deleted, suggest to use the Texinfo exporter instead, then to + convert the .texi to DocBook with makeinfo. + (Links in ODT export, Tables in ODT export): Fix indices. + + * org.texi (Deadlines and scheduling): Add a variable to the + index. Add documentation about delays for scheduled tasks. + + * org.texi (Emphasis and monospace): Mention + `org-fontify-emphasized-text' and + `org-emphasis-regexp-components'. + + * org.texi (References): Small enhancement. + + * org.texi (Column width and alignment): Make the example visually + more clear. + + * org.texi (The clock table): Document :mstart and :wstart as a + way to set the starting day of the week. + + * org.texi (In-buffer settings): Document new startup keywords. + Thanks to John J Foerch for this idea. + + * org.texi (Include files): Tiny formatting fix. + + * org.texi (Activation): Point to the "Conflicts" section. + +2013-11-12 Carsten Dominik + + * org.texi (CSS support): Clarify this section. + + * org.texi (@LaTeX{} specific attributes): Document that tabu and + tabularx packages are not in the default set of packages. + + * org.texi (Agenda commands): Document fortnight view. + + * org.texi: Document conflict with ecomplete.el. + + * org.texi (History and Acknowledgments): Acknowledgements for + Jason Dunsmore and Rakcspace. + + * org.texi: Rename org-crypt.el node to org-crypt. + + * org.texi (A @LaTeX{} example): Fix typo in variable name. + + * org.texi (MobileOrg): Mention the new iPhone developer. + + * org.texi (Table of contents) Improve documentation of TOC + placement. + + * org.texi: Explain that date/time information at read-date prompt + should start at the beginning, not anywhere in the middle of a + long string. + +2013-11-12 Christopher Schmidt + + * org.texi (Orgstruct mode): Fix wrong regexp. + +2013-11-12 Eric Abrahamsen + + * org.texi: Document export to (X)HTML flavors. + +2013-11-12 Eric Schulte + + * org.texi (Extracting source code): Mention the prefix argument + to org-babel-tangle. + (noweb): Removed erroneous negative. + (Specific header arguments): Document new header arguments. + Documentation for new tangle-mode header argument. + (Top): Documentation for new tangle-mode header argument. + (rownames): Documentation for new tangle-mode header argument. + Mention elisp as special rowname case. + (tangle-mode): Documentation for new tangle-mode header argument. + (post): Documentation and an example of usage. + (var): Remove the "Alternate argument syntax" section from the + documentation. + (hlines): Note that :hline has no effect for Emacs Lisp code + blocks. + +2013-11-12 Feng Shu + + * org.texi (@LaTeX{} fragments, Previewing @LaTeX{} fragments) + (Math formatting in HTML export) + (Working with @LaTeX{} math snippets): Add document about creating + formula image with imagemagick. + + * org.texi (@LaTeX{} specific attributes): Document `:caption' + attribute of #+ATTR_LATEX. + +2013-11-12 Grégoire Jadi + + * org.texi (Handling links): Fix a typo in + `org-startup-with-inline-images' documentation. + + * org.texi (Previewing @LaTeX{} fragments): Document the startup + keywords to use for previewing LaTeX fragments or not. + (Summary of in-buffer settings): Improve formatting and add an + entry for the variable `org-startup-with-latex-preview'. + + * org.texi (Property syntax): Recall the user to refresh the org + buffer when properties are set on a per-file basis. + +2013-11-12 Gustav Wikström (tiny change) + + * org.texi (Matching tags and properties): Clarification. + +2013-11-12 Ippei Furuhashi + + * org.texi (Editing and debugging formulas): Add an example when a + table has multiple #+TBLFM lines. + +2013-11-12 Ivan Vilata i Balaguer (tiny change) + + * org.texi (The clock table): Document acceptance of relative + times in tstart and tend, link to syntax description and provide + example. + +2013-11-12 Jarmo Hurri + + * org.texi (The spreadsheet): Document lookup functions. + +2013-11-12 Kodi Arfer (tiny change) + + * org.text (CSS support): Mention .figure-number, .listing-number, + and .table-number. + +2013-11-12 Michael Brand + + * org.texi + (Formula syntax for Calc, Emacs Lisp forms as formulas): Reformat + spreadsheet formula mode strings and some examples from @example + block with xy @r{yz} to @table. + + * org.texi (Formula syntax for Calc): Improve the documentation of + empty fields in formulas for spreadsheet. Add explanation and + example for empty field. Extend explanations of format + specifiers. Add a sentence to mention Calc defmath. + + * org.texi (Column formulas): Add a sentence to be more explicit + about when a table header is mandatory. + +2013-11-12 Nicolas Goaziou + + * org.texi (Subscripts and superscripts): Remove reference to + quoted underscores until this mechanism is implemented again. + + * org.texi (Beamer export): Be more accurate about BEAMER_OPT + property. + + * org.texi (Document title): Subtree export is no longer triggered + by marking one as the region. + (Horizontal rules): LaTeX export doesn't use "\hrule" anymore, and + giving examples isn't very useful: "horizontal rule" is, at least, + as explicit as
. + + * org.texi (HTML doctypes): Reflect keyword removal. + (CSS support): Reflect keyword removal. + + * org.texi (@LaTeX{} specific attributes): Document new :float + values. + + * org.texi (Export settings): Improve documentation. + + * org.texi (Math formatting in HTML export): Fix OPTIONS item's name. + (Text areas in HTML export): Update text areas. + (HTML Export commands): Update export commands. + + * org.texi (Header and sectioning): Add a footnote about the + different between LATEX_HEADER_EXTRA and LATEX_HEADER. + + * org.texi (The Export Dispatcher): Document + `org-export-in-background'. + + * org.texi (Footnotes): Export back-ends do not use + `org-footnote-normalize' anymore. + + * org.texi: Document variable changes. + + * org.texi (Export settings): Doument p: item in OPTIONS keyword. + + * org.texi (Exporting): Massive rewrite of the first sections. + (Selective export): Delete. + (The Export Dispatcher): Rewrite. + (Export options): Rewrite as "Export settings". + + * org.texi: Small changes to documentation for embedded LaTeX. + + * org.texi (Internal links): Document #+NAME keyword and + cross-referencing during export. + + * org.texi (Include files): Remove reference to :prefix1 + and :prefix. Give more details for :minlevel. + + * org.texi (Macro replacement): Fix macro name. Update + documentation about possible locations and escaping mechanism. + + * org.texi (Table of contents): Update documentation. Document + lists of listings and lists of tables. Add documentation for + optional title and #+TOC: keyword. + +2013-11-12 Rick Frankel + + * org.texi (results): Add Format section, broken out of Type + section to match code. + (hlines, colnames): Remove incorrect Emacs Lisp exception. Note + that the actual default handling (at least for python and + emacs-lisp) does not seem to match the description. + +2013-11-12 Sacha Chua (tiny change) + + * org.texi (The date/time prompt): Update the documentation to + reflect the new way `org-read-date-get-relative' handles weekdays. + +2013-11-12 Yasushi Shoji + + * org.texi (Resolving idle time): Document + `org-clock-x11idle-program-name'. + 2013-10-24 Michael Albinus * ert.texi (Running Tests Interactively): Adapt examle output. diff --git a/doc/misc/org.texi b/doc/misc/org.texi index 832976e9ea0..94f7ac30ac8 100644 --- a/doc/misc/org.texi +++ b/doc/misc/org.texi @@ -2,7 +2,8 @@ @c %**start of header @setfilename ../../info/org @settitle The Org Manual -@set VERSION 7.9.3f (GNU Emacs 24.3) + +@include org-version.inc @c Use proper quote and backtick for code sections in PDF output @c Cf. Texinfo manual 14.2 @@ -10,7 +11,7 @@ @set txicodequotebacktick @c Version and Contact Info -@set MAINTAINERSITE @uref{http://orgmode.org,maintainers webpage} +@set MAINTAINERSITE @uref{http://orgmode.org,maintainers web page} @set AUTHOR Carsten Dominik @set MAINTAINER Carsten Dominik @set MAINTAINEREMAIL @email{carsten at orgmode dot org} @@ -287,7 +288,8 @@ modify this GNU manual.'' @subtitle Release @value{VERSION} @author by Carsten Dominik -with contributions by David O'Toole, Bastien Guerry, Philip Rooke, Dan Davison, Eric Schulte, Thomas Dye and Jambunathan K. +with contributions by David O'Toole, Bastien Guerry, Philip Rooke, Dan +Davison, Eric Schulte, Thomas Dye, Jambunathan K and Nicolas Goaziou. @c The following two commands start the copyright page. @page @@ -320,7 +322,7 @@ with contributions by David O'Toole, Bastien Guerry, Philip Rooke, Dan Davison, * Capture - Refile - Archive:: The ins and outs for projects * Agenda Views:: Collecting information into views * Markup:: Prepare text for rich export -* Exporting:: Sharing and publishing of notes +* Exporting:: Sharing and publishing notes * Publishing:: Create a web site of linked Org files * Working With Source Code:: Export, evaluate, and tangle code blocks * Miscellaneous:: All the rest which did not fit elsewhere @@ -357,6 +359,18 @@ Document structure * Blocks:: Folding blocks * Footnotes:: How footnotes are defined in Org's syntax * Orgstruct mode:: Structure editing outside Org +* Org syntax:: Formal description of Org's syntax + +Visibility cycling + +* Global and local cycling:: Cycling through various visibility states +* Initial visibility:: Setting the initial visibility state +* Catching invisible edits:: Preventing mistakes when editing invisible parts + +Global and local cycling + +* Initial visibility:: Setting the initial visibility state +* Catching invisible edits:: Preventing mistakes when editing invisible parts Tables @@ -375,6 +389,7 @@ The spreadsheet * Durations and time values:: How to compute durations and time values * Field and range formulas:: Formula for specific (ranges of) fields * Column formulas:: Formulas valid for an entire column +* Lookup functions:: Lookup functions for searching tables * Editing and debugging formulas:: Fixing formulas * Updating the table:: Recomputing all dependent fields * Advanced features:: Field and column names, parameters and automatic recalc @@ -423,6 +438,7 @@ Tags * Tag inheritance:: Tags use the tree structure of the outline * Setting tags:: How to assign tags to a headline +* Tag groups:: Use one tag to search for several tags * Tag searches:: Searching for combinations of tags Properties and columns @@ -477,7 +493,7 @@ Capture - Refile - Archive * Attachments:: Add files to tasks * RSS Feeds:: Getting input from RSS feeds * Protocols:: External (e.g., Browser) access to Emacs and Org -* Refiling notes:: Moving a tree from one place to another +* Refile and copy:: Moving/copying a tree from one place to another * Archiving:: What to do with finished projects Capture @@ -521,7 +537,8 @@ Presentation and sorting * Categories:: Not all tasks are equal * Time-of-day specifications:: How the agenda knows the time -* Sorting of agenda items:: The order of things +* Sorting agenda items:: The order of things +* Filtering/limiting agenda items:: Dynamically narrow the agenda Custom agenda views @@ -532,19 +549,19 @@ Custom agenda views Markup for rich export * Structural markup elements:: The basic structure as seen by the exporter -* Images and tables:: Tables and Images will be included +* Images and tables:: Images, tables and caption mechanism * Literal examples:: Source code examples with special formatting * Include files:: Include additional files into a document * Index entries:: Making an index -* Macro replacement:: Use macros to create complex output +* Macro replacement:: Use macros to create templates * Embedded @LaTeX{}:: LaTeX can be freely used inside Org documents +* Special blocks:: Containers targeted at export back-ends Structural markup elements * Document title:: Where the title is taken from * Headings and sections:: The document structure as seen by the exporter * Table of contents:: The if and where of the table of contents -* Initial text:: Text before the first heading? * Lists:: Lists * Paragraphs:: Paragraphs * Footnote markup:: Footnotes @@ -562,22 +579,24 @@ Embedded @LaTeX{} Exporting -* Selective export:: Using tags to select and exclude trees -* Export options:: Per-file export settings -* The export dispatcher:: How to access exporter commands +* The Export Dispatcher:: The main exporter interface +* Export back-ends:: Built-in export formats +* Export settings:: Generic export settings * ASCII/Latin-1/UTF-8 export:: Exporting to flat files with encoding +* Beamer export:: Exporting as a Beamer presentation * HTML export:: Exporting to HTML * @LaTeX{} and PDF export:: Exporting to @LaTeX{}, and processing to PDF -* DocBook export:: Exporting to DocBook +* Markdown export:: Exporting to Markdown * OpenDocument Text export:: Exporting to OpenDocument Text -* TaskJuggler export:: Exporting to TaskJuggler -* Freemind export:: Exporting to Freemind mind maps -* XOXO export:: Exporting to XOXO -* iCalendar export:: Exporting in iCalendar format +* iCalendar export:: Exporting to iCalendar +* Other built-in back-ends:: Exporting to @code{Texinfo}, a man page, or Org +* Export in foreign buffers:: Author tables in lists in Org syntax +* Advanced configuration:: Fine-tuning the export output HTML export * HTML Export commands:: How to invoke HTML export +* HTML doctypes:: Org can export to various (X)HTML flavors * HTML preamble and postamble:: How to insert a preamble and a postamble * Quoting HTML tags:: Using direct HTML in Org mode * Links in HTML export:: How links will be interpreted and formatted @@ -590,21 +609,10 @@ HTML export @LaTeX{} and PDF export -* @LaTeX{}/PDF export commands:: +* @LaTeX{} export commands:: How to export to LaTeX and PDF * Header and sectioning:: Setting up the export file structure * Quoting @LaTeX{} code:: Incorporating literal @LaTeX{} code -* Tables in @LaTeX{} export:: Options for exporting tables to @LaTeX{} -* Images in @LaTeX{} export:: How to insert figures into @LaTeX{} output -* Beamer class export:: Turning the file into a presentation - -DocBook export - -* DocBook export commands:: How to invoke DocBook export -* Quoting DocBook code:: Incorporating DocBook code in Org files -* Recursive sections:: Recursive sections in DocBook -* Tables in DocBook export:: Tables are exported as HTML tables -* Images in DocBook export:: How to insert figures into DocBook output -* Special characters:: How to handle special characters +* @LaTeX{} specific attributes:: Controlling @LaTeX{} output OpenDocument Text export @@ -680,8 +688,8 @@ Using header arguments * System-wide header arguments:: Set global default values * Language-specific header arguments:: Set default values by language -* Buffer-wide header arguments:: Set default values for a specific buffer * Header arguments in Org mode properties:: Set default values for a buffer or heading +* Language-specific header arguments in Org mode properties:: Set langugage-specific default values for a buffer or heading * Code block specific header arguments:: The most common way to set values * Header arguments in function calls:: The most specific level @@ -714,8 +722,12 @@ Specific header arguments * colnames:: Handle column names in tables * rownames:: Handle row names in tables * shebang:: Make tangled files executable +* tangle-mode:: Set permission of tangled files * eval:: Limit evaluation of specific code blocks * wrap:: Mark source block evaluation results +* post:: Post processing of code block results +* prologue:: Text to prepend to code block body +* epilogue:: Text to append to code block body Miscellaneous @@ -729,7 +741,7 @@ Miscellaneous * Clean view:: Getting rid of leading stars in the outline * TTY keys:: Using Org on a tty * Interaction:: Other Emacs packages -* org-crypt.el:: Encrypting Org files +* org-crypt:: Encrypting Org files Interaction with other packages @@ -741,11 +753,13 @@ Hacking * Hooks:: How to reach into Org's internals * Add-on packages:: Available extensions * Adding hyperlink types:: New custom link types +* Adding export back-ends:: How to write new export back-ends * Context-sensitive commands:: How to add functionality to such commands * Tables in arbitrary syntax:: Orgtbl for @LaTeX{} and other programs * Dynamic blocks:: Automatically filled blocks * Special agenda views:: Customized views -* Extracting agenda information:: Postprocessing of agenda information +* Speeding up your agendas:: Tips on how to speed up your agendas +* Extracting agenda information:: Post-processing of agenda information * Using the property API:: Writing programs that use entry properties * Using the mapping API:: Mapping over all or selected entries @@ -754,7 +768,7 @@ Tables and lists in arbitrary syntax * Radio tables:: Sending and receiving radio tables * A @LaTeX{} example:: Step by step, almost a tutorial * Translator functions:: Copy and modify -* Radio lists:: Doing the same for lists +* Radio lists:: Sending and receiving lists MobileOrg @@ -794,7 +808,7 @@ timestamps, and scheduling. It dynamically compiles entries into an agenda that utilizes and smoothly integrates much of the Emacs calendar and diary. Plain text URL-like links connect to websites, emails, Usenet messages, BBDB entries, and any files related to the projects. -For printing and sharing of notes, an Org file can be exported as a +For printing and sharing notes, an Org file can be exported as a structured ASCII file, as HTML, or (TODO and agenda items only) as an iCalendar file. It can also serve as a publishing tool for a set of linked web pages. @@ -828,7 +842,7 @@ ends, for example: @pindex GTD, Getting Things Done @r{@bullet{} an environment in which to implement David Allen's GTD system} @r{@bullet{} a simple hypertext system, with HTML and @LaTeX{} export} -@r{@bullet{} a publishing tool to create a set of interlinked webpages} +@r{@bullet{} a publishing tool to create a set of interlinked web pages} @r{@bullet{} an environment for literate programming} @end example @@ -867,10 +881,11 @@ We @b{strongly recommend} to stick to a single installation method. Recent Emacs distributions include a packaging system which lets you install Elisp libraries. You can install Org with @kbd{M-x package-install RET org}. -To make sure your Org configuration is well taken into account, initialize -the package system with @code{(package-initialize)} before setting any Org -option. If you want to use Org's package repository, check out the -@uref{http://orgmode.org/elpa.html, Org ELPA page}. +You need to do this in a session where no @code{.org} file has been visited. +Then, to make sure your Org configuration is taken into account, initialize +the package system with @code{(package-initialize)} in your @file{.emacs} +before setting any Org option. If you want to use Org's package repository, +check out the @uref{http://orgmode.org/elpa.html, Org ELPA page}. @subsubheading Downloading Org as an archive @@ -878,17 +893,17 @@ You can download Org latest release from @uref{http://orgmode.org/, Org's website}. In this case, make sure you set the load-path correctly in your @file{.emacs}: -@example +@lisp (add-to-list 'load-path "~/path/to/orgdir/lisp") -@end example +@end lisp The downloaded archive contains contributed libraries that are not included in Emacs. If you want to use them, add the @file{contrib} directory to your load-path: -@example +@lisp (add-to-list 'load-path "~/path/to/orgdir/contrib/lisp" t) -@end example +@end lisp Optionally, you can compile the files and/or install them in your system. Run @code{make help} to list compilation and installation options. @@ -1001,10 +1016,10 @@ version of Org available---if you are running an outdated version, it is quite possible that the bug has been fixed already. If the bug persists, prepare a report and provide as much information as possible, including the version information of Emacs (@kbd{M-x emacs-version @key{RET}}) and Org -(@kbd{M-x org-version @key{RET}}), as well as the Org related setup in +(@kbd{M-x org-version RET}), as well as the Org related setup in @file{.emacs}. The easiest way to do this is to use the command @example -@kbd{M-x org-submit-bug-report} +@kbd{M-x org-submit-bug-report RET} @end example @noindent which will put all this information into an Emacs mail buffer so that you only need to add your description. If you re not sending the Email @@ -1025,7 +1040,7 @@ is not necessary. In that case it is sufficient to start Emacs as @code{emacs -Q}. The @code{minimal-org.el} setup file can have contents as shown below. -@example +@lisp ;;; Minimal setup to load latest `org-mode' ;; activate debugging @@ -1036,7 +1051,7 @@ shown below. ;; add latest org-mode to load path (add-to-list 'load-path (expand-file-name "/path/to/org-mode/lisp")) (add-to-list 'load-path (expand-file-name "/path/to/org-mode/contrib/lisp" t)) -@end example +@end lisp If an error occurs, a backtrace can be very useful (see below on how to create one). Often a small example file helps, along with clear information @@ -1064,7 +1079,7 @@ Reload uncompiled versions of all Org mode Lisp files. The backtrace contains much more information if it is produced with uncompiled code. To do this, use @example -C-u M-x org-reload RET +@kbd{C-u M-x org-reload RET} @end example @noindent or select @code{Org -> Refresh/Reload -> Reload Org uncompiled} from the @@ -1109,7 +1124,7 @@ and @i{environment keywords} (like @code{#+BEGIN_HTML} to start a @code{HTML} environment). They are written in uppercase in the manual to enhance its readability, but you can use lowercase in your Org files@footnote{Easy templates insert lowercase keywords and Babel dynamically inserts -@code{#+results}.} +@code{#+results}.}. @subsubheading Keybindings and commands @kindex C-c a @@ -1152,6 +1167,7 @@ edit the structure of the document. * Blocks:: Folding blocks * Footnotes:: How footnotes are defined in Org's syntax * Orgstruct mode:: Structure editing outside Org +* Org syntax:: Formal description of Org's syntax @end menu @node Outlines, Headlines, Document Structure, Document Structure @@ -1213,6 +1229,15 @@ variable @code{org-cycle-separator-lines} to modify this behavior. @cindex show hidden text @cindex hide text +@menu +* Global and local cycling:: Cycling through various visibility states +* Initial visibility:: Setting the initial visibility state +* Catching invisible edits:: Preventing mistakes when editing invisible parts +@end menu + +@node Global and local cycling, Initial visibility, Visibility cycling, Visibility cycling +@subsection Global and local cycling + Outlines make it possible to hide parts of the text in the buffer. Org uses just two commands, bound to @key{TAB} and @kbd{S-@key{TAB}} to change the visibility in the buffer. @@ -1295,6 +1320,15 @@ the previously used indirect buffer. Copy the @i{visible} text in the region into the kill ring. @end table +@menu +* Initial visibility:: Setting the initial visibility state +* Catching invisible edits:: Preventing mistakes when editing invisible parts +@end menu + +@node Initial visibility, Catching invisible edits, Global and local cycling, Visibility cycling +@subsection Initial visibility + +@cindex visibility, initialize @vindex org-startup-folded @vindex org-agenda-inhibit-startup @cindex @code{overview}, STARTUP keyword @@ -1302,11 +1336,13 @@ Copy the @i{visible} text in the region into the kill ring. @cindex @code{showall}, STARTUP keyword @cindex @code{showeverything}, STARTUP keyword -When Emacs first visits an Org file, the global state is set to -OVERVIEW, i.e., only the top level headlines are visible. This can be -configured through the variable @code{org-startup-folded}, or on a -per-file basis by adding one of the following lines anywhere in the -buffer: +When Emacs first visits an Org file, the global state is set to OVERVIEW, +i.e., only the top level headlines are visible@footnote{When +@code{org-agenda-inhibit-startup} is non-@code{nil}, Org will not honor the default +visibility state when first opening a file for the agenda (@pxref{Speeding up +your agendas}).} This can be configured through the variable +@code{org-startup-folded}, or on a per-file basis by adding one of the +following lines anywhere in the buffer: @example #+STARTUP: overview @@ -1317,7 +1353,7 @@ buffer: The startup visibility options are ignored when the file is open for the first time during the agenda generation: if you want the agenda to honor -the startup visibility, set @code{org-agenda-inhibit-startup} to nil. +the startup visibility, set @code{org-agenda-inhibit-startup} to @code{nil}. @cindex property, VISIBILITY @noindent @@ -1325,6 +1361,7 @@ Furthermore, any entries with a @samp{VISIBILITY} property (@pxref{Properties and Columns}) will get their visibility adapted accordingly. Allowed values for this property are @code{folded}, @code{children}, @code{content}, and @code{all}. + @table @asis @orgcmd{C-u C-u @key{TAB},org-set-startup-visibility} Switch back to the startup visibility of the buffer, i.e., whatever is @@ -1332,6 +1369,17 @@ requested by startup options and @samp{VISIBILITY} properties in individual entries. @end table +@node Catching invisible edits, , Initial visibility, Visibility cycling +@subsection Catching invisible edits + +@vindex org-catch-invisible-edits +@cindex edits, catching invisible +Sometimes you may inadvertently edit an invisible part of the buffer and be +confused on what has been edited and how to undo the mistake. Setting +@code{org-catch-invisible-edits} to non-@code{nil} will help prevent this. See the +docstring of this option on how Org should catch invisible edits and process +them. + @node Motion, Structure editing, Visibility cycling, Document Structure @section Motion @cindex motion, between headlines @@ -1369,7 +1417,7 @@ q @r{Quit} @end example @vindex org-goto-interface @noindent -See also the variable @code{org-goto-interface}. +See also the option @code{org-goto-interface}. @end table @node Structure editing, Sparse trees, Motion, Document Structure @@ -1388,17 +1436,20 @@ See also the variable @code{org-goto-interface}. @table @asis @orgcmd{M-@key{RET},org-insert-heading} @vindex org-M-RET-may-split-line -Insert new heading with same level as current. If the cursor is in a plain -list item, a new item is created (@pxref{Plain lists}). To force creation of -a new headline, use a prefix argument. When this command is used in the -middle of a line, the line is split and the rest of the line becomes the new -headline@footnote{If you do not want the line to be split, customize the -variable @code{org-M-RET-may-split-line}.}. If the command is used at the -beginning of a headline, the new headline is created before the current line. -If at the beginning of any other line, the content of that line is made the -new heading. If the command is used at the end of a folded subtree (i.e., -behind the ellipses at the end of a headline), then a headline like the -current one will be inserted after the end of the subtree. +Insert a new heading/item with the same level than the one at point. +If the cursor is in a plain list item, a new item is created +(@pxref{Plain lists}). To prevent this behavior in lists, call the +command with a prefix argument. When this command is used in the +middle of a line, the line is split and the rest of the line becomes +the new item or headline@footnote{If you do not want the line to be +split, customize the variable @code{org-M-RET-may-split-line}.}. If +the command is used at the @emph{beginning} of a headline, the new +headline is created before the current line. If the command is used +at the @emph{end} of a folded subtree (i.e., behind the ellipses at +the end of a headline), then a headline will be +inserted after the end of the subtree. Calling this command with +@kbd{C-u C-u} will unconditionally respect the headline's content and +create a new item at the end of the parent subtree. @orgcmd{C-@key{RET},org-insert-heading-respect-content} Just like @kbd{M-@key{RET}}, except when adding a new heading below the current heading, the new heading is placed after the body instead of before @@ -1450,7 +1501,7 @@ headline marker like @samp{****}. @orgcmd{C-y,org-yank} @vindex org-yank-adjusted-subtrees @vindex org-yank-folded-subtrees -Depending on the variables @code{org-yank-adjusted-subtrees} and +Depending on the options @code{org-yank-adjusted-subtrees} and @code{org-yank-folded-subtrees}, Org's internal @code{yank} command will paste subtrees folded and in a clever way, using the same command as @kbd{C-c C-x C-y}. With the default settings, no level adjustment will take place, @@ -1468,7 +1519,7 @@ to create a number of tasks related to a series of lectures to prepare. For more details, see the docstring of the command @code{org-clone-subtree-with-time-shift}. @orgcmd{C-c C-w,org-refile} -Refile entry or region to a different location. @xref{Refiling notes}. +Refile entry or region to a different location. @xref{Refile and copy}. @orgcmd{C-c ^,org-sort} Sort same-level entries. When there is an active region, all entries in the region will be sorted. Otherwise the children of the current headline are @@ -1550,11 +1601,10 @@ Jump to the next sparse tree match in this buffer. Jump to the previous sparse tree match in this buffer. @end table - @noindent @vindex org-agenda-custom-commands For frequently used sparse trees of specific search strings, you can -use the variable @code{org-agenda-custom-commands} to define fast +use the option @code{org-agenda-custom-commands} to define fast keyboard access to specific sparse trees. These commands will then be accessible through the agenda dispatcher (@pxref{Agenda dispatcher}). For example: @@ -1570,15 +1620,15 @@ a sparse tree matching the string @samp{FIXME}. The other sparse tree commands select headings based on TODO keywords, tags, or properties and will be discussed later in this manual. -@kindex C-c C-e v +@kindex C-c C-e C-v @cindex printing sparse trees @cindex visible text, printing To print a sparse tree, you can use the Emacs command @code{ps-print-buffer-with-faces} which does not print invisible parts of the document @footnote{This does not work under XEmacs, because XEmacs uses selective display for outlining, not text properties.}. -Or you can use the command @kbd{C-c C-e v} to export only the visible -part of the document and print the resulting file. +Or you can use @kbd{C-c C-e C-v} to export only the visible part of +the document and print the resulting file. @node Plain lists, Drawers, Sparse trees, Document Structure @section Plain lists @@ -1604,12 +1654,12 @@ is supported, it may be better to not use it for plain list items.} as bullets. @item @vindex org-plain-list-ordered-item-terminator -@vindex org-alphabetical-lists +@vindex org-list-allow-alphabetical @emph{Ordered} list items start with a numeral followed by either a period or a right parenthesis@footnote{You can filter out any of them by configuring @code{org-plain-list-ordered-item-terminator}.}, such as @samp{1.} or @samp{1)}@footnote{You can also get @samp{a.}, @samp{A.}, @samp{a)} and -@samp{A)} by configuring @code{org-alphabetical-lists}. To minimize +@samp{A)} by configuring @code{org-list-allow-alphabetical}. To minimize confusion with normal text, those are limited to one character only. Beyond that limit, bullets will automatically fallback to numbers.}. If you want a list to start with a different value (e.g., 20), start the text of the item @@ -1629,11 +1679,11 @@ line. In particular, if an ordered list reaches number @samp{10.}, then the list. An item ends before the next line that is less or equally indented than its bullet/number. -@vindex org-empty-line-terminates-plain-lists +@vindex org-list-empty-line-terminates-plain-lists A list ends whenever every item has ended, which means before any line less or equally indented than items at top level. It also ends before two blank -lines@footnote{See also @code{org-empty-line-terminates-plain-lists}.}. In -that case, all items are closed. Here is an example: +lines@footnote{See also @code{org-list-empty-line-terminates-plain-lists}.}. +In that case, all items are closed. Here is an example: @example @group @@ -1705,7 +1755,7 @@ one. @table @kbd @kindex M-S-@key{RET} -@item M-S-RET +@item M-S-@key{RET} Insert a new item with a checkbox (@pxref{Checkboxes}). @kindex S-@key{down} @item S-up @@ -1724,7 +1774,7 @@ similar effect. @item M-up @itemx M-down Move the item including subitems up/down@footnote{See -@code{org-liste-use-circular-motion} for a cyclic behavior.} (swap with +@code{org-list-use-circular-motion} for a cyclic behavior.} (swap with previous/next item of same indentation). If the list is ordered, renumbering is automatic. @kindex M-@key{left} @@ -1734,8 +1784,8 @@ is automatic. Decrease/increase the indentation of an item, leaving children alone. @kindex M-S-@key{left} @kindex M-S-@key{right} -@item M-S-left -@itemx M-S-right +@item M-S-@key{left} +@itemx M-S-@key{right} Decrease/increase the indentation of the item, including subitems. Initially, the item tree is selected based on current indentation. When these commands are executed several times in direct succession, the initially @@ -1781,9 +1831,11 @@ This command also cycles bullet styles when the cursor in on the bullet or anywhere in an item line, details depending on @code{org-support-shift-select}. @kindex C-c ^ +@cindex sorting, of plain list @item C-c ^ Sort the plain list. You will be prompted for the sorting method: -numerically, alphabetically, by time, or by custom function. +numerically, alphabetically, by time, by checked status for check lists, +or by a custom function. @end table @node Drawers, Blocks, Plain lists, Document Structure @@ -1797,10 +1849,9 @@ numerically, alphabetically, by time, or by custom function. @kindex C-c C-x d Sometimes you want to keep information associated with an entry, but you normally don't want to see it. For this, Org mode has @emph{drawers}. -Drawers need to be configured with the variable -@code{org-drawers}@footnote{You can define additional drawers on a -per-file basis with a line like @code{#+DRAWERS: HIDDEN STATE}}. Drawers -look like this: +Drawers need to be configured with the option @code{org-drawers}@footnote{You +can define additional drawers on a per-file basis with a line like +@code{#+DRAWERS: HIDDEN STATE}}. Drawers look like this: @example ** This is a headline @@ -1833,6 +1884,12 @@ want to store a quick note in the LOGBOOK drawer, in a similar way to state chan Add a time-stamped note to the LOGBOOK drawer. @end table +@vindex org-export-with-drawers +You can select the name of the drawers which should be exported with +@code{org-export-with-drawers}. In that case, drawer contents will appear in +export output. Property drawers are not affected by this variable and are +never exported. + @node Blocks, Footnotes, Drawers, Document Structure @section Blocks @@ -1842,7 +1899,7 @@ Org mode uses begin...end blocks for various purposes from including source code examples (@pxref{Literal examples}) to capturing time logging information (@pxref{Clocking work time}). These blocks can be folded and unfolded by pressing TAB in the begin line. You can also get all blocks -folded at startup by configuring the variable @code{org-hide-block-startup} +folded at startup by configuring the option @code{org-hide-block-startup} or on a per-file basis by using @cindex @code{hideblocks}, STARTUP keyword @@ -1857,13 +1914,13 @@ or on a per-file basis by using @cindex footnotes Org mode supports the creation of footnotes. In contrast to the -@file{footnote.el} package, Org mode's footnotes are designed for work on a -larger document, not only for one-off documents like emails. The basic -syntax is similar to the one used by @file{footnote.el}, i.e., a footnote is -defined in a paragraph that is started by a footnote marker in square -brackets in column 0, no indentation allowed. If you need a paragraph break -inside a footnote, use the @LaTeX{} idiom @samp{\par}. The footnote reference -is simply the marker in square brackets, inside text. For example: +@file{footnote.el} package, Org mode's footnotes are designed for work on +a larger document, not only for one-off documents like emails. + +A footnote is started by a footnote marker in square brackets in column 0, no +indentation allowed. It ends at the next footnote definition, headline, or +after two consecutive empty lines. The footnote reference is simply the +marker in square brackets, inside text. For example: @example The Org homepage[fn:1] now looks a lot better than it used to. @@ -1913,11 +1970,11 @@ is at a definition, jump to the (first) reference. @vindex org-footnote-define-inline @vindex org-footnote-section @vindex org-footnote-auto-adjust -Otherwise, create a new footnote. Depending on the variable +Otherwise, create a new footnote. Depending on the option @code{org-footnote-define-inline}@footnote{The corresponding in-buffer setting is: @code{#+STARTUP: fninline} or @code{#+STARTUP: nofninline}}, the definition will be placed right into the text as part of the reference, or -separately into the location determined by the variable +separately into the location determined by the option @code{org-footnote-section}. When this command is called with a prefix argument, a menu of additional @@ -1928,17 +1985,16 @@ s @r{Sort the footnote definitions by reference sequence. During editing,} @r{sequence. If you want them sorted, use this command, which will} @r{also move entries according to @code{org-footnote-section}. Automatic} @r{sorting after each insertion/deletion can be configured using the} - @r{variable @code{org-footnote-auto-adjust}.} + @r{option @code{org-footnote-auto-adjust}.} r @r{Renumber the simple @code{fn:N} footnotes. Automatic renumbering} - @r{after each insertion/deletion can be configured using the variable} + @r{after each insertion/deletion can be configured using the option} @r{@code{org-footnote-auto-adjust}.} S @r{Short for first @code{r}, then @code{s} action.} n @r{Normalize the footnotes by collecting all definitions (including} @r{inline definitions) into a special section, and then numbering them} @r{in sequence. The references will then also be numbers. This is} @r{meant to be the final step before finishing a document (e.g., sending} - @r{off an email). The exporters do this automatically, and so could} - @r{something like @code{message-send-hook}.} + @r{off an email).} d @r{Delete the footnote at point, and all definitions of and references} @r{to it.} @end example @@ -1960,7 +2016,7 @@ Footnote labels are also links to the corresponding definition/reference, and you can use the usual commands to follow these links. @end table -@node Orgstruct mode, , Footnotes, Document Structure +@node Orgstruct mode, Org syntax, Footnotes, Document Structure @section The Orgstruct minor mode @cindex Orgstruct mode @cindex minor mode for structure editing @@ -1968,7 +2024,7 @@ you can use the usual commands to follow these links. If you like the intuitive way the Org mode structure editing and list formatting works, you might want to use these commands in other modes like Text mode or Mail mode as well. The minor mode @code{orgstruct-mode} makes -this possible. Toggle the mode with @kbd{M-x orgstruct-mode}, or +this possible. Toggle the mode with @kbd{M-x orgstruct-mode RET}, or turn it on by default, for example in Message mode, with one of: @lisp @@ -1980,10 +2036,42 @@ When this mode is active and the cursor is on a line that looks to Org like a headline or the first line of a list item, most structure editing commands will work, even if the same keys normally have different functionality in the major mode you are using. If the cursor is not in one of those special -lines, Orgstruct mode lurks silently in the shadows. When you use -@code{orgstruct++-mode}, Org will also export indentation and autofill -settings into that mode, and detect item context after the first line of an -item. +lines, Orgstruct mode lurks silently in the shadows. + +When you use @code{orgstruct++-mode}, Org will also export indentation and +autofill settings into that mode, and detect item context after the first +line of an item. + +@vindex orgstruct-heading-prefix-regexp +You can also use Org structure editing to fold and unfold headlines in +@emph{any} file, provided you defined @code{orgstruct-heading-prefix-regexp}: +the regular expression must match the local prefix to use before Org's +headlines. For example, if you set this variable to @code{";; "} in Emacs +Lisp files, you will be able to fold and unfold headlines in Emacs Lisp +commented lines. Some commands like @code{org-demote} are disabled when the +prefix is set, but folding/unfolding will work correctly. + +@node Org syntax, , Orgstruct mode, Document Structure +@section Org syntax +@cindex Org syntax + +A reference document providing a formal description of Org's syntax is +available as @uref{http://orgmode.org/worg/dev/org-syntax.html, a draft on +Worg}, written and maintained by Nicolas Goaziou. It defines Org's core +internal concepts such as @code{headlines}, @code{sections}, @code{affiliated +keywords}, @code{(greater) elements} and @code{objects}. Each part of an Org +file falls into one of the categories above. + +To explore the abstract structure of an Org buffer, run this in a buffer: + +@lisp +M-: (org-element-parse-buffer) RET +@end lisp + +It will output a list containing the buffer's content represented as an +abstract structure. The export engine relies on the information stored in +this list. Most interactive commands (e.g., for structure editing) also +rely on the syntactic meaning of the surrounding context. @node Tables, Hyperlinks, Document Structure, Top @chapter Tables @@ -2046,7 +2134,7 @@ inserting and deleting avoids shifting other fields. Also, when typing @emph{immediately after the cursor was moved into a new field with @kbd{@key{TAB}}, @kbd{S-@key{TAB}} or @kbd{@key{RET}}}, the field is automatically made blank. If this behavior is too -unpredictable for you, configure the variables +unpredictable for you, configure the options @code{org-enable-table-editor} and @code{org-table-auto-blank-field}. @table @kbd @@ -2066,7 +2154,7 @@ table. But it is easier just to start typing, like @tsubheading{Re-aligning and field motion} @orgcmd{C-c C-c,org-table-align} -Re-align the table without moving the cursor. +Re-align the table and don't move to another field. @c @orgcmd{,org-table-next-field} Re-align the table, move to the next field. Creates a new row if @@ -2165,7 +2253,7 @@ be inserted with @kbd{C-y}. @vindex org-table-copy-increment When current field is empty, copy from first non-empty field above. When not empty, copy current field down to next row and move cursor along with it. -Depending on the variable @code{org-table-copy-increment}, integer field +Depending on the option @code{org-table-copy-increment}, integer field values will be incremented during copy. Integers that are too large will not be incremented. Also, a @code{0} prefix argument temporarily disables the increment. This key is also used by shift-selection and related modes @@ -2181,7 +2269,7 @@ window follow the cursor through the table and always show the current field. The follow mode exits automatically when the cursor leaves the table, or when you repeat this command with @kbd{C-u C-u C-c `}. @c -@item M-x org-table-import +@item M-x org-table-import RET Import a file as a table. The table should be TAB or whitespace separated. Use, for example, to import a spreadsheet table or data from a database, because these programs generally can write @@ -2194,12 +2282,12 @@ Tables can also be imported by pasting tabular text into the Org buffer, selecting the pasted text with @kbd{C-x C-x} and then using the @kbd{C-c |} command (see above under @i{Creation and conversion}). @c -@item M-x org-table-export +@item M-x org-table-export RET @findex org-table-export @vindex org-table-export-default-format Export the table, by default as a TAB-separated file. Use for data exchange with, for example, spreadsheet or database programs. The format -used to export the file can be configured in the variable +used to export the file can be configured in the option @code{org-table-export-default-format}. You may also use properties @code{TABLE_EXPORT_FILE} and @code{TABLE_EXPORT_FORMAT} to specify the file name and the format for table export in a subtree. Org supports quite @@ -2274,7 +2362,7 @@ If you would like to overrule the automatic alignment of number-rich columns to the right and of string-rich column to the left, you can use @samp{}, @samp{}@footnote{Centering does not work inside Emacs, but it does have an effect when exporting to HTML.} or @samp{} in a similar fashion. You may -also combine alignment and field width like this: @samp{}. +also combine alignment and field width like this: @samp{}. Lines which only contain these formatting cookies will be removed automatically when exporting the document. @@ -2323,7 +2411,7 @@ every vertical line you would like to have: If you like the intuitive way the Org table editor works, you might also want to use it in other modes like Text mode or Mail mode. The minor mode Orgtbl mode makes this possible. You can always toggle -the mode with @kbd{M-x orgtbl-mode}. To turn it on by default, for +the mode with @kbd{M-x orgtbl-mode RET}. To turn it on by default, for example in Message mode, use @lisp @@ -2359,6 +2447,7 @@ formula, moving these references by arrow keys * Durations and time values:: How to compute durations and time values * Field and range formulas:: Formula for specific (ranges of) fields * Column formulas:: Formulas valid for an entire column +* Lookup functions:: Lookup functions for searching tables * Editing and debugging formulas:: Fixing formulas * Updating the table:: Recomputing all dependent fields * Advanced features:: Field and column names, parameters and automatic recalc @@ -2384,8 +2473,8 @@ combination like @code{B3}, meaning the 2nd field in the 3rd row. @vindex org-table-use-standard-references However, Org prefers@footnote{Org will understand references typed by the user as @samp{B4}, but it will not use this syntax when offering a formula -for editing. You can customize this behavior using the variable -@code{org-table-use-standard-references}.} to use another, more general +for editing. You can customize this behavior using the option +@code{org-table-use-standard-references}.} to use another, more general representation that looks like this: @example @@@var{row}$@var{column} @@ -2452,15 +2541,15 @@ $1..$3 @r{first three fields in the current row} $P..$Q @r{range, using column names (see under Advanced)} $<<<..$>> @r{start in third column, continue to the one but last} @@2$1..@@4$3 @r{6 fields between these two fields (same as @code{A2..C4})} -@@-1$-2..@@-1 @r{in the first row up, 3 fields from 2 columns on the left} +@@-1$-2..@@-1 @r{3 fields in the row above, starting from 2 columns on the left} @@I..II @r{between first and second hline, short for @code{@@I..@@II}} @end example @noindent Range references return a vector of values that can be fed -into Calc vector functions. Empty fields in ranges are normally -suppressed, so that the vector contains only the non-empty fields (but -see the @samp{E} mode switch below). If there are no non-empty fields, -@samp{[0]} is returned to avoid syntax errors in formulas. +into Calc vector functions. Empty fields in ranges are normally suppressed, +so that the vector contains only the non-empty fields. For other options +with the mode switches @samp{E}, @samp{N} and examples @pxref{Formula syntax +for Calc}. @subsubheading Field coordinates in formulas @cindex field coordinates @@ -2493,7 +2582,7 @@ number of rows. @vindex org-table-formula-constants @samp{$name} is interpreted as the name of a column, parameter or -constant. Constants are defined globally through the variable +constant. Constants are defined globally through the option @code{org-table-formula-constants}, and locally (for the file) through a line like @@ -2526,7 +2615,7 @@ numbers. @cindex references, to a different table @cindex name, of column or field @cindex constants, in calculations -@cindex #+TBLNAME +@cindex #+NAME, for table You may also reference constants, fields and ranges from a different table, either in the current file or even in a different file. The syntax is @@ -2537,7 +2626,7 @@ remote(NAME-OR-ID,REF) @noindent where NAME can be the name of a table in the current file as set by a -@code{#+TBLNAME: NAME} line before the table. It can also be the ID of an +@code{#+NAME: Name} line before the table. It can also be the ID of an entry, even in a different file, and the reference then refers to the first table in that entry. REF is an absolute field or range reference as described above for example @code{@@3$3} or @code{$somename}, valid in the @@ -2548,14 +2637,13 @@ referenced table. @cindex formula syntax, Calc @cindex syntax, of formulas -A formula can be any algebraic expression understood by the Emacs -@file{Calc} package. @b{Note that @file{calc} has the -non-standard convention that @samp{/} has lower precedence than -@samp{*}, so that @samp{a/b*c} is interpreted as @samp{a/(b*c)}.} Before -evaluation by @code{calc-eval} (@pxref{Calling Calc from -Your Programs, calc-eval, Calling Calc from Your Lisp Programs, calc, GNU -Emacs Calc Manual}), -variable substitution takes place according to the rules described above. +A formula can be any algebraic expression understood by the Emacs @file{Calc} +package. Note that @file{calc} has the non-standard convention that @samp{/} +has lower precedence than @samp{*}, so that @samp{a/b*c} is interpreted as +@samp{a/(b*c)}. Before evaluation by @code{calc-eval} (@pxref{Calling Calc +from Your Programs, calc-eval, Calling Calc from Your Lisp Programs, calc, +GNU Emacs Calc Manual}), variable substitution takes place according to the +rules described above. @cindex vectors, in table calculations The range vectors can be directly fed into the Calc vector functions like @samp{vmean} and @samp{vsum}. @@ -2568,33 +2656,52 @@ string consists of flags to influence Calc and other modes during execution. By default, Org uses the standard Calc modes (precision 12, angular units degrees, fraction and symbolic modes off). The display format, however, has been changed to @code{(float 8)} to keep tables -compact. The default settings can be configured using the variable +compact. The default settings can be configured using the option @code{org-calc-default-modes}. -@example -p20 @r{set the internal Calc calculation precision to 20 digits} -n3 s3 e2 f4 @r{Normal, scientific, engineering, or fixed} - @r{format of the result of Calc passed back to Org.} - @r{Calc formatting is unlimited in precision as} - @r{long as the Calc calculation precision is greater.} -D R @r{angle modes: degrees, radians} -F S @r{fraction and symbolic modes} -N @r{interpret all fields as numbers, use 0 for non-numbers} -E @r{keep empty fields in ranges} -L @r{literal} -@end example +@noindent List of modes: + +@table @asis +@item @code{p20} +Set the internal Calc calculation precision to 20 digits. +@item @code{n3}, @code{s3}, @code{e2}, @code{f4} +Normal, scientific, engineering or fixed format of the result of Calc passed +back to Org. Calc formatting is unlimited in precision as long as the Calc +calculation precision is greater. +@item @code{D}, @code{R} +Degree and radian angle modes of Calc. +@item @code{F}, @code{S} +Fraction and symbolic modes of Calc. +@item @code{T}, @code{t} +Duration computations in Calc or Lisp, @pxref{Durations and time values}. +@item @code{E} +If and how to consider empty fields. Without @samp{E} empty fields in range +references are suppressed so that the Calc vector or Lisp list contains only +the non-empty fields. With @samp{E} the empty fields are kept. For empty +fields in ranges or empty field references the value @samp{nan} (not a +number) is used in Calc formulas and the empty string is used for Lisp +formulas. Add @samp{N} to use 0 instead for both formula types. For the +value of a field the mode @samp{N} has higher precedence than @samp{E}. +@item @code{N} +Interpret all fields as numbers, use 0 for non-numbers. See the next section +to see how this is essential for computations with Lisp formulas. In Calc +formulas it is used only occasionally because there number strings are +already interpreted as numbers without @samp{N}. +@item @code{L} +Literal, for Lisp formulas only. See the next section. +@end table @noindent -Unless you use large integer numbers or high-precision-calculation -and -display for floating point numbers you may alternatively provide a -@code{printf} format specifier to reformat the Calc result after it has been +Unless you use large integer numbers or high-precision-calculation and +-display for floating point numbers you may alternatively provide a +@samp{printf} format specifier to reformat the Calc result after it has been passed back to Org instead of letting Calc already do the -formatting@footnote{The @code{printf} reformatting is limited in precision -because the value passed to it is converted into an @code{integer} or -@code{double}. The @code{integer} is limited in size by truncating the -signed value to 32 bits. The @code{double} is limited in precision to 64 -bits overall which leaves approximately 16 significant decimal digits.}. -A few examples: +formatting@footnote{The @samp{printf} reformatting is limited in precision +because the value passed to it is converted into an @samp{integer} or +@samp{double}. The @samp{integer} is limited in size by truncating the +signed value to 32 bits. The @samp{double} is limited in precision to 64 +bits overall which leaves approximately 16 significant decimal digits.}. A +few examples: @example $1+$2 @r{Sum of first and second field} @@ -2605,19 +2712,38 @@ $0;%.1f @r{Reformat current cell to 1 decimal} $c/$1/$cm @r{Hz -> cm conversion, using @file{constants.el}} tan($1);Dp3s1 @r{Compute in degrees, precision 3, display SCI 1} sin($1);Dp3%.1e @r{Same, but use printf specifier for display} -vmean($2..$7) @r{Compute column range mean, using vector function} -vmean($2..$7);EN @r{Same, but treat empty fields as 0} taylor($3,x=7,2) @r{Taylor series of $3, at x=7, second degree} @end example -Calc also contains a complete set of logical operations. For example +Calc also contains a complete set of logical operations, (@pxref{Logical +Operations, , Logical Operations, calc, GNU Emacs Calc Manual}). For example -@example -if($1<20,teen,string("")) @r{"teen" if age $1 less than 20, else empty} -@end example +@table @code +@item if($1 < 20, teen, string("")) +"teen" if age $1 is less than 20, else the Org table result field is set to +empty with the empty string. +@item if("$1" == "nan" || "$2" == "nan", string(""), $1 + $2); E +Sum of the first two columns. When at least one of the input fields is empty +the Org table result field is set to empty. +@item if(typeof(vmean($1..$7)) == 12, string(""), vmean($1..$7); E +Mean value of a range unless there is any empty field. Every field in the +range that is empty is replaced by @samp{nan} which lets @samp{vmean} result +in @samp{nan}. Then @samp{typeof == 12} detects the @samp{nan} from +@samp{vmean} and the Org table result field is set to empty. Use this when +the sample set is expected to never have missing values. +@item if("$1..$7" == "[]", string(""), vmean($1..$7)) +Mean value of a range with empty fields skipped. Every field in the range +that is empty is skipped. When all fields in the range are empty the mean +value is not defined and the Org table result field is set to empty. Use +this when the sample set can have a variable size. +@item vmean($1..$7); EN +To complete the example before: Mean value of a range with empty fields +counting as samples with value 0. Use this only when incomplete sample sets +should be padded with 0 to the full size. +@end table -Note that you can also use two org-specific flags @code{T} and @code{t} for -durations computations @ref{Durations and time values}. +You can add your own Calc functions defined in Emacs Lisp with @code{defmath} +and use them in formula syntax for Calc. @node Formula syntax for Lisp, Durations and time values, Formula syntax for Calc, The spreadsheet @subsection Emacs Lisp forms as formulas @@ -2646,14 +2772,14 @@ fields, so you can embed them in list or vector syntax. Here are a few examples---note how the @samp{N} mode is used when we do computations in Lisp: -@example -@r{Swap the first two characters of the content of column 1} - '(concat (substring $1 1 2) (substring $1 0 1) (substring $1 2)) -@r{Add columns 1 and 2, equivalent to Calc's @code{$1+$2}} - '(+ $1 $2);N -@r{Compute the sum of columns 1--4, like Calc's @code{vsum($1..$4)}} - '(apply '+ '($1..$4));N -@end example +@table @code +@item '(concat (substring $1 1 2) (substring $1 0 1) (substring $1 2)) +Swap the first two characters of the content of column 1. +@item '(+ $1 $2);N +Add columns 1 and 2, equivalent to Calc's @code{$1+$2}. +@item '(apply '+ '($1..$4));N +Compute the sum of columns 1 to 4, like Calc's @code{vsum($1..$4)}. +@end table @node Durations and time values, Field and range formulas, Formula syntax for Lisp, The spreadsheet @subsection Durations and time values @@ -2677,7 +2803,7 @@ formulas or Elisp formulas: Input duration values must be of the form @code{[HH:MM[:SS]}, where seconds are optional. With the @code{T} flag, computed durations will be displayed as @code{HH:MM:SS} (see the first formula above). With the @code{t} flag, -computed durations will be displayed according to the value of the variable +computed durations will be displayed according to the value of the option @code{org-table-duration-custom-format}, which defaults to @code{'hours} and will display the result as a fraction of hours (see the second formula in the example above). @@ -2741,7 +2867,7 @@ can also be used to assign a formula to some but not all fields in a row. Named field, see @ref{Advanced features}. @end table -@node Column formulas, Editing and debugging formulas, Field and range formulas, The spreadsheet +@node Column formulas, Lookup functions, Field and range formulas, The spreadsheet @subsection Column formulas @cindex column formula @cindex formula, for table column @@ -2749,10 +2875,13 @@ Named field, see @ref{Advanced features}. When you assign a formula to a simple column reference like @code{$3=}, the same formula will be used in all fields of that column, with the following very convenient exceptions: (i) If the table contains horizontal separator -hlines, everything before the first such line is considered part of the table -@emph{header} and will not be modified by column formulas. (ii) Fields that -already get a value from a field/range formula will be left alone by column -formulas. These conditions make column formulas very easy to use. +hlines with rows above and below, everything before the first such hline is +considered part of the table @emph{header} and will not be modified by column +formulas. Therefore a header is mandatory when you use column formulas and +want to add hlines to group rows, like for example to separate a total row at +the bottom from the summand rows above. (ii) Fields that already get a value +from a field/range formula will be left alone by column formulas. These +conditions make column formulas very easy to use. To assign a formula to a column, type it directly into any field in the column, preceded by an equal sign, like @samp{=$1+$2}. When you press @@ -2777,19 +2906,62 @@ stores it. With a numeric prefix argument(e.g., @kbd{C-5 C-c =}) the command will apply it to that many consecutive fields in the current column. @end table -@node Editing and debugging formulas, Updating the table, Column formulas, The spreadsheet +@node Lookup functions, Editing and debugging formulas, Column formulas, The spreadsheet +@subsection Lookup functions +@cindex lookup functions in tables +@cindex table lookup functions + +Org has three predefined Emacs Lisp functions for lookups in tables. +@table @code +@item (org-lookup-first VAL S-LIST R-LIST &optional PREDICATE) +@findex org-lookup-first +Searches for the first element @code{S} in list @code{S-LIST} for which +@lisp +(PREDICATE VAL S) +@end lisp +is @code{t}; returns the value from the corresponding position in list +@code{R-LIST}. The default @code{PREDICATE} is @code{equal}. Note that the +parameters @code{VAL} and @code{S} are passed to @code{PREDICATE} in the same +order as the corresponding parameters are in the call to +@code{org-lookup-first}, where @code{VAL} precedes @code{S-LIST}. If +@code{R-LIST} is @code{nil}, the matching element @code{S} of @code{S-LIST} +is returned. +@item (org-lookup-last VAL S-LIST R-LIST &optional PREDICATE) +@findex org-lookup-last +Similar to @code{org-lookup-first} above, but searches for the @i{last} +element for which @code{PREDICATE} is @code{t}. +@item (org-lookup-all VAL S-LIST R-LIST &optional PREDICATE) +@findex org-lookup-all +Similar to @code{org-lookup-first}, but searches for @i{all} elements for +which @code{PREDICATE} is @code{t}, and returns @i{all} corresponding +values. This function can not be used by itself in a formula, because it +returns a list of values. However, powerful lookups can be built when this +function is combined with other Emacs Lisp functions. +@end table + +If the ranges used in these functions contain empty fields, the @code{E} mode +for the formula should usually be specified: otherwise empty fields will not be +included in @code{S-LIST} and/or @code{R-LIST} which can, for example, result +in an incorrect mapping from an element of @code{S-LIST} to the corresponding +element of @code{R-LIST}. + +These three functions can be used to implement associative arrays, count +matching cells, rank results, group data etc. For practical examples +see @uref{http://orgmode.org/worg/org-tutorials/org-lookups.html, this +tutorial on Worg}. + +@node Editing and debugging formulas, Updating the table, Lookup functions, The spreadsheet @subsection Editing and debugging formulas @cindex formula editing @cindex editing, of table formulas @vindex org-table-use-standard-references -You can edit individual formulas in the minibuffer or directly in the -field. Org can also prepare a special buffer with all active -formulas of a table. When offering a formula for editing, Org -converts references to the standard format (like @code{B3} or @code{D&}) -if possible. If you prefer to only work with the internal format (like -@code{@@3$2} or @code{$4}), configure the variable -@code{org-table-use-standard-references}. +You can edit individual formulas in the minibuffer or directly in the field. +Org can also prepare a special buffer with all active formulas of a table. +When offering a formula for editing, Org converts references to the standard +format (like @code{B3} or @code{D&}) if possible. If you prefer to only work +with the internal format (like @code{@@3$2} or @code{$4}), configure the +option @code{org-table-use-standard-references}. @table @kbd @orgcmdkkc{C-c =,C-u C-c =,org-table-eval-formula} @@ -2821,6 +2993,7 @@ active formula, the cursor in the formula editor will mark it. While inside the special buffer, Org will automatically highlight any field or range reference at the cursor position. You may edit, remove and add formulas, and use the following commands: + @table @kbd @orgcmdkkc{C-c C-c,C-x C-s,org-table-fedit-finish} Exit the formula editor and store the modified formulas. With @kbd{C-u} @@ -2872,6 +3045,52 @@ You may edit the @samp{#+TBLFM} directly and re-apply the changed equations with @kbd{C-c C-c} in that line or with the normal recalculation commands in the table. +@anchor{Using multiple #+TBLFM lines} +@subsubheading Using multiple #+TBLFM lines +@cindex #+TBLFM line, multiple +@cindex #+TBLFM +@cindex #+TBLFM, switching +@kindex C-c C-c + +You may apply the formula temporarily. This is useful when you +switch the formula. Place multiple @samp{#+TBLFM} lines right +after the table, and then press @kbd{C-c C-c} on the formula to +apply. Here is an example: + +@example +| x | y | +|---+---| +| 1 | | +| 2 | | +#+TBLFM: $2=$1*1 +#+TBLFM: $2=$1*2 +@end example + +@noindent +Pressing @kbd{C-c C-c} in the line of @samp{#+TBLFM: $2=$1*2} yields: + +@example +| x | y | +|---+---| +| 1 | 2 | +| 2 | 4 | +#+TBLFM: $2=$1*1 +#+TBLFM: $2=$1*2 +@end example + +@noindent +Note: If you recalculate this table (with @kbd{C-u C-c *}, for example), you +will get the following result of applying only the first @samp{#+TBLFM} line. + +@example +| x | y | +|---+---| +| 1 | 1 | +| 2 | 2 | +#+TBLFM: $2=$1*1 +#+TBLFM: $2=$1*2 +@end example + @subsubheading Debugging formulas @cindex formula debugging @cindex debugging, of table formulas @@ -2910,10 +3129,10 @@ hline are left alone, assuming that these are part of the table header. Iterate the table by recomputing it until no further changes occur. This may be necessary if some computed fields use the value of other fields that are computed @i{later} in the calculation sequence. -@item M-x org-table-recalculate-buffer-tables +@item M-x org-table-recalculate-buffer-tables RET @findex org-table-recalculate-buffer-tables Recompute all tables in the current buffer. -@item M-x org-table-iterate-buffer-tables +@item M-x org-table-iterate-buffer-tables RET @findex org-table-iterate-buffer-tables Iterate all tables in the current buffer, in order to converge table-to-table dependencies. @@ -2966,6 +3185,7 @@ empty first field. @cindex marking characters, tables The marking characters have the following meaning: + @table @samp @item ! The fields in this line define names for the columns, so that you may @@ -3167,10 +3387,8 @@ internal structure of all links, use the menu entry If the link does not look like a URL, it is considered to be internal in the current file. The most important case is a link like @samp{[[#my-custom-id]]} which will link to the entry with the -@code{CUSTOM_ID} property @samp{my-custom-id}. Such custom IDs are very good -for HTML export (@pxref{HTML export}) where they produce pretty section -links. You are responsible yourself to make sure these custom IDs are unique -in a file. +@code{CUSTOM_ID} property @samp{my-custom-id}. You are responsible yourself +to make sure these custom IDs are unique in a file. Links such as @samp{[[My Target]]} or @samp{[[My Target][Find my target]]} lead to a text search in the current file. @@ -3178,27 +3396,48 @@ lead to a text search in the current file. The link can be followed with @kbd{C-c C-o} when the cursor is on the link, or with a mouse click (@pxref{Handling links}). Links to custom IDs will point to the corresponding headline. The preferred match for a text link is -a @i{dedicated target}: the same string in double angular brackets. Targets -may be located anywhere; sometimes it is convenient to put them into a -comment line. For example +a @i{dedicated target}: the same string in double angular brackets, like +@samp{<>}. + +@cindex #+NAME +If no dedicated target exists, the link will then try to match the exact name +of an element within the buffer. Naming is done with the @code{#+NAME} +keyword, which has to be put the line before the element it refers to, as in +the following example @example -# <> +#+NAME: My Target +| a | table | +|----+------------| +| of | four cells | @end example -@noindent In HTML export (@pxref{HTML export}), such targets will become -named anchors for direct access through @samp{http} links@footnote{Note that -text before the first headline is usually not exported, so the first such -target should be after the first headline, or in the line directly before the -first headline.}. - -If no dedicated target exists, Org will search for a headline that is exactly +If none of the above succeeds, Org will search for a headline that is exactly the link text but may also include a TODO keyword and tags@footnote{To insert -a link targeting a headline, in-buffer completion can be used. Just type a -star followed by a few optional letters into the buffer and press +a link targeting a headline, in-buffer completion can be used. Just type +a star followed by a few optional letters into the buffer and press @kbd{M-@key{TAB}}. All headlines in the current buffer will be offered as -completions.}. In non-Org files, the search will look for the words in the -link text. In the above example the search would be for @samp{my target}. +completions.}. + +During export, internal links will be used to mark objects and assign them +a number. Marked objects will then be referenced by links pointing to them. +In particular, links without a description will appear as the number assigned +to the marked object@footnote{When targeting a @code{#+NAME} keyword, +@code{#+CAPTION} keyword is mandatory in order to get proper numbering +(@pxref{Images and tables}).}. In the following excerpt from an Org buffer + +@example +- one item +- <>another item +Here we refer to item [[target]]. +@end example + +@noindent +The last sentence will appear as @samp{Here we refer to item 2} when +exported. + +In non-Org files, the search will look for the words in the link text. In +the above example the search would be for @samp{my target}. Following a link pushes a mark onto Org's own mark ring. You can return to the previous position with @kbd{C-c &}. Using this command @@ -3229,26 +3468,23 @@ cursor on or at a target. @section External links @cindex links, external @cindex external links -@cindex links, external @cindex Gnus links @cindex BBDB links @cindex IRC links @cindex URL links @cindex file links -@cindex VM links @cindex RMAIL links -@cindex WANDERLUST links @cindex MH-E links @cindex USENET links @cindex SHELL links @cindex Info links @cindex Elisp links -Org supports links to files, websites, Usenet and email messages, -BBDB database entries and links to both IRC conversations and their -logs. External links are URL-like locators. They start with a short -identifying string followed by a colon. There can be no space after -the colon. The following list shows examples for each link type. +Org supports links to files, websites, Usenet and email messages, BBDB +database entries and links to both IRC conversations and their logs. +External links are URL-like locators. They start with a short identifying +string followed by a colon. There can be no space after the colon. The +following list shows examples for each link type. @example http://www.astro.uva.nl/~dominik @r{on the web} @@ -3263,8 +3499,8 @@ file:sometextfile::NNN @r{file, jump to line number} file:projects.org @r{another Org file} file:projects.org::some words @r{text search in Org file}@footnote{ The actual behavior of the search will depend on the value of -the variable @code{org-link-search-must-match-exact-headline}. If its value -is nil, then a fuzzy text search will be done. If it is t, then only the +the option @code{org-link-search-must-match-exact-headline}. If its value +is @code{nil}, then a fuzzy text search will be done. If it is t, then only the exact headline will be matched. If the value is @code{'query-to-create}, then an exact headline will be searched; if it is not found, then the user will be queried to create it.} @@ -3275,13 +3511,6 @@ docview:papers/last.pdf::NNN @r{open in doc-view mode at page} id:B7423F4D-2E8A-471B-8810-C40F074717E9 @r{Link to heading by ID} news:comp.emacs @r{Usenet link} mailto:adent@@galaxy.net @r{Mail link} -vm:folder @r{VM folder link} -vm:folder#id @r{VM message link} -vm://myself@@some.where.org/folder#id @r{VM on remote machine} -vm-imap:account:folder @r{VM IMAP folder link} -vm-imap:account:folder#id @r{VM IMAP message link} -wl:folder @r{WANDERLUST folder link} -wl:folder#id @r{WANDERLUST message link} mhe:folder @r{MH-E folder link} mhe:folder#id @r{MH-E message link} rmail:folder @r{RMAIL folder link} @@ -3296,11 +3525,27 @@ elisp:org-agenda @r{Interactive Elisp command} elisp:(find-file-other-frame "Elisp.org") @r{Elisp form to evaluate} @end example +@cindex VM links +@cindex WANDERLUST links +On top of these built-in link types, some are available through the +@code{contrib/} directory (@pxref{Installation}). For example, these links +to VM or Wanderlust messages are available when you load the corresponding +libraries from the @code{contrib/} directory: + +@example +vm:folder @r{VM folder link} +vm:folder#id @r{VM message link} +vm://myself@@some.where.org/folder#id @r{VM on remote machine} +vm-imap:account:folder @r{VM IMAP folder link} +vm-imap:account:folder#id @r{VM IMAP message link} +wl:folder @r{WANDERLUST folder link} +wl:folder#id @r{WANDERLUST message link} +@end example + For customizing Org to add new link types @ref{Adding hyperlink types}. -A link should be enclosed in double brackets and may contain a -descriptive text to be displayed instead of the URL (@pxref{Link -format}), for example: +A link should be enclosed in double brackets and may contain a descriptive +text to be displayed instead of the URL (@pxref{Link format}), for example: @example [[http://www.gnu.org/software/emacs/][GNU Emacs]] @@ -3349,14 +3594,13 @@ timestamp in the headline.}. If the headline has a @code{CUSTOM_ID} property, a link to this custom ID will be stored. In addition or alternatively (depending on the value of @code{org-id-link-to-org-use-id}), a globally unique @code{ID} property will -be created and/or used to construct a link@footnote{The library @code{org-id} -must first be loaded, either through @code{org-customize} by enabling -@code{id} in @code{org-modules} , or by adding @code{(require 'org-id)} in -your @file{.emacs}.}. So using this command in Org -buffers will potentially create two links: a human-readable from the custom -ID, and one that is globally unique and works even if the entry is moved from -file to file. Later, when inserting the link, you need to decide which one -to use. +be created and/or used to construct a link@footnote{The library +@file{org-id.el} must first be loaded, either through @code{org-customize} by +enabling @code{org-id} in @code{org-modules}, or by adding @code{(require +'org-id)} in your @file{.emacs}.}. So using this command in Org buffers will +potentially create two links: a human-readable from the custom ID, and one +that is globally unique and works even if the entry is moved from file to +file. Later, when inserting the link, you need to decide which one to use. @b{Email/News clients: VM, Rmail, Wanderlust, MH-E, Gnus}@* Pretty much all Emacs mail clients are supported. The link will point to the @@ -3371,10 +3615,10 @@ Links created in a BBDB buffer will point to the current entry. @b{Chat: IRC}@* @vindex org-irc-link-to-logs -For IRC links, if you set the variable @code{org-irc-link-to-logs} to -@code{t}, a @samp{file:/} style link to the relevant point in the logs for -the current conversation is created. Otherwise an @samp{irc:/} style link to -the user/channel/server under the point will be stored. +For IRC links, if you set the option @code{org-irc-link-to-logs} to @code{t}, +a @samp{file:/} style link to the relevant point in the logs for the current +conversation is created. Otherwise an @samp{irc:/} style link to the +user/channel/server under the point will be stored. @b{Other files}@* For any other files, the link will point to the file, with a search string @@ -3476,7 +3720,7 @@ would. Under Emacs 22 and later, @kbd{mouse-1} will also follow a link. @vindex org-display-internal-link-with-indirect-buffer Like @kbd{mouse-2}, but force file links to be opened with Emacs, and internal links to be displayed in another window@footnote{See the -variable @code{org-display-internal-link-with-indirect-buffer}}. +option @code{org-display-internal-link-with-indirect-buffer}}. @c @orgcmd{C-c C-x C-v,org-toggle-inline-images} @cindex inlining images @@ -3490,7 +3734,7 @@ be inlined during export. When called with a prefix argument, also display images that do have a link description. You can ask for inline images to be displayed at startup by configuring the variable @code{org-startup-with-inline-images}@footnote{with corresponding -@code{#+STARTUP} keywords @code{inlineimages} and @code{inlineimages}}. +@code{#+STARTUP} keywords @code{inlineimages} and @code{noinlineimages}}. @orgcmd{C-c %,org-mark-ring-push} @cindex mark ring Push the current position onto the mark ring, to be able to return @@ -3728,7 +3972,7 @@ Rotate the TODO state of the current item among If TODO keywords have fast access keys (see @ref{Fast access to TODO states}), you will be prompted for a TODO keyword through the fast selection interface; this is the default behavior when -@var{org-use-fast-todo-selection} is @code{non-nil}. +@code{org-use-fast-todo-selection} is non-@code{nil}. The same rotation can also be done ``remotely'' from the timeline and agenda buffers with the @kbd{t} command key (@pxref{Agenda commands}). @@ -3736,7 +3980,7 @@ buffers with the @kbd{t} command key (@pxref{Agenda commands}). @orgkey{C-u C-c C-t} When TODO keywords have no selection keys, select a specific keyword using completion; otherwise force cycling through TODO states with no prompt. When -@var{org-use-fast-todo-selection} is set to @code{prefix}, use the fast +@code{org-use-fast-todo-selection} is set to @code{prefix}, use the fast selection interface. @kindex S-@key{right} @@ -3754,12 +3998,11 @@ with @code{shift-selection-mode}. See also the variable View TODO items in a @emph{sparse tree} (@pxref{Sparse trees}). Folds the entire buffer, but shows all TODO items (with not-DONE state) and the headings hierarchy above them. With a prefix argument (or by using @kbd{C-c -/ T}), search for a specific TODO@. You will be prompted for the keyword, and -you can also give a list of keywords like @code{KWD1|KWD2|...} to list +/ T}), search for a specific TODO@. You will be prompted for the keyword, +and you can also give a list of keywords like @code{KWD1|KWD2|...} to list entries that match any one of these keywords. With a numeric prefix argument -N, show the tree for the Nth keyword in the variable -@code{org-todo-keywords}. With two prefix arguments, find all TODO states, -both un-done and done. +N, show the tree for the Nth keyword in the option @code{org-todo-keywords}. +With two prefix arguments, find all TODO states, both un-done and done. @orgcmd{C-c a t,org-todo-list} Show the global TODO list. Collects the TODO items (with not-DONE states) from all agenda files (@pxref{Agenda Views}) into a single buffer. The new @@ -3930,7 +4173,7 @@ each keyword, in parentheses@footnote{All characters are allowed except @vindex org-fast-tag-selection-include-todo If you then press @kbd{C-c C-t} followed by the selection key, the entry will be switched to this state. @kbd{SPC} can be used to remove any TODO -keyword from an entry.@footnote{Check also the variable +keyword from an entry.@footnote{Check also the option @code{org-fast-tag-selection-include-todo}, it allows you to change the TODO state through the tags interface (@pxref{Setting tags}), in case you like to mingle the two concepts. Note that this means you need to come up with @@ -3994,7 +4237,7 @@ Org mode highlights TODO keywords with special faces: @code{org-todo} for keywords indicating that an item still has to be acted upon, and @code{org-done} for keywords indicating that an item is finished. If you are using more than 2 different states, you might want to use -special faces for some of them. This can be done using the variable +special faces for some of them. This can be done using the option @code{org-todo-keyword-faces}. For example: @lisp @@ -4007,7 +4250,7 @@ special faces for some of them. This can be done using the variable While using a list with face properties as shown for CANCELED @emph{should} work, this does not always seem to be the case. If necessary, define a -special face and use that. A string is interpreted as a color. The variable +special face and use that. A string is interpreted as a color. The option @code{org-faces-easy-properties} determines if that color is interpreted as a foreground or a background color. @@ -4023,7 +4266,7 @@ dependencies. Usually, a parent TODO task should not be marked DONE until all subtasks (defined as children tasks) are marked as DONE@. And sometimes there is a logical sequence to a number of (sub)tasks, so that one task cannot be acted upon before all siblings above it are done. If you customize -the variable @code{org-enforce-todo-dependencies}, Org will block entries +the option @code{org-enforce-todo-dependencies}, Org will block entries from changing state to DONE while they have children that are not DONE@. Furthermore, if an entry has a property @code{ORDERED}, each of its children will be blocked until all earlier siblings are marked DONE@. Here is an @@ -4050,21 +4293,21 @@ example: Toggle the @code{ORDERED} property of the current entry. A property is used for this behavior because this should be local to the current entry, not inherited like a tag. However, if you would like to @i{track} the value of -this property with a tag for better visibility, customize the variable +this property with a tag for better visibility, customize the option @code{org-track-ordered-property-with-tag}. @orgkey{C-u C-u C-u C-c C-t} Change TODO state, circumventing any state blocking. @end table @vindex org-agenda-dim-blocked-tasks -If you set the variable @code{org-agenda-dim-blocked-tasks}, TODO entries +If you set the option @code{org-agenda-dim-blocked-tasks}, TODO entries that cannot be closed because of such dependencies will be shown in a dimmed font or even made invisible in agenda views (@pxref{Agenda Views}). @cindex checkboxes and TODO dependencies @vindex org-enforce-todo-dependencies You can also block changes of TODO states by looking at checkboxes -(@pxref{Checkboxes}). If you set the variable +(@pxref{Checkboxes}). If you set the option @code{org-enforce-todo-checkbox-dependencies}, an entry that has unchecked checkboxes will be blocked from switching to DONE. @@ -4102,13 +4345,17 @@ in-buffer setting is: @code{#+STARTUP: logdone}} (setq org-log-done 'time) @end lisp +@vindex org-closed-keep-when-no-todo @noindent -Then each time you turn an entry from a TODO (not-done) state into any -of the DONE states, a line @samp{CLOSED: [timestamp]} will be inserted -just after the headline. If you turn the entry back into a TODO item -through further state cycling, that line will be removed again. If you -want to record a note along with the timestamp, use@footnote{The -corresponding in-buffer setting is: @code{#+STARTUP: lognotedone}} +Then each time you turn an entry from a TODO (not-done) state into any of the +DONE states, a line @samp{CLOSED: [timestamp]} will be inserted just after +the headline. If you turn the entry back into a TODO item through further +state cycling, that line will be removed again. If you turn the entry back +to a non-TODO state (by pressing @key{C-c C-t SPC} for example), that line +will also be removed, unless you set @code{org-closed-keep-when-no-todo} to +non-@code{nil}. If you want to record a note along with the timestamp, +use@footnote{The corresponding in-buffer setting is: @code{#+STARTUP: +lognotedone}.} @lisp (setq org-log-done 'note) @@ -4134,11 +4381,11 @@ When TODO keywords are used as workflow states (@pxref{Workflow states}), you might want to keep track of when a state change occurred and maybe take a note about this change. You can either record just a timestamp, or a time-stamped note for a change. These records will be inserted after the -headline as an itemized list, newest first@footnote{See the variable +headline as an itemized list, newest first@footnote{See the option @code{org-log-states-order-reversed}}. When taking a lot of notes, you might want to get the notes out of the way into a drawer (@pxref{Drawers}). -Customize the variable @code{org-log-into-drawer} to get this behavior---the -recommended drawer for this is called @code{LOGBOOK}@footnote{Note that the +Customize @code{org-log-into-drawer} to get this behavior---the recommended +drawer for this is called @code{LOGBOOK}@footnote{Note that the @code{LOGBOOK} drawer is unfolded when pressing @key{SPC} in the agenda to show an entry---use @key{C-u SPC} to keep it folded here}. You can also overrule the setting of this variable for a subtree by setting a @@ -4186,7 +4433,7 @@ to a buffer: @cindex property, LOGGING In order to define logging settings that are local to a subtree or a single item, define a LOGGING property in this entry. Any non-empty -LOGGING property resets all logging settings to nil. You may then turn +LOGGING property resets all logging settings to @code{nil}. You may then turn on logging for this specific tree using STARTUP keywords like @code{lognotedone} or @code{logrepeat}, as well as adding state specific settings like @code{TODO(!)}. For example @@ -4215,8 +4462,7 @@ called ``habits''. A habit has the following properties: @enumerate @item -You have enabled the @code{habits} module by customizing the variable -@code{org-modules}. +You have enabled the @code{habits} module by customizing @code{org-modules}. @item The habit is a TODO item, with a TODO keyword representing an open state. @item @@ -4298,7 +4544,7 @@ The amount of history, in days before today, to appear in consistency graphs. @item org-habit-following-days The number of days after today that will appear in consistency graphs. @item org-habit-show-habits-only-for-today -If non-nil, only show habits in today's agenda view. This is set to true by +If non-@code{nil}, only show habits in today's agenda view. This is set to true by default. @end table @@ -4326,7 +4572,7 @@ By default, Org mode supports three priorities: @samp{A}, @samp{B}, and treated just like priority @samp{B}. Priorities make a difference only for sorting in the agenda (@pxref{Weekly/daily agenda}); outside the agenda, they have no inherent meaning to Org mode. The cookies can be highlighted with -special faces by customizing the variable @code{org-priority-faces}. +special faces by customizing @code{org-priority-faces}. Priorities can be attached to any outline node; they do not need to be TODO items. @@ -4353,7 +4599,7 @@ also used to modify timestamps (@pxref{Creating timestamps}). See also @vindex org-highest-priority @vindex org-lowest-priority @vindex org-default-priority -You can change the range of allowed priorities by setting the variables +You can change the range of allowed priorities by setting the options @code{org-highest-priority}, @code{org-lowest-priority}, and @code{org-default-priority}. For an individual buffer, you may set these values (highest, lowest, default) like this (please make sure that @@ -4397,7 +4643,7 @@ this issue. @vindex org-hierarchical-todo-statistics If you would like to have the statistics cookie count any TODO entries in the -subtree (not just direct children), configure the variable +subtree (not just direct children), configure @code{org-hierarchical-todo-statistics}. To do this for a single subtree, include the word @samp{recursive} into the value of the @code{COOKIE_DATA} property. @@ -4462,15 +4708,15 @@ checked. @cindex statistics, for checkboxes @cindex checkbox statistics @cindex property, COOKIE_DATA -@vindex org-hierarchical-checkbox-statistics +@vindex org-checkbox-hierarchical-statistics The @samp{[2/4]} and @samp{[1/3]} in the first and second line are cookies indicating how many checkboxes present in this entry have been checked off, and the total number of checkboxes present. This can give you an idea on how many checkboxes remain, even without opening a folded entry. The cookies can be placed into a headline or into (the first line of) a plain list item. Each cookie covers checkboxes of direct children structurally below the -headline/item on which the cookie appears@footnote{Set the variable -@code{org-hierarchical-checkbox-statistics} if you want such cookies to +headline/item on which the cookie appears@footnote{Set the option +@code{org-checkbox-hierarchical-statistics} if you want such cookies to count all checkboxes below the cookie, not just those belonging to direct children.}. You have to insert the cookie yourself by typing either @samp{[/]} or @samp{[%]}. With @samp{[/]} you get an @samp{n out of m} @@ -4522,8 +4768,7 @@ Toggle the @code{ORDERED} property of the entry, to toggle if checkboxes must be checked off in sequence. A property is used for this behavior because this should be local to the current entry, not inherited like a tag. However, if you would like to @i{track} the value of this property with a tag -for better visibility, customize the variable -@code{org-track-ordered-property-with-tag}. +for better visibility, customize @code{org-track-ordered-property-with-tag}. @orgcmd{C-c #,org-update-statistics-cookies} Update the statistics cookie in the current outline entry. When called with a @kbd{C-u} prefix, update the entire file. Checkbox statistic cookies are @@ -4550,13 +4795,14 @@ headline. Tags are normal words containing letters, numbers, @samp{_}, and @samp{@@}. Tags must be preceded and followed by a single colon, e.g., @samp{:work:}. Several tags can be specified, as in @samp{:work:urgent:}. Tags will by default be in bold face with the same color as the headline. -You may specify special faces for specific tags using the variable +You may specify special faces for specific tags using the option @code{org-tag-faces}, in much the same way as you can for TODO keywords (@pxref{Faces for TODO keywords}). @menu * Tag inheritance:: Tags use the tree structure of the outline * Setting tags:: How to assign tags to a headline +* Tag groups:: Use one tag to search for several tags * Tag searches:: Searching for combinations of tags @end menu @@ -4602,8 +4848,8 @@ on, all the sublevels in the same tree will (for a simple match form) match as well@footnote{This is only true if the search does not involve more complex tests including properties (@pxref{Property searches}).}. The list of matches may then become very long. If you only want to see the first tags -match in a subtree, configure the variable -@code{org-tags-match-list-sublevels} (not recommended). +match in a subtree, configure @code{org-tags-match-list-sublevels} (not +recommended). @vindex org-agenda-use-tag-inheritance Tag inheritance is relevant when the agenda search tries to match a tag, @@ -4611,10 +4857,10 @@ either in the @code{tags} or @code{tags-todo} agenda types. In other agenda types, @code{org-use-tag-inheritance} has no effect. Still, you may want to have your tags correctly set in the agenda, so that tag filtering works fine, with inherited tags. Set @code{org-agenda-use-tag-inheritance} to control -this: the default value includes all agenda types, but setting this to nil +this: the default value includes all agenda types, but setting this to @code{nil} can really speed up agenda generation. -@node Setting tags, Tag searches, Tag inheritance, Tags +@node Setting tags, Tag groups, Tag inheritance, Tags @section Setting tags @cindex setting tags @cindex tags, setting @@ -4635,6 +4881,7 @@ to @code{org-tags-column}. When called with a @kbd{C-u} prefix, all tags in the current buffer will be aligned to that column, just to make things look nice. TAGS are automatically realigned after promotion, demotion, and TODO state changes (@pxref{TODO basics}). + @orgcmd{C-c C-c,org-set-tags-command} When the cursor is in a headline, this does the same as @kbd{C-c C-q}. @end table @@ -4722,7 +4969,7 @@ and @samp{@@tennisclub} should be selected. Multiple such groups are allowed. these lines to activate any changes. @noindent -To set these mutually exclusive groups in the variable @code{org-tags-alist}, +To set these mutually exclusive groups in the variable @code{org-tag-alist}, you must use the dummy tags @code{:startgroup} and @code{:endgroup} instead of the braces. Similarly, you can use @code{:newline} to indicate a line break. The previous example would be set globally by the following @@ -4785,17 +5032,58 @@ alternatively with @kbd{C-c C-c C-c w}. Adding the non-predefined tag @vindex org-fast-tag-selection-single-key If you find that most of the time you need only a single key press to -modify your list of tags, set the variable -@code{org-fast-tag-selection-single-key}. Then you no longer have to -press @key{RET} to exit fast tag selection---it will immediately exit -after the first change. If you then occasionally need more keys, press -@kbd{C-c} to turn off auto-exit for the current tag selection process -(in effect: start selection with @kbd{C-c C-c C-c} instead of @kbd{C-c -C-c}). If you set the variable to the value @code{expert}, the special -window is not even shown for single-key tag selection, it comes up only -when you press an extra @kbd{C-c}. - -@node Tag searches, , Setting tags, Tags +modify your list of tags, set @code{org-fast-tag-selection-single-key}. +Then you no longer have to press @key{RET} to exit fast tag selection---it +will immediately exit after the first change. If you then occasionally +need more keys, press @kbd{C-c} to turn off auto-exit for the current tag +selection process (in effect: start selection with @kbd{C-c C-c C-c} +instead of @kbd{C-c C-c}). If you set the variable to the value +@code{expert}, the special window is not even shown for single-key tag +selection, it comes up only when you press an extra @kbd{C-c}. + +@node Tag groups, Tag searches, Setting tags, Tags +@section Tag groups + +@cindex group tags +@cindex tags, groups +In a set of mutually exclusive tags, the first tag can be defined as a +@emph{group tag}. When you search for a group tag, it will return matches +for all members in the group. In an agenda view, filtering by a group tag +will display headlines tagged with at least one of the members of the +group. This makes tag searches and filters even more flexible. + +You can set group tags by inserting a colon between the group tag and other +tags---beware that all whitespaces are mandatory so that Org can parse this +line correctly: + +@example +#+TAGS: @{ @@read : @@read_book @@read_ebook @} +@end example + +In this example, @samp{@@read} is a @emph{group tag} for a set of three +tags: @samp{@@read}, @samp{@@read_book} and @samp{@@read_ebook}. + +You can also use the @code{:grouptags} keyword directly when setting +@code{org-tag-alist}: + +@lisp +(setq org-tag-alist '((:startgroup . nil) + ("@@read" . nil) + (:grouptags . nil) + ("@@read_book" . nil) + ("@@read_ebook" . nil) + (:endgroup . nil))) +@end lisp + +You cannot nest group tags or use a group tag as a tag in another group. + +@kindex C-c C-x q +@vindex org-group-tags +If you want to ignore group tags temporarily, toggle group tags support +with @command{org-toggle-tags-groups}, bound to @kbd{C-c C-x q}. If you +want to disable tag groups completely, set @code{org-group-tags} to @code{nil}. + +@node Tag searches, , Tag groups, Tags @section Tag searches @cindex tag searches @cindex searching for tags @@ -4805,15 +5093,16 @@ information into special lists. @table @kbd @orgcmdkkc{C-c / m,C-c \\,org-match-sparse-tree} -Create a sparse tree with all headlines matching a tags search. With a -@kbd{C-u} prefix argument, ignore headlines that are not a TODO line. -@orgcmd{C-c a m,org-tags-view} -Create a global list of tag matches from all agenda files. +Create a sparse tree with all headlines matching a tags/property/TODO search. +With a @kbd{C-u} prefix argument, ignore headlines that are not a TODO line. @xref{Matching tags and properties}. +@orgcmd{C-c a m,org-tags-view} +Create a global list of tag matches from all agenda files. @xref{Matching +tags and properties}. @orgcmd{C-c a M,org-tags-view} @vindex org-tags-match-list-sublevels Create a global list of tag matches from all agenda files, but check -only TODO items and force checking subitems (see variable +only TODO items and force checking subitems (see the option @code{org-tags-match-list-sublevels}). @end table @@ -4908,6 +5197,9 @@ file, use a line like #+PROPERTY: NDisks_ALL 1 2 3 4 @end example +Contrary to properties set from a special drawer, you have to refresh the +buffer with @kbd{C-c C-c} to activate this changes. + If you want to add to the value of an existing property, append a @code{+} to the property name. The following results in the property @code{var} having the value ``foo=1 bar=2''. @@ -4954,7 +5246,7 @@ in the current file will be offered as possible completions. @orgcmd{C-c C-x p,org-set-property} Set a property. This prompts for a property name and a value. If necessary, the property drawer is created as well. -@item C-u M-x org-insert-drawer +@item C-u M-x org-insert-drawer RET @cindex org-insert-drawer Insert a property drawer into the current entry. The drawer will be inserted early in the entry, but after the lines with planning @@ -5033,6 +5325,7 @@ FILE @r{The filename the entry is located in.} To create sparse trees and special lists with selection based on properties, the same commands are used as for tag searches (@pxref{Tag searches}). + @table @kbd @orgcmdkkc{C-c / m,C-c \\,org-match-sparse-tree} Create a sparse tree with all matching entries. With a @@ -5043,7 +5336,7 @@ Create a global list of tag/property matches from all agenda files. @orgcmd{C-c a M,org-tags-view} @vindex org-tags-match-list-sublevels Create a global list of tag matches from all agenda files, but check -only TODO items and force checking of subitems (see variable +only TODO items and force checking of subitems (see the option @code{org-tags-match-list-sublevels}). @end table @@ -5077,7 +5370,7 @@ useful, you can turn it on by setting the variable @code{org-use-property-inheritance}. It may be set to @code{t} to make all properties inherited from the parent, to a list of properties that should be inherited, or to a regular expression that matches -inherited properties. If a property has the value @samp{nil}, this is +inherited properties. If a property has the value @code{nil}, this is interpreted as an explicit undefine of the property, so that inheritance search will stop at this value and return @code{nil}. @@ -5351,7 +5644,7 @@ global @r{make a global view, including all headings in the file} @r{run column view at the top of this file} "@var{ID}" @r{call column view in the tree that has an @code{:ID:}} @r{property with the value @i{label}. You can use} - @r{@kbd{M-x org-id-copy} to create a globally unique ID for} + @r{@kbd{M-x org-id-copy RET} to create a globally unique ID for} @r{the current entry and copy it to the kill-ring.} @end example @item :hlines @@ -5604,10 +5897,9 @@ the following column). @vindex org-read-date-prefer-future When Org mode prompts for a date/time, the default is shown in default date/time format, and the prompt therefore seems to ask for a specific -format. But it will in fact accept any string containing some date and/or -time information, and it is really smart about interpreting your input. You -can, for example, use @kbd{C-y} to paste a (possibly multi-line) string -copied from an email message. Org mode will find whatever information is in +format. But it will in fact accept date/time information in a variety of +formats. Generally, the information should start at the beginning of the +string. Org mode will find whatever information is in there and derive anything you have not specified from the @emph{default date and time}. The default is usually the current date and time, but when modifying an existing timestamp, or when entering the second stamp of a @@ -5630,7 +5922,7 @@ in @b{bold}. 14 @result{} @b{2006}-@b{06}-14 12 @result{} @b{2006}-@b{07}-12 2/5 @result{} @b{2007}-02-05 -Fri @result{} nearest Friday (default date or later) +Fri @result{} nearest Friday after the default date sep 15 @result{} @b{2006}-09-15 feb 15 @result{} @b{2007}-02-15 sep 12 9 @result{} 2009-09-12 @@ -5641,13 +5933,12 @@ w4 @result{} ISO week for of the current year @b{2006} 2012-w04-5 @result{} Same as above @end example -Furthermore you can specify a relative date by giving, as the -@emph{first} thing in the input: a plus/minus sign, a number and a -letter ([dwmy]) to indicate change in days, weeks, months, or years. With a -single plus or minus, the date is always relative to today. With a -double plus or minus, it is relative to the default date. If instead of -a single letter, you use the abbreviation of day name, the date will be -the Nth such day, e.g.: +Furthermore you can specify a relative date by giving, as the @emph{first} +thing in the input: a plus/minus sign, a number and a letter ([hdwmy]) to +indicate change in hours, days, weeks, months, or years. With a single plus +or minus, the date is always relative to today. With a double plus or minus, +it is relative to the default date. If instead of a single letter, you use +the abbreviation of day name, the date will be the Nth such day, e.g.: @example +0 @result{} today @@ -5656,7 +5947,8 @@ the Nth such day, e.g.: +4 @result{} same as above +2w @result{} two weeks from today ++5 @result{} five days from default date -+2tue @result{} second Tuesday from now. ++2tue @result{} second Tuesday from now +-wed @result{} last Wednesday @end example @vindex parse-time-months @@ -5720,7 +6012,7 @@ The actions of the date/time prompt may seem complex, but I assure you they will grow on you, and you will start getting annoyed by pretty much any other way of entering a date/time out there. To help you understand what is going on, the current interpretation of your input will be displayed live in the -minibuffer@footnote{If you find this distracting, turn the display of with +minibuffer@footnote{If you find this distracting, turn the display off with @code{org-read-date-display-live}.}. @node Custom time format, , The date/time prompt, Creating timestamps @@ -5734,7 +6026,7 @@ minibuffer@footnote{If you find this distracting, turn the display of with Org mode uses the standard ISO notation for dates and times as it is defined in ISO 8601. If you cannot get used to this and require another representation of date and time to keep you happy, you can get it by -customizing the variables @code{org-display-custom-times} and +customizing the options @code{org-display-custom-times} and @code{org-time-stamp-custom-formats}. @table @kbd @@ -5784,6 +6076,7 @@ Meaning: the task (most likely a TODO item, though not necessarily) is supposed to be finished on that date. @vindex org-deadline-warning-days +@vindex org-agenda-skip-deadline-prewarning-if-scheduled On the deadline date, the task will be listed in the agenda. In addition, the agenda for @emph{today} will carry a warning about the approaching or missed deadline, starting @@ -5798,7 +6091,9 @@ until the entry is marked DONE@. An example: You can specify a different lead time for warnings for a specific deadlines using the following syntax. Here is an example with a warning -period of 5 days @code{DEADLINE: <2004-02-29 Sun -5d>}. +period of 5 days @code{DEADLINE: <2004-02-29 Sun -5d>}. This warning is +deactivated if the task get scheduled and you set +@code{org-agenda-skip-deadline-prewarning-if-scheduled} to @code{t}. @item SCHEDULED @cindex SCHEDULED keyword @@ -5819,6 +6114,17 @@ the task will automatically be forwarded until completed. SCHEDULED: <2004-12-25 Sat> @end example +@vindex org-scheduled-delay-days +@vindex org-agenda-skip-scheduled-delay-if-deadline +If you want to @emph{delay} the display of this task in the agenda, use +@code{SCHEDULED: <2004-12-25 Sat -2d>}: the task is still scheduled on the +25th but will appear two days later. In case the task contains a repeater, +the delay is considered to affect all occurrences; if you want the delay to +only affect the first scheduled occurrence of the task, use @code{--2d} +instead. See @code{org-scheduled-delay-days} and +@code{org-agenda-skip-scheduled-delay-if-deadline} for details on how to +control this globally or per agenda. + @noindent @b{Important:} Scheduling an item in Org mode should @i{not} be understood in the same way that we understand @i{scheduling a meeting}. @@ -5979,8 +6285,14 @@ special repeaters @samp{++} and @samp{.+}. For example: today. @end example -You may have both scheduling and deadline information for a specific -task---just make sure that the repeater intervals on both are the same. +@vindex org-agenda-skip-scheduled-if-deadline-is-shown +You may have both scheduling and deadline information for a specific task. +If the repeater is set for the scheduling information only, you probably want +the repeater to be ignored after the deadline. If so, set the variable +@code{org-agenda-skip-scheduled-if-deadline-is-shown} to +@code{repeated-after-deadline}. If you want both scheduling and deadline +information to repeat after the same interval, set the same repeater for both +timestamps. An alternative to using a repeater is to create a number of copies of a task subtree, with dates shifted in each copy. The command @kbd{C-c C-x c} was @@ -6192,7 +6504,14 @@ be selected: thisyear, lastyear, thisyear-@var{N} @r{a relative year} @r{Use @kbd{S-@key{left}/@key{right}} keys to shift the time interval.} :tstart @r{A time string specifying when to start considering times.} + @r{Relative times like @code{"<-2w>"} can also be used. See} + @r{@ref{Matching tags and properties} for relative time syntax.} :tend @r{A time string specifying when to stop considering times.} + @r{Relative times like @code{""} can also be used. See} + @r{@ref{Matching tags and properties} for relative time syntax.} +:wstart @r{The starting day of the week. The default is 1 for monday.} +:mstart @r{The starting day of the month. The default 1 is for the first} + @r{day of the month.} :step @r{@code{week} or @code{day}, to split the table into chunks.} @r{To use this, @code{:block} or @code{:tstart}, @code{:tend} are needed.} :stepskip0 @r{Do not show steps that have zero time.} @@ -6243,6 +6562,11 @@ only to fit it into the manual.} :tend "<2006-08-10 Thu 12:00>" #+END: clocktable @end example +A range starting a week ago and ending right now could be written as +@example +#+BEGIN: clocktable :tstart "<-1w>" :tend "" +#+END: clocktable +@end example A summary of the current subtree with % times would be @example #+BEGIN: clocktable :scope subtree :link t :formula % @@ -6260,6 +6584,7 @@ would be @subsubheading Resolving idle time @cindex resolve idle time +@vindex org-clock-x11idle-program-name @cindex idle, resolve, dangling If you clock in on a work item, and then walk away from your @@ -6273,12 +6598,14 @@ as 10 or 15, Emacs can alert you when you get back to your computer after being idle for that many minutes@footnote{On computers using Mac OS X, idleness is based on actual user idleness, not just Emacs' idle time. For X11, you can install a utility program @file{x11idle.c}, available in the -@code{contrib/scripts} directory of the Org git distribution, to get the same -general treatment of idleness. On other systems, idle time refers to Emacs -idle time only.}, and ask what you want to do with the idle time. There will -be a question waiting for you when you get back, indicating how much idle -time has passed (constantly updated with the current amount), as well as a -set of choices to correct the discrepancy: +@code{contrib/scripts} directory of the Org git distribution, or install the +@file{xprintidle} package and set it to the variable +@code{org-clock-x11idle-program-name} if you are running Debian, to get the +same general treatment of idleness. On other systems, idle time refers to +Emacs idle time only.}, and ask what you want to do with the idle time. +There will be a question waiting for you when you get back, indicating how +much idle time has passed (constantly updated with the current amount), as +well as a set of choices to correct the discrepancy: @table @kbd @item k @@ -6470,7 +6797,7 @@ trees to an archive file keeps the system compact and fast. * Attachments:: Add files to tasks * RSS Feeds:: Getting input from RSS feeds * Protocols:: External (e.g., Browser) access to Emacs and Org -* Refiling notes:: Moving a tree from one place to another +* Refile and copy:: Moving/copying a tree from one place to another * Archiving:: What to do with finished projects @end menu @@ -6478,25 +6805,22 @@ trees to an archive file keeps the system compact and fast. @section Capture @cindex capture -Org's method for capturing new items is heavily inspired by John Wiegley -excellent remember package. Up to version 6.36 Org used a special setup -for @file{remember.el}. @file{org-remember.el} is still part of Org mode for -backward compatibility with existing setups. You can find the documentation -for org-remember at @url{http://orgmode.org/org-remember.pdf}. +Capture lets you quickly store notes with little interruption of your work +flow. Org's method for capturing new items is heavily inspired by John +Wiegley excellent @file{remember.el} package. Up to version 6.36, Org +used a special setup for @file{remember.el}, then replaced it with +@file{org-remember.el}. As of version 8.0, @file{org-remember.el} has +been completely replaced by @file{org-capture.el}. -The new capturing setup described here is preferred and should be used by new -users. To convert your @code{org-remember-templates}, run the command +If your configuration depends on @file{org-remember.el}, you need to update +it and use the setup described below. To convert your +@code{org-remember-templates}, run the command @example -@kbd{M-x org-capture-import-remember-templates @key{RET}} +@kbd{M-x org-capture-import-remember-templates RET} @end example @noindent and then customize the new variable with @kbd{M-x customize-variable org-capture-templates}, check the result, and save the -customization. You can then use both remember and capture until -you are familiar with the new mechanism. - -Capture lets you quickly store notes with little interruption of your work -flow. The basic process of capturing is very similar to remember, but Org -does enhance it with templates and more. +customization. @menu * Setting up capture:: Where notes will be stored @@ -6512,10 +6836,12 @@ a global key@footnote{Please select your own key, @kbd{C-c c} is only a suggestion.} for capturing new material. @vindex org-default-notes-file -@example +@smalllisp +@group (setq org-default-notes-file (concat org-directory "/notes.org")) (define-key global-map "\C-cc" 'org-capture) -@end example +@end group +@end smalllisp @node Using capture, Capture templates, Setting up capture, Capture @subsection Using capture @@ -6537,7 +6863,7 @@ so that you can resume your work without further distraction. When called with a prefix arg, finalize and then jump to the captured item. @orgcmd{C-c C-w,org-capture-refile} -Finalize the capture process by refiling (@pxref{Refiling notes}) the note to +Finalize the capture process by refiling (@pxref{Refile and copy}) the note to a different place. Please realize that this is a normal refiling command that will be executed---so the cursor position at the moment you run this command is important. If you have inserted a tree with a parent and @@ -6594,13 +6920,15 @@ your file @file{~/org/gtd.org}. Also, a date tree in the file @file{journal.org} should capture journal entries. A possible configuration would look like: -@example +@smalllisp +@group (setq org-capture-templates '(("t" "Todo" entry (file+headline "~/org/gtd.org" "Tasks") "* TODO %?\n %i\n %a") ("j" "Journal" entry (file+datetree "~/org/journal.org") "* %?\nEntered on %U\n %i\n %a"))) -@end example +@end group +@end smalllisp @noindent If you then press @kbd{C-c c t}, Org will prepare the template for you like this: @@ -6613,7 +6941,7 @@ for you like this: During expansion of the template, @code{%a} has been replaced by a link to the location from where you called the capture command. This can be extremely useful for deriving tasks from emails, for example. You fill in -the task definition, press @code{C-c C-c} and Org returns you to the same +the task definition, press @kbd{C-c C-c} and Org returns you to the same place where you started the capture process. To define special keys to capture to a particular template without going @@ -6645,9 +6973,9 @@ single key, or @code{"bt"} for selection with two keys. When using several keys, keys using the same prefix key must be sequential in the list and preceded by a 2-element entry explaining the prefix key, for example -@example +@smalllisp ("b" "Templates for marking stuff to buy") -@end example +@end smalllisp @noindent If you do not define a template for the @kbd{C} key, this key will be used to open the customize buffer for this complex variable. @@ -6657,6 +6985,7 @@ selection. @item type The type of entry, a symbol. Valid values are: + @table @code @item entry An Org mode node, with a headline. Will be filed as the child of the target @@ -6685,6 +7014,7 @@ the empty string, it defaults to @code{org-default-notes-file}. A file can also be given as a variable, function, or Emacs Lisp form. Valid values are: + @table @code @item (file "path/to/file") Text will be placed at the beginning or end of that file. @@ -6702,7 +7032,10 @@ For non-unique headings, the full path is safer. Use a regular expression to position the cursor. @item (file+datetree "path/to/file") -Will create a heading in a date tree for today's date. +Will create a heading in a date tree for today's date@footnote{Datetree +headlines for years accept tags, so if you use both @code{* 2013 :noexport:} +and @code{* 2013} in your file, the capture will refile the note to the first +one matched.}. @item (file+datetree+prompt "path/to/file") Will create a heading in a date tree, but will prompt for the date. @@ -6729,6 +7062,7 @@ more details. @item properties The rest of the entry is a property list of additional options. Recognized properties are: + @table @code @item :prepend Normally new captured information will be appended at @@ -6782,7 +7116,9 @@ dynamic insertion of content. The templates are expanded in the order given her @smallexample %[@var{file}] @r{Insert the contents of the file given by @var{file}.} %(@var{sexp}) @r{Evaluate Elisp @var{sexp} and replace with the result.} - @r{The sexp must return a string.} + @r{For convenience, %:keyword (see below) placeholders} + @r{within the expression will be expanded prior to this.} + @r{The sexp must return a string.} %<...> @r{The result of format-time-string on the ... format specification.} %t @r{Timestamp, date only.} %T @r{Timestamp, with date and time.} @@ -6855,22 +7191,22 @@ To place the cursor after template expansion use: @vindex org-capture-templates-contexts To control whether a capture template should be accessible from a specific -context, you can customize @var{org-capture-templates-contexts}. Let's say +context, you can customize @code{org-capture-templates-contexts}. Let's say for example that you have a capture template @code{"p"} for storing Gnus emails containing patches. Then you would configure this option like this: -@example +@smalllisp (setq org-capture-templates-contexts '(("p" (in-mode . "message-mode")))) -@end example +@end smalllisp You can also tell that the command key @code{"p"} should refer to another template. In that case, add this command key like this: -@example +@smalllisp (setq org-capture-templates-contexts '(("p" "q" (in-mode . "message-mode")))) -@end example +@end smalllisp See the docstring of the variable for more information. @@ -6901,7 +7237,6 @@ directory. @noindent The following commands deal with attachments: @table @kbd - @orgcmd{C-c C-a,org-attach} The dispatcher for commands related to the attachment system. After these keys, a list of commands is displayed and you must press an additional key @@ -6975,12 +7310,14 @@ web to import tasks into Org. To access feeds, configure the variable @code{org-feed-alist}. The docstring of this variable has detailed information. Here is just an example: -@example +@smalllisp +@group (setq org-feed-alist '(("Slashdot" "http://rss.slashdot.org/Slashdot/slashdot" "~/txt/org/feeds.org" "Slashdot Entries"))) -@end example +@end group +@end smalllisp @noindent will configure that new items from the feed provided by @@ -7009,7 +7346,7 @@ list of drawers in that file: For more information, including how to read atom feeds, see @file{org-feed.el} and the docstring of @code{org-feed-alist}. -@node Protocols, Refiling notes, RSS Feeds, Capture - Refile - Archive +@node Protocols, Refile and copy, RSS Feeds, Capture - Refile - Archive @section Protocols for external access @cindex protocols, for external access @cindex emacsserver @@ -7023,17 +7360,22 @@ a remote website you are looking at with the browser. See @uref{http://orgmode.org/worg/org-contrib/org-protocol.php} for detailed documentation and setup instructions. -@node Refiling notes, Archiving, Protocols, Capture - Refile - Archive -@section Refiling notes +@node Refile and copy, Archiving, Protocols, Capture - Refile - Archive +@section Refile and copy @cindex refiling notes +@cindex copying notes -When reviewing the captured data, you may want to refile some of the entries -into a different list, for example into a project. Cutting, finding the -right location, and then pasting the note is cumbersome. To simplify this -process, you can use the following special command: +When reviewing the captured data, you may want to refile or to copy some of +the entries into a different list, for example into a project. Cutting, +finding the right location, and then pasting the note is cumbersome. To +simplify this process, you can use the following special command: @table @kbd +@orgcmd{C-c M-w,org-copy} +@findex org-copy +Copying works like refiling, except that the original note is not deleted. @orgcmd{C-c C-w,org-refile} +@findex org-refile @vindex org-reverse-note-order @vindex org-refile-targets @vindex org-refile-use-outline-path @@ -7041,6 +7383,7 @@ process, you can use the following special command: @vindex org-refile-allow-creating-parent-nodes @vindex org-log-refile @vindex org-refile-use-cache +@vindex org-refile-keep Refile the entry or region at point. This command offers possible locations for refiling the entry and lets you select one with completion. The item (or all items in the region) is filed below the target heading as a subitem. @@ -7064,13 +7407,17 @@ Use the refile interface to jump to a heading. Jump to the location where @code{org-refile} last moved a tree to. @item C-2 C-c C-w Refile as the child of the item currently being clocked. +@item C-3 C-c C-w +Refile and keep the entry in place. Also see @code{org-refile-keep} to make +this the default behavior, and beware that this may result in duplicated +@code{ID} properties. @orgcmdtkc{C-0 C-c C-w @ @r{or} @ C-u C-u C-u C-c C-w,C-0 C-c C-w,org-refile-cache-clear} Clear the target cache. Caching of refile targets can be turned on by setting @code{org-refile-use-cache}. To make the command see new possible targets, you have to clear the cache with this command. @end table -@node Archiving, , Refiling notes, Capture - Refile - Archive +@node Archiving, , Refile and copy, Capture - Refile - Archive @section Archiving @cindex archiving @@ -7307,7 +7654,7 @@ Remove current file from the list of agenda files. @itemx C-, Cycle through agenda file list, visiting one file after the other. @kindex M-x org-iswitchb -@item M-x org-iswitchb +@item M-x org-iswitchb RET Command to use an @code{iswitchb}-like interface to switch to and between Org buffers. @end table @@ -7338,6 +7685,7 @@ Remove the permanent restriction created by @kbd{C-c C-x <}. @noindent When working with @file{speedbar.el}, you can use the following commands in the Speedbar frame: + @table @kbd @orgcmdtkc{< @r{in the speedbar frame},<,org-speedbar-set-agenda-restriction} Permanently restrict the agenda to the item---either an Org file or a subtree @@ -7358,6 +7706,7 @@ following we will assume that @kbd{C-c a} is indeed how the dispatcher is accessed and list keyboard access to commands accordingly. After pressing @kbd{C-c a}, an additional letter is required to execute a command. The dispatcher offers the following default commands: + @table @kbd @item a Create the calendar-like agenda (@pxref{Weekly/daily agenda}). @@ -7446,11 +7795,16 @@ C-c a a}) you may set the number of days to be displayed. @vindex org-agenda-span @vindex org-agenda-ndays +@vindex org-agenda-start-day +@vindex org-agenda-start-on-weekday The default number of days displayed in the agenda is set by the variable @code{org-agenda-span} (or the obsolete @code{org-agenda-ndays}). This variable can be set to any number of days you want to see by default in the -agenda, or to a span name, such a @code{day}, @code{week}, @code{month} or -@code{year}. +agenda, or to a span name, such as @code{day}, @code{week}, @code{month} or +@code{year}. For weekly agendas, the default is to start on the previous +monday (see @code{org-agenda-start-on-weekday}). You can also set the start +date using a date shift: @code{(setq org-agenda-start-day "+10d")} will +start the agenda ten days from today in the future. Remote editing from the agenda buffer means, for example, that you can change the dates of deadlines and appointments from the agenda buffer. @@ -7656,16 +8010,21 @@ commands}. @subsubheading Match syntax @cindex Boolean logic, for tag/property searches -A search string can use Boolean operators @samp{&} for AND and @samp{|} for -OR@. @samp{&} binds more strongly than @samp{|}. Parentheses are currently -not implemented. Each element in the search is either a tag, a regular -expression matching tags, or an expression like @code{PROPERTY OPERATOR -VALUE} with a comparison operator, accessing a property value. Each element -may be preceded by @samp{-}, to select against it, and @samp{+} is syntactic -sugar for positive selection. The AND operator @samp{&} is optional when -@samp{+} or @samp{-} is present. Here are some examples, using only tags. +A search string can use Boolean operators @samp{&} for @code{AND} and +@samp{|} for @code{OR}@. @samp{&} binds more strongly than @samp{|}. +Parentheses are not implemented. Each element in the search is either a +tag, a regular expression matching tags, or an expression like +@code{PROPERTY OPERATOR VALUE} with a comparison operator, accessing a +property value. Each element may be preceded by @samp{-}, to select +against it, and @samp{+} is syntactic sugar for positive selection. The +@code{AND} operator @samp{&} is optional when @samp{+} or @samp{-} is +present. Here are some examples, using only tags. @table @samp +@item work +Select headlines tagged @samp{:work:}. +@item work&boss +Select headlines tagged @samp{:work:} and @samp{:boss:}. @item +work-boss Select headlines tagged @samp{:work:}, but discard those also tagged @samp{:boss:}. @@ -7682,6 +8041,13 @@ braces. For example, @samp{work+@{^boss.*@}} matches headlines that contain the tag @samp{:work:} and any tag @i{starting} with @samp{boss}. +@cindex group tags, as regular expressions +Group tags (@pxref{Tag groups}) are expanded as regular expressions. E.g., +if @samp{:work:} is a group tag for the group @samp{:work:lab:conf:}, then +searching for @samp{work} will search for @samp{@{\(?:work\|lab\|conf\)@}} +and searching for @samp{-work} will search for all headlines but those with +one of the tag in the group (i.e., @samp{-@{\(?:work\|lab\|conf\)@}}). + @cindex TODO keyword matching, with tags search @cindex level, require for tags/property match @cindex category, require for tags/property match @@ -7690,16 +8056,20 @@ You may also test for properties (@pxref{Properties and Columns}) at the same time as matching tags. The properties may be real properties, or special properties that represent other metadata (@pxref{Special properties}). For example, the ``property'' @code{TODO} represents the TODO keyword of the -entry. Or, the ``property'' @code{LEVEL} represents the level of an entry. -So a search @samp{+LEVEL=3+boss-TODO="DONE"} lists all level three headlines -that have the tag @samp{boss} and are @emph{not} marked with the TODO keyword -DONE@. In buffers with @code{org-odd-levels-only} set, @samp{LEVEL} does not -count the number of stars, but @samp{LEVEL=2} will correspond to 3 stars etc. -The ITEM special property cannot currently be used in tags/property +entry and the ``propety'' @code{PRIORITY} represents the PRIORITY keyword of +the entry. The ITEM special property cannot currently be used in tags/property searches@footnote{But @pxref{x-agenda-skip-entry-regexp, ,skipping entries based on regexp}.}. +Except the @pxref{Special properties}, one other ``property'' can also be +used. @code{LEVEL} represents the level of an entry. So a search +@samp{+LEVEL=3+boss-TODO="DONE"} lists all level three headlines that have +the tag @samp{boss} and are @emph{not} marked with the TODO keyword DONE@. +In buffers with @code{org-odd-levels-only} set, @samp{LEVEL} does not count +the number of stars, but @samp{LEVEL=2} will correspond to 3 stars etc. + Here are more examples: + @table @samp @item work+TODO="WAITING" Select @samp{:work:}-tagged TODO lines with the specific TODO @@ -7899,7 +8269,8 @@ associated with the item. @menu * Categories:: Not all tasks are equal * Time-of-day specifications:: How the agenda knows the time -* Sorting of agenda items:: The order of things +* Sorting agenda items:: The order of things +* Filtering/limiting agenda items:: Dynamically narrow the agenda @end menu @node Categories, Time-of-day specifications, Presentation and sorting, Presentation and sorting @@ -7936,7 +8307,7 @@ longer than 10 characters. You can set up icons for category by customizing the @code{org-agenda-category-icon-alist} variable. -@node Time-of-day specifications, Sorting of agenda items, Categories, Presentation and sorting +@node Time-of-day specifications, Sorting agenda items, Categories, Presentation and sorting @subsection Time-of-day specifications @cindex time-of-day specification @@ -7987,8 +8358,8 @@ The time grid can be turned on and off with the variable @code{org-agenda-use-time-grid}, and can be configured with @code{org-agenda-time-grid}. -@node Sorting of agenda items, , Time-of-day specifications, Presentation and sorting -@subsection Sorting of agenda items +@node Sorting agenda items, Filtering/limiting agenda items, Time-of-day specifications, Presentation and sorting +@subsection Sorting agenda items @cindex sorting, of agenda items @cindex priorities, of agenda items Before being inserted into a view, the items are sorted. How this is @@ -8021,66 +8392,249 @@ Sorting can be customized using the variable @code{org-agenda-sorting-strategy}, and may also include criteria based on the estimated effort of an entry (@pxref{Effort estimates}). -@node Agenda commands, Custom agenda views, Presentation and sorting, Agenda Views -@section Commands in the agenda buffer -@cindex commands, in agenda buffer +@node Filtering/limiting agenda items, , Sorting agenda items, Presentation and sorting +@subsection Filtering/limiting agenda items -Entries in the agenda buffer are linked back to the Org file or diary -file where they originate. You are not allowed to edit the agenda -buffer itself, but commands are provided to show and jump to the -original entry location, and to edit the Org files ``remotely'' from -the agenda buffer. In this way, all information is stored only once, -removing the risk that your agenda and note files may diverge. +Agenda built-in or customized commands are statically defined. Agenda +filters and limits provide two ways of dynamically narrowing down the list of +agenda entries: @emph{fitlers} and @emph{limits}. Filters only act on the +display of the items, while limits take effect before the list of agenda +entries is built. Filter are more often used interactively, while limits are +mostly useful when defined as local variables within custom agenda commands. -Some commands can be executed with mouse clicks on agenda lines. For -the other commands, the cursor needs to be in the desired line. +@subsubheading Filtering in the agenda +@cindex filtering, by tag, category, top headline and effort, in agenda +@cindex tag filtering, in agenda +@cindex category filtering, in agenda +@cindex top headline filtering, in agenda +@cindex effort filtering, in agenda +@cindex query editing, in agenda @table @kbd -@tsubheading{Motion} -@cindex motion commands in agenda -@orgcmd{n,org-agenda-next-line} -Next line (same as @key{down} and @kbd{C-n}). -@orgcmd{p,org-agenda-previous-line} -Previous line (same as @key{up} and @kbd{C-p}). -@tsubheading{View/Go to Org file} -@orgcmdkkc{@key{SPC},mouse-3,org-agenda-show-and-scroll-up} -Display the original location of the item in another window. -With prefix arg, make sure that the entire entry is made visible in the -outline, not only the heading. -@c -@orgcmd{L,org-agenda-recenter} -Display original location and recenter that window. -@c -@orgcmdkkc{@key{TAB},mouse-2,org-agenda-goto} -Go to the original location of the item in another window. -@c -@orgcmd{@key{RET},org-agenda-switch-to} -Go to the original location of the item and delete other windows. -@c -@orgcmd{F,org-agenda-follow-mode} -@vindex org-agenda-start-with-follow-mode -Toggle Follow mode. In Follow mode, as you move the cursor through -the agenda buffer, the other window always shows the corresponding -location in the Org file. The initial setting for this mode in new -agenda buffers can be set with the variable -@code{org-agenda-start-with-follow-mode}. -@c -@orgcmd{C-c C-x b,org-agenda-tree-to-indirect-buffer} -Display the entire subtree of the current item in an indirect buffer. With a -numeric prefix argument N, go up to level N and then take that tree. If N is -negative, go up that many levels. With a @kbd{C-u} prefix, do not remove the -previously used indirect buffer. +@orgcmd{/,org-agenda-filter-by-tag} +@vindex org-agenda-tag-filter-preset +Filter the agenda view with respect to a tag and/or effort estimates. The +difference between this and a custom agenda command is that filtering is very +fast, so that you can switch quickly between different filters without having +to recreate the agenda.@footnote{Custom commands can preset a filter by +binding the variable @code{org-agenda-tag-filter-preset} as an option. This +filter will then be applied to the view and persist as a basic filter through +refreshes and more secondary filtering. The filter is a global property of +the entire agenda view---in a block agenda, you should only set this in the +global options section, not in the section of an individual block.} -@orgcmd{C-c C-o,org-agenda-open-link} -Follow a link in the entry. This will offer a selection of any links in the -text belonging to the referenced Org node. If there is only one link, it -will be followed without a selection prompt. +You will be prompted for a tag selection letter; @key{SPC} will mean any tag at +all. Pressing @key{TAB} at that prompt will offer use completion to select a +tag (including any tags that do not have a selection character). The command +then hides all entries that do not contain or inherit this tag. When called +with prefix arg, remove the entries that @emph{do} have the tag. A second +@kbd{/} at the prompt will turn off the filter and unhide any hidden entries. +If the first key you press is either @kbd{+} or @kbd{-}, the previous filter +will be narrowed by requiring or forbidding the selected additional tag. +Instead of pressing @kbd{+} or @kbd{-} after @kbd{/}, you can also +immediately use the @kbd{\} command. -@tsubheading{Change display} -@cindex display changing, in agenda -@kindex A -@item A -Interactively select another agenda view and append it to the current view. +@vindex org-sort-agenda-noeffort-is-high +In order to filter for effort estimates, you should set up allowed +efforts globally, for example +@lisp +(setq org-global-properties + '(("Effort_ALL". "0 0:10 0:30 1:00 2:00 3:00 4:00"))) +@end lisp +You can then filter for an effort by first typing an operator, one of +@kbd{<}, @kbd{>}, and @kbd{=}, and then the one-digit index of an effort +estimate in your array of allowed values, where @kbd{0} means the 10th value. +The filter will then restrict to entries with effort smaller-or-equal, equal, +or larger-or-equal than the selected value. If the digits 0--9 are not used +as fast access keys to tags, you can also simply press the index digit +directly without an operator. In this case, @kbd{<} will be assumed. For +application of the operator, entries without a defined effort will be treated +according to the value of @code{org-sort-agenda-noeffort-is-high}. To filter +for tasks without effort definition, press @kbd{?} as the operator. + +Org also supports automatic, context-aware tag filtering. If the variable +@code{org-agenda-auto-exclude-function} is set to a user-defined function, +that function can decide which tags should be excluded from the agenda +automatically. Once this is set, the @kbd{/} command then accepts @kbd{RET} +as a sub-option key and runs the auto exclusion logic. For example, let's +say you use a @code{Net} tag to identify tasks which need network access, an +@code{Errand} tag for errands in town, and a @code{Call} tag for making phone +calls. You could auto-exclude these tags based on the availability of the +Internet, and outside of business hours, with something like this: + +@smalllisp +@group +(defun org-my-auto-exclude-function (tag) + (and (cond + ((string= tag "Net") + (/= 0 (call-process "/sbin/ping" nil nil nil + "-c1" "-q" "-t1" "mail.gnu.org"))) + ((or (string= tag "Errand") (string= tag "Call")) + (let ((hour (nth 2 (decode-time)))) + (or (< hour 8) (> hour 21))))) + (concat "-" tag))) + +(setq org-agenda-auto-exclude-function 'org-my-auto-exclude-function) +@end group +@end smalllisp + +@orgcmd{\\,org-agenda-filter-by-tag-refine} +Narrow the current agenda filter by an additional condition. When called with +prefix arg, remove the entries that @emph{do} have the tag, or that do match +the effort criterion. You can achieve the same effect by pressing @kbd{+} or +@kbd{-} as the first key after the @kbd{/} command. + +@c +@kindex [ +@kindex ] +@kindex @{ +@kindex @} +@item [ ] @{ @} +@table @i +@item @r{in} search view +add new search words (@kbd{[} and @kbd{]}) or new regular expressions +(@kbd{@{} and @kbd{@}}) to the query string. The opening bracket/brace will +add a positive search term prefixed by @samp{+}, indicating that this search +term @i{must} occur/match in the entry. The closing bracket/brace will add a +negative search term which @i{must not} occur/match in the entry for it to be +selected. +@end table + +@orgcmd{<,org-agenda-filter-by-category} +@vindex org-agenda-category-filter-preset + +Filter the current agenda view with respect to the category of the item at +point. Pressing @code{<} another time will remove this filter. You can add +a filter preset through the option @code{org-agenda-category-filter-preset} +(see below.) + +@orgcmd{^,org-agenda-filter-by-top-headline} +Filter the current agenda view and only display the siblings and the parent +headline of the one at point. + +@orgcmd{=,org-agenda-filter-by-regexp} +@vindex org-agenda-regexp-filter-preset + +Filter the agenda view by a regular expression: only show agenda entries +matching the regular expression the user entered. When called with a prefix +argument, it will filter @emph{out} entries matching the regexp. With two +universal prefix arguments, it will remove all the regexp filters, which can +be accumulated. You can add a filter preset through the option +@code{org-agenda-category-filter-preset} (see below.) + +@orgcmd{|,org-agenda-filter-remove-all} +Remove all filters in the current agenda view. +@end table + +@subsubheading Setting limits for the agenda +@cindex limits, in agenda +@vindex org-agenda-max-entries +@vindex org-agenda-max-effort +@vindex org-agenda-max-todos +@vindex org-agenda-max-tags + +Here is a list of options that you can set, either globally, or locally in +your custom agenda views@pxref{Custom agenda views}. + +@table @var +@item org-agenda-max-entries +Limit the number of entries. +@item org-agenda-max-effort +Limit the duration of accumulated efforts (as minutes). +@item org-agenda-max-todos +Limit the number of entries with TODO keywords. +@item org-agenda-max-tags +Limit the number of tagged entries. +@end table + +When set to a positive integer, each option will exclude entries from other +catogories: for example, @code{(setq org-agenda-max-effort 100)} will limit +the agenda to 100 minutes of effort and exclude any entry that as no effort +property. If you want to include entries with no effort property, use a +negative value for @code{org-agenda-max-effort}. + +One useful setup is to use @code{org-agenda-max-entries} locally in a custom +command. For example, this custom command will display the next five entries +with a @code{NEXT} TODO keyword. + +@smalllisp +(setq org-agenda-custom-commands + '(("n" todo "NEXT" + ((org-agenda-max-entries 5))))) +@end smalllisp + +Once you mark one of these five entry as @code{DONE}, rebuilding the agenda +will again the next five entries again, including the first entry that was +excluded so far. + +You can also dynamically set temporary limits@footnote{Those temporary limits +are lost when rebuilding the agenda.}: + +@table @kbd +@orgcmd{~,org-agenda-limit-interactively} +This prompts for the type of limit to apply and its value. +@end table + +@node Agenda commands, Custom agenda views, Presentation and sorting, Agenda Views +@section Commands in the agenda buffer +@cindex commands, in agenda buffer + +Entries in the agenda buffer are linked back to the Org file or diary +file where they originate. You are not allowed to edit the agenda +buffer itself, but commands are provided to show and jump to the +original entry location, and to edit the Org files ``remotely'' from +the agenda buffer. In this way, all information is stored only once, +removing the risk that your agenda and note files may diverge. + +Some commands can be executed with mouse clicks on agenda lines. For +the other commands, the cursor needs to be in the desired line. + +@table @kbd +@tsubheading{Motion} +@cindex motion commands in agenda +@orgcmd{n,org-agenda-next-line} +Next line (same as @key{down} and @kbd{C-n}). +@orgcmd{p,org-agenda-previous-line} +Previous line (same as @key{up} and @kbd{C-p}). +@tsubheading{View/Go to Org file} +@orgcmdkkc{@key{SPC},mouse-3,org-agenda-show-and-scroll-up} +Display the original location of the item in another window. +With prefix arg, make sure that the entire entry is made visible in the +outline, not only the heading. +@c +@orgcmd{L,org-agenda-recenter} +Display original location and recenter that window. +@c +@orgcmdkkc{@key{TAB},mouse-2,org-agenda-goto} +Go to the original location of the item in another window. +@c +@orgcmd{@key{RET},org-agenda-switch-to} +Go to the original location of the item and delete other windows. +@c +@orgcmd{F,org-agenda-follow-mode} +@vindex org-agenda-start-with-follow-mode +Toggle Follow mode. In Follow mode, as you move the cursor through +the agenda buffer, the other window always shows the corresponding +location in the Org file. The initial setting for this mode in new +agenda buffers can be set with the variable +@code{org-agenda-start-with-follow-mode}. +@c +@orgcmd{C-c C-x b,org-agenda-tree-to-indirect-buffer} +Display the entire subtree of the current item in an indirect buffer. With a +numeric prefix argument N, go up to level N and then take that tree. If N is +negative, go up that many levels. With a @kbd{C-u} prefix, do not remove the +previously used indirect buffer. + +@orgcmd{C-c C-o,org-agenda-open-link} +Follow a link in the entry. This will offer a selection of any links in the +text belonging to the referenced Org node. If there is only one link, it +will be followed without a selection prompt. + +@tsubheading{Change display} +@cindex display changing, in agenda +@kindex A +@item A +Interactively select another agenda view and append it to the current view. @c @kindex o @item o @@ -8088,6 +8642,7 @@ Delete other windows. @c @orgcmdkskc{v d,d,org-agenda-day-view} @xorgcmdkskc{v w,w,org-agenda-week-view} +@xorgcmd{v t,org-agenda-fortnight-view} @xorgcmd{v m,org-agenda-month-view} @xorgcmd{v y,org-agenda-year-view} @xorgcmd{v SPC,org-agenda-reset-view} @@ -8134,7 +8689,7 @@ entries that have been clocked on that day. You can configure the entry types that should be included in log mode using the variable @code{org-agenda-log-mode-items}. When called with a @kbd{C-u} prefix, show all possible logbook entries, including state changes. When called with two -prefix args @kbd{C-u C-u}, show only logging information, nothing else. +prefix arguments @kbd{C-u C-u}, show only logging information, nothing else. @kbd{v L} is equivalent to @kbd{C-u v l}. @c @orgcmdkskc{v [,[,org-agenda-manipulate-query-add} @@ -8152,7 +8707,7 @@ press @kbd{v a} again. @vindex org-agenda-start-with-clockreport-mode @vindex org-clock-report-include-clocking-task Toggle Clockreport mode. In Clockreport mode, the daily/weekly agenda will -always show a table with the clocked times for the timespan and file scope +always show a table with the clocked times for the time span and file scope covered by the current agenda view. The initial setting for this mode in new agenda buffers can be set with the variable @code{org-agenda-start-with-clockreport-mode}. By using a prefix argument @@ -8212,108 +8767,39 @@ Remove the restriction lock on the agenda, if it is currently restricted to a file or subtree (@pxref{Agenda files}). @tsubheading{Secondary filtering and query editing} -@cindex filtering, by tag category and effort, in agenda -@cindex tag filtering, in agenda -@cindex category filtering, in agenda -@cindex effort filtering, in agenda -@cindex query editing, in agenda -@orgcmd{<,org-agenda-filter-by-category} -@vindex org-agenda-category-filter-preset - -Filter the current agenda view with respect to the category of the item at -point. Pressing @code{<} another time will remove this filter. You can add -a filter preset through the option @code{org-agenda-category-filter-preset} -(see below.) +For a detailed description of these commands, see @pxref{Filtering/limiting +agenda items}. @orgcmd{/,org-agenda-filter-by-tag} @vindex org-agenda-tag-filter-preset -Filter the current agenda view with respect to a tag and/or effort estimates. -The difference between this and a custom agenda command is that filtering is -very fast, so that you can switch quickly between different filters without -having to recreate the agenda.@footnote{Custom commands can preset a filter by -binding the variable @code{org-agenda-tag-filter-preset} as an option. This -filter will then be applied to the view and persist as a basic filter through -refreshes and more secondary filtering. The filter is a global property of -the entire agenda view---in a block agenda, you should only set this in the -global options section, not in the section of an individual block.} +Filter the agenda view with respect to a tag and/or effort estimates. -You will be prompted for a tag selection letter; @key{SPC} will mean any tag at -all. Pressing @key{TAB} at that prompt will offer use completion to select a -tag (including any tags that do not have a selection character). The command -then hides all entries that do not contain or inherit this tag. When called -with prefix arg, remove the entries that @emph{do} have the tag. A second -@kbd{/} at the prompt will turn off the filter and unhide any hidden entries. -If the first key you press is either @kbd{+} or @kbd{-}, the previous filter -will be narrowed by requiring or forbidding the selected additional tag. -Instead of pressing @kbd{+} or @kbd{-} after @kbd{/}, you can also -immediately use the @kbd{\} command. +@orgcmd{\\,org-agenda-filter-by-tag-refine} +Narrow the current agenda filter by an additional condition. -@vindex org-sort-agenda-noeffort-is-high -In order to filter for effort estimates, you should set up allowed -efforts globally, for example -@lisp -(setq org-global-properties - '(("Effort_ALL". "0 0:10 0:30 1:00 2:00 3:00 4:00"))) -@end lisp -You can then filter for an effort by first typing an operator, one of -@kbd{<}, @kbd{>}, and @kbd{=}, and then the one-digit index of an effort -estimate in your array of allowed values, where @kbd{0} means the 10th value. -The filter will then restrict to entries with effort smaller-or-equal, equal, -or larger-or-equal than the selected value. If the digits 0--9 are not used -as fast access keys to tags, you can also simply press the index digit -directly without an operator. In this case, @kbd{<} will be assumed. For -application of the operator, entries without a defined effort will be treated -according to the value of @code{org-sort-agenda-noeffort-is-high}. To filter -for tasks without effort definition, press @kbd{?} as the operator. +@orgcmd{<,org-agenda-filter-by-category} +@vindex org-agenda-category-filter-preset -Org also supports automatic, context-aware tag filtering. If the variable -@code{org-agenda-auto-exclude-function} is set to a user-defined function, -that function can decide which tags should be excluded from the agenda -automatically. Once this is set, the @kbd{/} command then accepts @kbd{RET} -as a sub-option key and runs the auto exclusion logic. For example, let's -say you use a @code{Net} tag to identify tasks which need network access, an -@code{Errand} tag for errands in town, and a @code{Call} tag for making phone -calls. You could auto-exclude these tags based on the availability of the -Internet, and outside of business hours, with something like this: +Filter the current agenda view with respect to the category of the item at +point. Pressing @code{<} another time will remove this filter. -@lisp -@group -(defun org-my-auto-exclude-function (tag) - (and (cond - ((string= tag "Net") - (/= 0 (call-process "/sbin/ping" nil nil nil - "-c1" "-q" "-t1" "mail.gnu.org"))) - ((or (string= tag "Errand") (string= tag "Call")) - (let ((hour (nth 2 (decode-time)))) - (or (< hour 8) (> hour 21))))) - (concat "-" tag))) +@orgcmd{^,org-agenda-filter-by-top-headline} +Filter the current agenda view and only display the siblings and the parent +headline of the one at point. -(setq org-agenda-auto-exclude-function 'org-my-auto-exclude-function) -@end group -@end lisp +@orgcmd{=,org-agenda-filter-by-regexp} +@vindex org-agenda-regexp-filter-preset -@orgcmd{\\,org-agenda-filter-by-tag-refine} -Narrow the current agenda filter by an additional condition. When called with -prefix arg, remove the entries that @emph{do} have the tag, or that do match -the effort criterion. You can achieve the same effect by pressing @kbd{+} or -@kbd{-} as the first key after the @kbd{/} command. +Filter the agenda view by a regular expression: only show agenda entries +matching the regular expression the user entered. When called with a prefix +argument, it will filter @emph{out} entries matching the regexp. With two +universal prefix arguments, it will remove all the regexp filters, which can +be accumulated. You can add a filter preset through the option +@code{org-agenda-category-filter-preset} (see below.) -@c -@kindex [ -@kindex ] -@kindex @{ -@kindex @} -@item [ ] @{ @} -@table @i -@item @r{in} search view -add new search words (@kbd{[} and @kbd{]}) or new regular expressions -(@kbd{@{} and @kbd{@}}) to the query string. The opening bracket/brace will -add a positive search term prefixed by @samp{+}, indicating that this search -term @i{must} occur/match in the entry. The closing bracket/brace will add a -negative search term which @i{must not} occur/match in the entry for it to be -selected. -@end table +@orgcmd{|,org-agenda-filter-remove-all} +Remove all filters in the current agenda view. @tsubheading{Remote editing} @cindex remote editing, from agenda @@ -8440,29 +8926,50 @@ Jump to the running clock in another window. @c @orgcmd{k,org-agenda-capture} Like @code{org-capture}, but use the date at point as the default date for -the capture template. See @var{org-capture-use-agenda-date} to make this +the capture template. See @code{org-capture-use-agenda-date} to make this the default behavior of @code{org-capture}. @cindex capturing, from agenda @vindex org-capture-use-agenda-date +@tsubheading{Dragging agenda lines forward/backward} +@cindex dragging, agenda lines + +@orgcmd{M-,org-agenda-drag-line-backward} +Drag the line at point backward one line@footnote{Moving agenda lines does +not persist after an agenda refresh and does not modify the contributing +@file{.org} files}. With a numeric prefix argument, drag backward by that +many lines. + +@orgcmd{M-,org-agenda-drag-line-forward} +Drag the line at point forward one line. With a numeric prefix argument, +drag forward by that many lines. + @tsubheading{Bulk remote editing selected entries} @cindex remote editing, bulk, from agenda -@vindex org-agenda-bulk-persistent-marks @vindex org-agenda-bulk-custom-functions @orgcmd{m,org-agenda-bulk-mark} -Mark the entry at point for bulk action. With prefix arg, mark that many -successive entries. +Mark the entry at point for bulk action. With numeric prefix argument, mark +that many successive entries. @c -@orgcmd{%,org-agenda-bulk-mark-regexp} -Mark entries matching a regular expression for bulk action. +@orgcmd{*,org-agenda-bulk-mark-all} +Mark all visible agenda entries for bulk action. @c @orgcmd{u,org-agenda-bulk-unmark} -Unmark entry for bulk action. +Unmark entry at point for bulk action. @c @orgcmd{U,org-agenda-bulk-remove-all-marks} Unmark all marked entries for bulk action. @c +@orgcmd{M-m,org-agenda-bulk-toggle} +Toggle mark of the entry at point for bulk action. +@c +@orgcmd{M-*,org-agenda-bulk-toggle-all} +Toggle marks of all visible entries for bulk action. +@c +@orgcmd{%,org-agenda-bulk-mark-regexp} +Mark entries matching a regular expression for bulk action. +@c @orgcmd{B,org-agenda-bulk-action} Bulk action: act on all marked entries in the agenda. This will prompt for another key to select the action to be applied. The prefix arg to @kbd{B} @@ -8471,40 +8978,55 @@ these special timestamps. By default, marks are removed after the bulk. If you want them to persist, set @code{org-agenda-bulk-persistent-marks} to @code{t} or hit @kbd{p} at the prompt. -@example -* @r{Toggle persistent marks.} -$ @r{Archive all selected entries.} -A @r{Archive entries by moving them to their respective archive siblings.} -t @r{Change TODO state. This prompts for a single TODO keyword and} - @r{changes the state of all selected entries, bypassing blocking and} - @r{suppressing logging notes (but not timestamps).} -+ @r{Add a tag to all selected entries.} -- @r{Remove a tag from all selected entries.} -s @r{Schedule all items to a new date. To shift existing schedule dates} - @r{by a fixed number of days, use something starting with double plus} - @r{at the prompt, for example @samp{++8d} or @samp{++2w}.} -d @r{Set deadline to a specific date.} -r @r{Prompt for a single refile target and move all entries. The entries} - @r{will no longer be in the agenda; refresh (@kbd{g}) to bring them back.} -S @r{Reschedule randomly into the coming N days. N will be prompted for.} - @r{With prefix arg (@kbd{C-u B S}), scatter only across weekdays.} -f @r{Apply a function@footnote{You can also create persistent custom functions through@code{org-agenda-bulk-custom-functions}.} to marked entries.} - @r{For example, the function below sets the CATEGORY property of the} - @r{entries to web.} - @r{(defun set-category ()} - @r{ (interactive "P")} - @r{ (let* ((marker (or (org-get-at-bol 'org-hd-marker)} - @r{ (org-agenda-error)))} - @r{ (buffer (marker-buffer marker)))} - @r{ (with-current-buffer buffer} - @r{ (save-excursion} - @r{ (save-restriction} - @r{ (widen)} - @r{ (goto-char marker)} - @r{ (org-back-to-heading t)} - @r{ (org-set-property "CATEGORY" "web"))))))} -@end example +@table @kbd +@item * +Toggle persistent marks. +@item $ +Archive all selected entries. +@item A +Archive entries by moving them to their respective archive siblings. +@item t +Change TODO state. This prompts for a single TODO keyword and changes the +state of all selected entries, bypassing blocking and suppressing logging +notes (but not timestamps). +@item + +Add a tag to all selected entries. +@item - +Remove a tag from all selected entries. +@item s +Schedule all items to a new date. To shift existing schedule dates by a +fixed number of days, use something starting with double plus at the prompt, +for example @samp{++8d} or @samp{++2w}. +@item d +Set deadline to a specific date. +@item r +Prompt for a single refile target and move all entries. The entries will no +longer be in the agenda; refresh (@kbd{g}) to bring them back. +@item S +Reschedule randomly into the coming N days. N will be prompted for. With +prefix arg (@kbd{C-u B S}), scatter only across weekdays. +@item f +Apply a function@footnote{You can also create persistent custom functions +through @code{org-agenda-bulk-custom-functions}.} to marked entries. For +example, the function below sets the CATEGORY property of the entries to web. +@lisp +@group +(defun set-category () + (interactive "P") + (let* ((marker (or (org-get-at-bol 'org-hd-marker) + (org-agenda-error))) + (buffer (marker-buffer marker))) + (with-current-buffer buffer + (save-excursion + (save-restriction + (widen) + (goto-char marker) + (org-back-to-heading t) + (org-set-property "CATEGORY" "web")))))) +@end group +@end lisp +@end table @tsubheading{Calendar commands} @cindex calendar commands, from agenda @@ -8551,7 +9073,7 @@ calendars. @orgcmd{H,org-agenda-holidays} Show holidays for three months around the cursor date. -@item M-x org-export-icalendar-combine-agenda-files +@item M-x org-icalendar-combine-agenda-files RET Export a single iCalendar file containing entries from all agenda files. This is a globally available command, and also available in the agenda menu. @@ -8561,12 +9083,13 @@ This is a globally available command, and also available in the agenda menu. @cindex agenda views, exporting @vindex org-agenda-exporter-settings Write the agenda view to a file. Depending on the extension of the selected -file name, the view will be exported as HTML (extension @file{.html} or -@file{.htm}), Postscript (extension @file{.ps}), PDF (extension @file{.pdf}), -and plain text (any other extension). When called with a @kbd{C-u} prefix -argument, immediately open the newly created file. Use the variable -@code{org-agenda-exporter-settings} to set options for @file{ps-print} and -for @file{htmlize} to be used during export. +file name, the view will be exported as HTML (@file{.html} or @file{.htm}), +Postscript (@file{.ps}), PDF (@file{.pdf}), Org (@file{.org}) and plain text +(any other extension). When exporting to Org, only the body of original +headlines are exported, not subtrees or inherited tags. When called with a +@kbd{C-u} prefix argument, immediately open the newly created file. Use the +variable @code{org-agenda-exporter-settings} to set options for +@file{ps-print} and for @file{htmlize} to be used during export. @tsubheading{Quit and Exit} @orgcmd{q,org-agenda-quit} @@ -8606,6 +9129,8 @@ buffer). @kindex C-c a C @vindex org-agenda-custom-commands @cindex agenda views, main example +@cindex agenda, as an agenda views +@cindex agenda*, as an agenda views @cindex tags, as an agenda view @cindex todo, as an agenda view @cindex tags-todo @@ -8616,13 +9141,15 @@ buffer). Custom commands are configured in the variable @code{org-agenda-custom-commands}. You can customize this variable, for example by pressing @kbd{C-c a C}. You can also directly set it with Emacs -Lisp in @file{.emacs}. The following example contains all valid search -types: +Lisp in @file{.emacs}. The following example contains all valid agenda +views: @lisp @group (setq org-agenda-custom-commands - '(("w" todo "WAITING") + '(("x" agenda) + ("y" agenda*) + ("w" todo "WAITING") ("W" todo-tree "WAITING") ("u" tags "+boss-urgent") ("v" tags-todo "+boss-urgent") @@ -8648,6 +9175,15 @@ expression to be used for the matching. The example above will therefore define: @table @kbd +@item C-c a x +as a global search for agenda entries planned@footnote{@emph{Planned} means +here that these entries have some planning information attached to them, like +a time-stamp, a scheduled or a deadline string. See +@code{org-agenda-entry-types} on how to set what planning information will be +taken into account.} this week/day. +@item C-c a y +as a global search for agenda entries planned this week/day, but only those +with an hour specification like @code{[h]h:mm}---think of them as appointments. @item C-c a w as a global search for TODO entries with @samp{WAITING} as the TODO keyword @@ -8782,23 +9318,23 @@ yourself. @vindex org-agenda-custom-commands-contexts To control whether an agenda command should be accessible from a specific -context, you can customize @var{org-agenda-custom-commands-contexts}. Let's +context, you can customize @code{org-agenda-custom-commands-contexts}. Let's say for example that you have an agenda commands @code{"o"} displaying a view that you only need when reading emails. Then you would configure this option like this: -@example +@lisp (setq org-agenda-custom-commands-contexts '(("o" (in-mode . "message-mode")))) -@end example +@end lisp You can also tell that the command key @code{"o"} should refer to another command key @code{"r"}. In that case, add this command key like this: -@example +@lisp (setq org-agenda-custom-commands-contexts '(("o" "r" (in-mode . "message-mode")))) -@end example +@end lisp See the docstring of the variable for more information. @@ -9009,19 +9545,20 @@ spent (via @code{CLOCKSUM}) and with the planned total effort for it. @chapter Markup for rich export When exporting Org mode documents, the exporter tries to reflect the -structure of the document as accurately as possible in the backend. Since -export targets like HTML, @LaTeX{}, or DocBook allow much richer formatting, -Org mode has rules on how to prepare text for rich export. This section -summarizes the markup rules used in an Org mode buffer. +structure of the document as accurately as possible in the back-end. Since +export targets like HTML, @LaTeX{} allow much richer formatting, Org mode has +rules on how to prepare text for rich export. This section summarizes the +markup rules used in an Org mode buffer. @menu * Structural markup elements:: The basic structure as seen by the exporter -* Images and tables:: Tables and Images will be included +* Images and tables:: Images, tables and caption mechanism * Literal examples:: Source code examples with special formatting * Include files:: Include additional files into a document * Index entries:: Making an index -* Macro replacement:: Use macros to create complex output +* Macro replacement:: Use macros to create templates * Embedded @LaTeX{}:: LaTeX can be freely used inside Org documents +* Special blocks:: Containers targeted at export back-ends @end menu @node Structural markup elements, Images and tables, Markup, Markup @@ -9031,7 +9568,6 @@ summarizes the markup rules used in an Org mode buffer. * Document title:: Where the title is taken from * Headings and sections:: The document structure as seen by the exporter * Table of contents:: The if and where of the table of contents -* Initial text:: Text before the first heading? * Lists:: Lists * Paragraphs:: Paragraphs * Footnote markup:: Footnotes @@ -9053,15 +9589,13 @@ The title of the exported document is taken from the special line @end example @noindent -If this line does not exist, the title is derived from the first non-empty, -non-comment line in the buffer. If no such line exists, or if you have -turned off exporting of the text before the first headline (see below), the -title will be the file name without extension. +If this line does not exist, the title will be the name of the file +associated to buffer, without extension, or the buffer name. @cindex property, EXPORT_TITLE -If you are exporting only a subtree by marking is as the region, the heading -of the subtree will become the title of the document. If the subtree has a -property @code{EXPORT_TITLE}, that will take precedence. +If you are exporting only a subtree, its heading will become the title of the +document. If the subtree has a property @code{EXPORT_TITLE}, that will take +precedence. @node Headings and sections, Table of contents, Document title, Structural markup elements @subheading Headings and sections @@ -9081,58 +9615,55 @@ per-file basis with a line #+OPTIONS: H:4 @end example -@node Table of contents, Initial text, Headings and sections, Structural markup elements +@node Table of contents, Lists, Headings and sections, Structural markup elements @subheading Table of contents @cindex table of contents, markup rules +@cindex #+TOC @vindex org-export-with-toc The table of contents is normally inserted directly before the first headline -of the file. If you would like to get it to a different location, insert the -string @code{[TABLE-OF-CONTENTS]} on a line by itself at the desired -location. The depth of the table of contents is by default the same as the -number of headline levels, but you can choose a smaller number, or turn off -the table of contents entirely, by configuring the variable -@code{org-export-with-toc}, or on a per-file basis with a line like +of the file. The depth of the table is by default the same as the number of +headline levels, but you can choose a smaller number, or turn off the table +of contents entirely, by configuring the variable @code{org-export-with-toc}, +or on a per-file basis with a line like @example #+OPTIONS: toc:2 (only to two levels in TOC) -#+OPTIONS: toc:nil (no TOC at all) +#+OPTIONS: toc:nil (no default TOC at all) @end example -@node Initial text, Lists, Table of contents, Structural markup elements -@subheading Text before the first headline -@cindex text before first headline, markup rules -@cindex #+TEXT +If you would like to move the table of contents to a different location, you +should turn off the detault table using @code{org-export-with-toc} or +@code{#+OPTIONS} and insert @code{#+TOC: headlines N} at the desired +location(s). -Org mode normally exports the text before the first headline, and even uses -the first line as the document title. The text will be fully marked up. If -you need to include literal HTML, @LaTeX{}, or DocBook code, use the special -constructs described below in the sections for the individual exporters. - -@vindex org-export-skip-text-before-1st-heading -Some people like to use the space before the first headline for setup and -internal links and therefore would like to control the exported text before -the first headline in a different way. You can do so by setting the variable -@code{org-export-skip-text-before-1st-heading} to @code{t}. On a per-file -basis, you can get the same effect with @samp{#+OPTIONS: skip:t}. +@example +#+OPTIONS: toc:nil (no default TOC) +... +#+TOC: headlines 2 (insert TOC here, with two headline levels) +@end example -@noindent -If you still want to have some text before the first headline, use the -@code{#+TEXT} construct: +Multiple @code{#+TOC: headline} lines are allowed. The same @code{TOC} +keyword can also generate a list of all tables (resp.@: all listings) with a +caption in the buffer. @example -#+OPTIONS: skip:t -#+TEXT: This text will go before the *first* headline. -#+TEXT: [TABLE-OF-CONTENTS] -#+TEXT: This goes between the table of contents and the *first* headline +#+TOC: listings (build a list of listings) +#+TOC: tables (build a list of tables) @end example -@node Lists, Paragraphs, Initial text, Structural markup elements +@cindex property, ALT_TITLE +The headline's title usually determines its corresponding entry in a table of +contents. However, it is possible to specify an alternative title by +setting @code{ALT_TITLE} property accordingly. It will then be used when +building the table. + +@node Lists, Paragraphs, Table of contents, Structural markup elements @subheading Lists @cindex lists, markup rules -Plain lists as described in @ref{Plain lists}, are translated to the backend's -syntax for such lists. Most backends support unordered, ordered, and +Plain lists as described in @ref{Plain lists}, are translated to the back-end's +syntax for such lists. Most back-ends support unordered, ordered, and description lists. @node Paragraphs, Footnote markup, Lists, Structural markup elements @@ -9184,7 +9715,7 @@ but not any simpler @cindex @file{footnote.el} Footnotes defined in the way described in @ref{Footnotes}, will be exported -by all backends. Org allows multiple references to the same note, and +by all back-ends. Org allows multiple references to the same note, and multiple footnotes side by side. @node Emphasis and monospace, Horizontal rules, Footnote markup, Structural markup elements @@ -9196,16 +9727,27 @@ multiple footnotes side by side. @cindex verbatim text, markup rules @cindex code text, markup rules @cindex strike-through text, markup rules +@vindex org-fontify-emphasized-text +@vindex org-emphasis-regexp-components +@vindex org-emphasis-alist You can make words @b{*bold*}, @i{/italic/}, _underlined_, @code{=code=} and @code{~verbatim~}, and, if you must, @samp{+strike-through+}. Text in the code and verbatim string is not processed for Org mode specific -syntax; it is exported verbatim. +syntax, it is exported verbatim. + +To turn off fontification for marked up text, you can set +@code{org-fontify-emphasized-text} to @code{nil}. To narrow down the list of +available markup syntax, you can customize @code{org-emphasis-alist}. To fine +tune what characters are allowed before and after the markup characters, you +can tweak @code{org-emphasis-regexp-components}. Beware that changing one of +the above variables will no take effect until you reload Org, for which you +may need to restart Emacs. @node Horizontal rules, Comment lines, Emphasis and monospace, Structural markup elements @subheading Horizontal rules @cindex horizontal rules, markup rules A line consisting of only dashes, and at least 5 of them, will be exported as -a horizontal line (@samp{
} in HTML and @code{\hrule} in @LaTeX{}). +a horizontal line. @node Comment lines, , Horizontal rules, Structural markup elements @subheading Comment lines @@ -9231,45 +9773,48 @@ Toggle the COMMENT keyword at the beginning of an entry. @cindex tables, markup rules @cindex #+CAPTION -@cindex #+LABEL +@cindex #+NAME Both the native Org mode tables (@pxref{Tables}) and tables formatted with the @file{table.el} package will be exported properly. For Org mode tables, the lines before the first horizontal separator line will become table header lines. You can use the following lines somewhere before the table to assign a caption and a label for cross references, and in the text you can refer to -the object with @code{\ref@{tab:basic-data@}}: +the object with @code{[[tab:basic-data]]} (@pxref{Internal links}): @example #+CAPTION: This is the caption for the next table (or link) -#+LABEL: tab:basic-data +#+NAME: tab:basic-data | ... | ...| |-----|----| @end example Optionally, the caption can take the form: @example -#+CAPTION: [Caption for list of figures]@{Caption for table (or link).@} +#+CAPTION[Caption for list of tables]: Caption for table. @end example @cindex inlined images, markup rules -Some backends (HTML, @LaTeX{}, and DocBook) allow you to directly include -images into the exported document. Org does this, if a link to an image -files does not have a description part, for example @code{[[./img/a.jpg]]}. -If you wish to define a caption for the image and maybe a label for internal -cross references, make sure that the link is on a line by itself and precede -it with @code{#+CAPTION} and @code{#+LABEL} as follows: +Some back-ends allow you to directly include images into the exported +document. Org does this, if a link to an image files does not have +a description part, for example @code{[[./img/a.jpg]]}. If you wish to +define a caption for the image and maybe a label for internal cross +references, make sure that the link is on a line by itself and precede it +with @code{#+CAPTION} and @code{#+NAME} as follows: @example #+CAPTION: This is the caption for the next figure link (or table) -#+LABEL: fig:SED-HR4049 +#+NAME: fig:SED-HR4049 [[./img/a.jpg]] @end example -You may also define additional attributes for the figure. As this is -backend-specific, see the sections about the individual backends for more -information. +@noindent +Such images can be displayed within the buffer. @xref{Handling links,the +discussion of image links}. -@xref{Handling links,the discussion of image links}. +Even though images and tables are prominent examples of captioned structures, +the same caption mechanism can apply to many others (e.g., @LaTeX{} +equations, source code blocks). Depending on the export back-end, those may +or may not be handled. @node Literal examples, Include files, Images and tables, Markup @section Literal examples @@ -9302,11 +9847,11 @@ Here is an example If the example is source code from a programming language, or any other text that can be marked up by font-lock in Emacs, you can ask for the example to look like the fontified Emacs buffer@footnote{This works automatically for -the HTML backend (it requires version 1.34 of the @file{htmlize.el} package, +the HTML back-end (it requires version 1.34 of the @file{htmlize.el} package, which is distributed with Org). Fontified code chunks in @LaTeX{} can be achieved using either the listings or the @url{http://code.google.com/p/minted, minted,} package. Refer to -@code{org-export-latex-listings} documentation for details.}. This is done +@code{org-latex-listings} documentation for details.}. This is done with the @samp{src} block, where you also need to specify the name of the major mode that should be used to fontify the example@footnote{Code in @samp{src} blocks may also be evaluated either interactively or on export. @@ -9398,20 +9943,24 @@ include your @file{.emacs} file, you could use: @example #+INCLUDE: "~/.emacs" src emacs-lisp @end example + @noindent The optional second and third parameter are the markup (e.g., @samp{quote}, @samp{example}, or @samp{src}), and, if the markup is @samp{src}, the language for formatting the contents. The markup is optional; if it is not given, the text will be assumed to be in Org mode format and will be -processed normally. The include line will also allow additional keyword -parameters @code{:prefix1} and @code{:prefix} to specify prefixes for the -first line and for each following line, @code{:minlevel} in order to get -Org mode content demoted to a specified level, as well as any options -accepted by the selected markup. For example, to include a file as an item, -use +processed normally. + +Contents of the included file will belong to the same structure (headline, +item) containing the @code{INCLUDE} keyword. In particular, headlines within +the file will become children of the current section. That behaviour can be +changed by providing an additional keyword parameter, @code{:minlevel}. In +that case, all headlines in the included file will be shifted so the one with +the lowest level reaches that specified level. For example, to make a file +become a sibling of the current top-level headline, use @example -#+INCLUDE: "~/snippets/xx" :prefix1 " + " :prefix " " +#+INCLUDE: "~/my-book/chapter2.org" :minlevel 1 @end example You can also include a portion of a file by specifying a lines range using @@ -9460,21 +10009,24 @@ You can define text snippets with #+MACRO: name replacement text $1, $2 are arguments @end example -@noindent which can be referenced anywhere in the document (even in -code examples) with @code{@{@{@{name(arg1,arg2)@}@}@}}. In addition to -defined macros, @code{@{@{@{title@}@}@}}, @code{@{@{@{author@}@}@}}, etc., -will reference information set by the @code{#+TITLE:}, @code{#+AUTHOR:}, and -similar lines. Also, @code{@{@{@{date(@var{FORMAT})@}@}@}} and +@noindent which can be referenced in +paragraphs, verse blocks, table cells and some keywords with +@code{@{@{@{name(arg1,arg2)@}@}@}}@footnote{Since commas separate arguments, +commas within arguments have to be escaped with a backslash character. +Conversely, backslash characters before a comma, and only them, need to be +escaped with another backslash character.}. In addition to defined macros, +@code{@{@{@{title@}@}@}}, @code{@{@{@{author@}@}@}}, etc., will reference +information set by the @code{#+TITLE:}, @code{#+AUTHOR:}, and similar lines. +Also, @code{@{@{@{time(@var{FORMAT})@}@}@}} and @code{@{@{@{modification-time(@var{FORMAT})@}@}@}} refer to current date time and to the modification time of the file being exported, respectively. @var{FORMAT} should be a format string understood by @code{format-time-string}. -Macro expansion takes place during export, and some people use it to -construct complex HTML code. +Macro expansion takes place during export. -@node Embedded @LaTeX{}, , Macro replacement, Markup +@node Embedded @LaTeX{}, Special blocks, Macro replacement, Markup @section Embedded @LaTeX{} @cindex @TeX{} interpretation @cindex @LaTeX{} interpretation @@ -9487,7 +10039,7 @@ Donald E. Knuth's @TeX{} system. Many of the features described here as distinction.} is widely used to typeset scientific documents. Org mode supports embedding @LaTeX{} code into its files, because many academics are used to writing and reading @LaTeX{} source code, and because it can be -readily processed to produce pretty output for a number of export backends. +readily processed to produce pretty output for a number of export back-ends. @menu * Special symbols:: Greek letters and other symbols @@ -9506,11 +10058,11 @@ readily processed to produce pretty output for a number of export backends. @cindex HTML entities @cindex @LaTeX{} entities -You can use @LaTeX{} macros to insert special symbols like @samp{\alpha} to -indicate the Greek letter, or @samp{\to} to indicate an arrow. Completion -for these macros is available, just type @samp{\} and maybe a few letters, +You can use @LaTeX{}-like syntax to insert special symbols like @samp{\alpha} +to indicate the Greek letter, or @samp{\to} to indicate an arrow. Completion +for these symbols is available, just type @samp{\} and maybe a few letters, and press @kbd{M-@key{TAB}} to see possible completions. Unlike @LaTeX{} -code, Org mode allows these macros to be present without surrounding math +code, Org mode allows these symbols to be present without surrounding math delimiters, for example: @example @@ -9519,7 +10071,7 @@ Angles are written as Greek letters \alpha, \beta and \gamma. @vindex org-entities During export, these symbols will be transformed into the native format of -the exporter backend. Strings like @code{\alpha} will be exported as +the exporter back-end. Strings like @code{\alpha} will be exported as @code{α} in the HTML output, and as @code{$\alpha$} in the @LaTeX{} output. Similarly, @code{\nbsp} will become @code{ } in HTML and @code{~} in @LaTeX{}. If you need such a symbol inside a word, terminate it @@ -9531,12 +10083,13 @@ A large number of entities is provided, with names taken from both HTML and @samp{...} are all converted into special commands creating hyphens of different lengths or a compact set of dots. -If you would like to see entities displayed as UTF8 characters, use the +If you would like to see entities displayed as UTF-8 characters, use the following command@footnote{You can turn this on by default by setting the variable @code{org-pretty-entities}, or on a per-file base with the @code{#+STARTUP} option @code{entitiespretty}.}: @table @kbd +@cindex @code{entitiespretty}, STARTUP keyword @kindex C-c C-x \ @item C-c C-x \ Toggle display of entities as UTF-8 characters. This does not change the @@ -9549,31 +10102,23 @@ for display purposes only. @cindex subscript @cindex superscript -Just like in @LaTeX{}, @samp{^} and @samp{_} are used to indicate super- -and subscripts. Again, these can be used without embedding them in -math-mode delimiters. To increase the readability of ASCII text, it is -not necessary (but OK) to surround multi-character sub- and superscripts -with curly braces. For example +Just like in @LaTeX{}, @samp{^} and @samp{_} are used to indicate super- and +subscripts. Again, these can be used without embedding them in math-mode +delimiters. To increase the readability of ASCII text, it is not necessary +(but OK) to surround multi-character sub- and superscripts with curly braces. +For example @example The mass of the sun is M_sun = 1.989 x 10^30 kg. The radius of the sun is R_@{sun@} = 6.96 x 10^8 m. @end example -@vindex org-export-with-sub-superscripts -To avoid interpretation as raised or lowered text, you can quote @samp{^} and -@samp{_} with a backslash: @samp{\^} and @samp{\_}. If you write a text -where the underscore is often used in a different context, Org's convention -to always interpret these as subscripts can get in your way. Configure the -variable @code{org-export-with-sub-superscripts} to globally change this -convention, or use, on a per-file basis: - -@example -#+OPTIONS: ^:@{@} -@end example - -@noindent With this setting, @samp{a_b} will not be interpreted as a -subscript, but @samp{a_@{b@}} will. +@vindex org-use-sub-superscripts +If you write a text where the underscore is often used in a different +context, Org's convention to always interpret these as subscripts can get in +your way. Configure the variable @code{org-use-sub-superscripts} to change +this convention. For example, when setting this variable to @code{@{@}}, +@samp{a_b} will not be interpreted as a subscript, but @samp{a_@{b@}} will. @table @kbd @kindex C-c C-x \ @@ -9589,31 +10134,31 @@ format sub- and superscripts in a WYSIWYM way. @vindex org-format-latex-header Going beyond symbols and sub- and superscripts, a full formula language is needed. Org mode can contain @LaTeX{} math fragments, and it supports ways -to process these for several export backends. When exporting to @LaTeX{}, +to process these for several export back-ends. When exporting to @LaTeX{}, the code is obviously left as it is. When exporting to HTML, Org invokes the @uref{http://www.mathjax.org, MathJax library} (@pxref{Math formatting in HTML export}) to process and display the math@footnote{If you plan to use this regularly or on pages with significant page views, you should install -@file{MathJax} on your own -server in order to limit the load of our server.}. Finally, it can also -process the mathematical expressions into images@footnote{For this to work -you need to be on a system with a working @LaTeX{} installation. You also -need the @file{dvipng} program or the @file{convert}, respectively available -at @url{http://sourceforge.net/projects/dvipng/} and from the -@file{imagemagick} suite. The @LaTeX{} header that will be used when -processing a fragment can be configured with the variable -@code{org-format-latex-header}.} that can be displayed in a browser or in -DocBook documents. +@file{MathJax} on your own server in order to limit the load of our server.}. +Finally, it can also process the mathematical expressions into +images@footnote{For this to work you need to be on a system with a working +@LaTeX{} installation. You also need the @file{dvipng} program or the +@file{convert}, respectively available at +@url{http://sourceforge.net/projects/dvipng/} and from the @file{imagemagick} +suite. The @LaTeX{} header that will be used when processing a fragment can +be configured with the variable @code{org-format-latex-header}.} that can be +displayed in a browser. @LaTeX{} fragments don't need any special marking at all. The following snippets will be identified as @LaTeX{} source code: @itemize @bullet @item Environments of any kind@footnote{When @file{MathJax} is used, only the -environment recognized by @file{MathJax} will be processed. When -@file{dvipng} is used to create images, any @LaTeX{} environments will be -handled.}. The only requirement is that the @code{\begin} statement appears -on a new line, preceded by only whitespace. +environments recognized by @file{MathJax} will be processed. When +@file{dvipng} program or @file{imagemagick} suite is used to create images, +any @LaTeX{} environment will be handled.}. The only requirement is that the +@code{\begin} and @code{\end} statements appear on a new line, at the +beginning of the line or after whitespaces only. @item Text within the usual @LaTeX{} math delimiters. To avoid conflicts with currency specifications, single @samp{$} characters are only recognized as @@ -9627,40 +10172,44 @@ For the other delimiters, there is no such restriction, so when in doubt, use @noindent For example: @example -\begin@{equation@} % arbitrary environments, -x=\sqrt@{b@} % even tables, figures -\end@{equation@} % etc +\begin@{equation@} +x=\sqrt@{b@} +\end@{equation@} If $a^2=b$ and \( b=2 \), then the solution must be either $$ a=+\sqrt@{2@} $$ or \[ a=-\sqrt@{2@} \]. @end example -@noindent -@vindex org-format-latex-options -If you need any of the delimiter ASCII sequences for other purposes, you -can configure the option @code{org-format-latex-options} to deselect the -ones you do not wish to have interpreted by the @LaTeX{} converter. +@c FIXME +@c @noindent +@c @vindex org-format-latex-options +@c If you need any of the delimiter ASCII sequences for other purposes, you +@c can configure the option @code{org-format-latex-options} to deselect the +@c ones you do not wish to have interpreted by the @LaTeX{} converter. -@vindex org-export-with-LaTeX-fragments +@vindex org-export-with-latex @LaTeX{} processing can be configured with the variable -@code{org-export-with-LaTeX-fragments}. The default setting is @code{t} -which means @file{MathJax} for HTML, and no processing for DocBook, ASCII and -@LaTeX{} backends. You can also set this variable on a per-file basis using one -of these lines: +@code{org-export-with-latex}. The default setting is @code{t} which means +@file{MathJax} for HTML, and no processing for ASCII and @LaTeX{} back-ends. +You can also set this variable on a per-file basis using one of these +lines: @example -#+OPTIONS: LaTeX:t @r{Do the right thing automatically (MathJax)} -#+OPTIONS: LaTeX:dvipng @r{Force using dvipng images} -#+OPTIONS: LaTeX:nil @r{Do not process @LaTeX{} fragments at all} -#+OPTIONS: LaTeX:verbatim @r{Verbatim export, for jsMath or so} +#+OPTIONS: tex:t @r{Do the right thing automatically (MathJax)} +#+OPTIONS: tex:nil @r{Do not process @LaTeX{} fragments at all} +#+OPTIONS: tex:verbatim @r{Verbatim export, for jsMath or so} @end example @node Previewing @LaTeX{} fragments, CDLaTeX mode, @LaTeX{} fragments, Embedded @LaTeX{} @subsection Previewing @LaTeX{} fragments @cindex @LaTeX{} fragments, preview -If you have @file{dvipng} installed, @LaTeX{} fragments can be processed to -produce preview images of the typeset expressions: +@vindex org-latex-create-formula-image-program +If you have @file{dvipng} or @file{imagemagick} installed@footnote{Choose the +converter by setting the variable +@code{org-latex-create-formula-image-program} accordingly.}, @LaTeX{} +fragments can be processed to produce preview images of the typeset +expressions: @table @kbd @kindex C-c C-x C-l @@ -9682,6 +10231,19 @@ some aspects of the preview. In particular, the @code{:scale} (and for HTML export, @code{:html-scale}) property can be used to adjust the size of the preview images. +@vindex org-startup-with-latex-preview +You can turn on the previewing of all @LaTeX{} fragments in a file with + +@example +#+STARTUP: latexpreview +@end example + +To disable it, simply use + +@example +#+STARTUP: nolatexpreview +@end example + @node CDLaTeX mode, , Previewing @LaTeX{} fragments, Embedded @LaTeX{} @subsection Using CD@LaTeX{} to enter math @cindex CD@LaTeX{} @@ -9694,7 +10256,7 @@ some of the features of CD@LaTeX{} mode. You need to install AUC@TeX{}) from @url{http://www.astro.uva.nl/~dominik/Tools/cdlatex}. Don't use CD@LaTeX{} mode itself under Org mode, but use the light version @code{org-cdlatex-mode} that comes as part of Org mode. Turn it -on for the current buffer with @code{M-x org-cdlatex-mode}, or for all +on for the current buffer with @kbd{M-x org-cdlatex-mode RET}, or for all Org files with @lisp @@ -9719,7 +10281,7 @@ the second brace. Even outside fragments, @key{TAB} will expand environment abbreviations at the beginning of a line. For example, if you write @samp{equ} at the beginning of a line and press @key{TAB}, this abbreviation will be expanded to an @code{equation} environment. -To get a list of all abbreviations, type @kbd{M-x cdlatex-command-help}. +To get a list of all abbreviations, type @kbd{M-x cdlatex-command-help RET}. @item @kindex _ @kindex ^ @@ -9743,235 +10305,394 @@ modification will work only inside @LaTeX{} fragments; outside the quote is normal. @end itemize +@node Special blocks, , Embedded @LaTeX{}, Markup +@section Special blocks +@cindex Special blocks + +Org syntax includes pre-defined blocks (@pxref{Paragraphs} and @ref{Literal +examples}). It is also possible to create blocks containing raw code +targeted at a specific back-ends (e.g., @samp{#+BEGIN_LATEX}). + +Any other block is a @emph{special block}. Each export back-end decides if +they should be exported, and how. When the block is ignored, its contents +are still exported, as if the block were not there. For example, when +exporting a @samp{#+BEGIN_TEST} block, HTML back-end wraps its contents +within @samp{
} tag. Refer to back-end specific +documentation for more information. + @node Exporting, Publishing, Markup, Top @chapter Exporting @cindex exporting -Org mode documents can be exported into a variety of other formats. For -printing and sharing of notes, ASCII export produces a readable and simple -version of an Org file. HTML export allows you to publish a notes file on -the web, while the XOXO format provides a solid base for exchange with a -broad range of other applications. @LaTeX{} export lets you use Org mode and -its structured editing functions to easily create @LaTeX{} files. DocBook -export makes it possible to convert Org files to many other formats using -DocBook tools. OpenDocument Text (ODT) export allows seamless -collaboration across organizational boundaries. For project management you -can create gantt and resource charts by using TaskJuggler export. To -incorporate entries with associated times like deadlines or appointments into -a desktop calendar program like iCal, Org mode can also produce extracts in -the iCalendar format. Currently, Org mode only supports export, not import of -these different formats. - -Org supports export of selected regions when @code{transient-mark-mode} is -enabled (default in Emacs 23). +The Org mode export facilities can be used to export Org documents or parts +of Org documents to a variety of other formats. In addition, these +facilities can be used with @code{orgtbl-mode} and/or @code{orgstruct-mode} +in foreign buffers so you can author tables and lists in Org syntax and +convert them in place to the target language. + +ASCII export produces a readable and simple version of an Org file for +printing and sharing notes. HTML export allows you to easily publish notes +on the web, or to build full-fledged websites. @LaTeX{} export lets you use +Org mode and its structured editing functions to create arbitrarily complex +@LaTeX{} files for any kind of document. OpenDocument Text (ODT) export +allows seamless collaboration across organizational boundaries. Markdown +export lets you seamlessly collaborate with other developers. Finally, iCal +export can extract entries with deadlines or appointments to produce a file +in the iCalendar format. @menu -* Selective export:: Using tags to select and exclude trees -* Export options:: Per-file export settings -* The export dispatcher:: How to access exporter commands +* The Export Dispatcher:: The main exporter interface +* Export back-ends:: Built-in export formats +* Export settings:: Generic export settings * ASCII/Latin-1/UTF-8 export:: Exporting to flat files with encoding +* Beamer export:: Exporting as a Beamer presentation * HTML export:: Exporting to HTML * @LaTeX{} and PDF export:: Exporting to @LaTeX{}, and processing to PDF -* DocBook export:: Exporting to DocBook +* Markdown export:: Exporting to Markdown * OpenDocument Text export:: Exporting to OpenDocument Text -* TaskJuggler export:: Exporting to TaskJuggler -* Freemind export:: Exporting to Freemind mind maps -* XOXO export:: Exporting to XOXO -* iCalendar export:: Exporting in iCalendar format +* iCalendar export:: Exporting to iCalendar +* Other built-in back-ends:: Exporting to @code{Texinfo}, a man page, or Org +* Export in foreign buffers:: Author tables in lists in Org syntax +* Advanced configuration:: Fine-tuning the export output @end menu -@node Selective export, Export options, Exporting, Exporting -@section Selective export -@cindex export, selective by tags or TODO keyword +@node The Export Dispatcher, Export back-ends, Exporting, Exporting +@section The Export Dispatcher +@vindex org-export-dispatch-use-expert-ui +@cindex Export, dispatcher + +The main entry point for export related tasks is the dispatcher, a +hierarchical menu from which it is possible to select an export format and +toggle export options@footnote{It is also possible to use a less intrusive +interface by setting @code{org-export-dispatch-use-expert-ui} to a +non-@code{nil} value. In that case, only a prompt is visible from the +minibuffer. From there one can still switch back to regular menu by pressing +@key{?}.} from which it is possible to select an export format and to toggle +export options. + +@c @quotation +@table @asis +@orgcmd{C-c C-e,org-export-dispatch} -@vindex org-export-select-tags -@vindex org-export-exclude-tags -@cindex org-export-with-tasks -You may use tags to select the parts of a document that should be exported, -or to exclude parts from export. This behavior is governed by two variables: -@code{org-export-select-tags} and @code{org-export-exclude-tags}, -respectively defaulting to @code{'(:export:)} and @code{'(:noexport:)}. +Dispatch for export and publishing commands. When called with a @kbd{C-u} +prefix argument, repeat the last export command on the current buffer while +preserving toggled options. If the current buffer hasn't changed and subtree +export was activated, the command will affect that same subtree. +@end table +@c @end quotation -@enumerate -@item -Org first checks if any of the @emph{select} tags is present in the -buffer. If yes, all trees that do not carry one of these tags will be -excluded. If a selected tree is a subtree, the heading hierarchy above it -will also be selected for export, but not the text below those headings. +Normally the entire buffer is exported, but if there is an active region +only that part of the buffer will be exported. -@item -If none of the select tags is found, the whole buffer will be selected for -export. +Several export options (@pxref{Export settings}) can be toggled from the +export dispatcher with the following key combinations: -@item -Finally, all subtrees that are marked by any of the @emph{exclude} tags will -be removed from the export buffer. -@end enumerate +@table @kbd +@item C-a +@vindex org-export-async-init-file +Toggle asynchronous export. Asynchronous export uses an external Emacs +process that is configured with a specified initialization file. -The variable @code{org-export-with-tasks} can be configured to select which -kind of tasks should be included for export. See the docstring of the -variable for more information. +While exporting asynchronously, the output is not displayed. It is stored in +a list called ``the export stack'', and can be viewed from there. The stack +can be reached by calling the dispatcher with a double @kbd{C-u} prefix +argument, or with @kbd{&} key from the dispatcher. -@node Export options, The export dispatcher, Selective export, Exporting -@section Export options -@cindex options, for export +@vindex org-export-in-background +To make this behaviour the default, customize the variable +@code{org-export-in-background}. -@cindex completion, of option keywords -The exporter recognizes special lines in the buffer which provide -additional information. These lines may be put anywhere in the file. -The whole set of lines can be inserted into the buffer with @kbd{C-c -C-e t}. For individual lines, a good way to make sure the keyword is -correct is to type @samp{#+} and then use @kbd{M-@key{TAB}} completion -(@pxref{Completion}). For a summary of other in-buffer settings not -specifically related to export, see @ref{In-buffer settings}. -In particular, note that you can place commonly-used (export) options in -a separate file which can be included using @code{#+SETUPFILE}. +@item C-b +Toggle body-only export. Its effect depends on the back-end used. +Typically, if the back-end has a header section (like @code{...} +in the HTML back-end), a body-only export will not include this header. + +@item C-s +@vindex org-export-initial-scope +Toggle subtree export. The top heading becomes the document title. + +You can change the default state of this option by setting +@code{org-export-initial-scope}. + +@item C-v +Toggle visible-only export. Only export the text that is currently +visible, i.e. not hidden by outline visibility in the buffer. -@table @kbd -@orgcmd{C-c C-e t,org-insert-export-options-template} -Insert template with export options, see example below. @end table -@cindex #+TITLE -@cindex #+AUTHOR -@cindex #+DATE -@cindex #+EMAIL -@cindex #+DESCRIPTION -@cindex #+KEYWORDS -@cindex #+LANGUAGE -@cindex #+TEXT -@cindex #+OPTIONS -@cindex #+BIND -@cindex #+LINK_UP -@cindex #+LINK_HOME -@cindex #+EXPORT_SELECT_TAGS -@cindex #+EXPORT_EXCLUDE_TAGS -@cindex #+XSLT -@cindex #+LaTeX_HEADER +@vindex org-export-copy-to-kill-ring +With the exception of asynchronous export, a successful export process writes +its output to the kill-ring. You can configure this behavior by altering the +option @code{org-export-copy-to-kill-ring}. + +@node Export back-ends, Export settings, The Export Dispatcher, Exporting +@section Export back-ends +@cindex Export, back-ends + +An export back-end is a library that translates Org syntax into a foreign +format. An export format is not available until the proper back-end has been +loaded. + +@vindex org-export-backends +By default, the following four back-ends are loaded: @code{ascii}, +@code{html}, @code{icalendar} and @code{latex}. It is possible to add more +(or remove some) by customizing @code{org-export-backends}. + +Built-in back-ends include: + +@itemize +@item ascii (ASCII format) +@item beamer (@LaTeX{} Beamer format) +@item html (HTML format) +@item icalendar (iCalendar format) +@item latex (@LaTeX{} format) +@item man (Man page format) +@item md (Markdown format) +@item odt (OpenDocument Text format) +@item texinfo (Texinfo format) +@end itemize + +Other back-ends might be found in the @code{contrib/} directory +(@pxref{Installation}). + +@node Export settings, ASCII/Latin-1/UTF-8 export, Export back-ends, Exporting +@section Export settings +@cindex Export, settings + +Export options can be set: globally with variables; for an individual file by +making variables buffer-local with in-buffer settings (@pxref{In-buffer +settings}), by setting individual keywords, or by specifying them in a +compact form with the @code{#+OPTIONS} keyword; or for a tree by setting +properties (@pxref{Properties and Columns}). Options set at a specific level +override options set at a more general level. + +@cindex #+SETUPFILE +In-buffer settings may appear anywhere in the file, either directly or +indirectly through a file included using @samp{#+SETUPFILE: filename} syntax. +Option keyword sets tailored to a particular back-end can be inserted from +the export dispatcher (@pxref{The Export Dispatcher}) using the @code{Insert +template} command by pressing @key{#}. To insert keywords individually, +a good way to make sure the keyword is correct is to type @code{#+} and then +to use @kbd{M-} for completion. + +The export keywords available for every back-end, and their equivalent global +variables, include: + +@table @samp +@item AUTHOR @vindex user-full-name +The document author (@code{user-full-name}). + +@item CREATOR +@vindex org-export-creator-string +Entity responsible for output generation (@code{org-export-creator-string}). + +@item DATE +@vindex org-export-date-timestamp-format +A date or a time-stamp@footnote{The variable +@code{org-export-date-timestamp-format} defines how this time-stamp will be +exported.}. + +@item DESCRIPTION +The document description. Back-ends handle it as they see fit (e.g., for the +XHTML meta tag), if at all. You can use several such keywords for long +descriptions. + +@item EMAIL @vindex user-mail-address +The email address (@code{user-mail-address}). + +@item KEYWORDS +The keywords defining the contents of the document. Back-ends handle it as +they see fit (e.g., for the XHTML meta tag), if at all. You can use several +such keywords if the list is long. + +@item LANGUAGE @vindex org-export-default-language -@vindex org-export-date-timestamp-format -@example -#+TITLE: the title to be shown (default is the buffer name) -#+AUTHOR: the author (default taken from @code{user-full-name}) -#+DATE: a date, an Org timestamp@footnote{@code{org-export-date-timestamp-format} defines how this timestamp will be exported.}, or a format string for @code{format-time-string} -#+EMAIL: his/her email address (default from @code{user-mail-address}) -#+DESCRIPTION: the page description, e.g., for the XHTML meta tag -#+KEYWORDS: the page keywords, e.g., for the XHTML meta tag -#+LANGUAGE: language for HTML, e.g., @samp{en} (@code{org-export-default-language}) -#+TEXT: Some descriptive text to be inserted at the beginning. -#+TEXT: Several lines may be given. -#+OPTIONS: H:2 num:t toc:t \n:nil @@:t ::t |:t ^:t f:t TeX:t ... -#+BIND: lisp-var lisp-val, e.g., @code{org-export-latex-low-levels itemize} - @r{You need to confirm using these, or configure @code{org-export-allow-BIND}} -#+LINK_UP: the ``up'' link of an exported page -#+LINK_HOME: the ``home'' link of an exported page -#+LaTeX_HEADER: extra line(s) for the @LaTeX{} header, like \usepackage@{xyz@} -#+EXPORT_SELECT_TAGS: Tags that select a tree for export -#+EXPORT_EXCLUDE_TAGS: Tags that exclude a tree from export -#+XSLT: the XSLT stylesheet used by DocBook exporter to generate FO file -@end example +The language used for translating some strings +(@code{org-export-default-language}). E.g., @samp{#+LANGUAGE: fr} will tell +Org to translate @emph{File} (english) into @emph{Fichier} (french) in the +clocktable. -@noindent -The @code{#+OPTIONS} line is a compact@footnote{If you want to configure many options -this way, you can use several @code{#+OPTIONS} lines.} form to specify export -settings. Here you can: -@cindex headline levels -@cindex section-numbers -@cindex table of contents -@cindex line-break preservation -@cindex quoted HTML tags -@cindex fixed-width sections -@cindex tables -@cindex @TeX{}-like syntax for sub- and superscripts -@cindex footnotes -@cindex special strings -@cindex emphasized text -@cindex @TeX{} macros -@cindex @LaTeX{} fragments -@cindex author info, in export -@cindex time info, in export -@vindex org-export-plist-vars -@vindex org-export-author-info -@vindex org-export-creator-info -@vindex org-export-email-info +@item SELECT_TAGS +@vindex org-export-select-tags +The tags that select a tree for export (@code{org-export-select-tags}). The +default value is @code{:export:}. Within a subtree tagged with +@code{:export:}, you can still exclude entries with @code{:noexport:} (see +below). + +@item EXCLUDE_TAGS +The tags that exclude a tree from export (@code{org-export-exclude-tags}). +The default value is @code{:noexport:}. Entries with the @code{:noexport:} +tag will be unconditionally excluded from the export, even if they have an +@code{:export:} tag. + +@item TITLE +The title to be shown (otherwise derived from buffer's name). You can use +several such keywords for long titles. +@end table + +The @code{#+OPTIONS} keyword is a compact@footnote{If you want to configure +many options this way, you can use several @code{#+OPTIONS} lines.} form that +recognizes the following arguments: + +@table @code +@item ': +@vindex org-export-with-smart-quotes +Toggle smart quotes (@code{org-export-with-smart-quotes}). + +@item *: +Toggle emphasized text (@code{org-export-with-emphasize}). + +@item -: +@vindex org-export-with-special-strings +Toggle conversion of special strings +(@code{org-export-with-special-strings}). + +@item :: +@vindex org-export-with-fixed-width +Toggle fixed-width sections +(@code{org-export-with-fixed-width}). + +@item <: +@vindex org-export-with-timestamps +Toggle inclusion of any time/date active/inactive stamps +(@code{org-export-with-timestamps}). + +@item : +@vindex org-export-preserve-breaks +Toggle line-break-preservation (@code{org-export-preserve-breaks}). + +@item ^: +@vindex org-export-with-sub-superscripts +Toggle @TeX{}-like syntax for sub- and superscripts. If you write "^:@{@}", +@samp{a_@{b@}} will be interpreted, but the simple @samp{a_b} will be left as +it is (@code{org-export-with-sub-superscripts}). + +@item arch: +@vindex org-export-with-archived-trees +Configure export of archived trees. Can be set to @code{headline} to only +process the headline, skipping its contents +(@code{org-export-with-archived-trees}). + +@item author: +@vindex org-export-with-author +Toggle inclusion of author name into exported file +(@code{org-export-with-author}). + +@item c: +@vindex org-export-with-clocks +Toggle inclusion of CLOCK keywords (@code{org-export-with-clocks}). + +@item creator: +@vindex org-export-with-creator +Configure inclusion of creator info into exported file. It may be set to +@code{comment} (@code{org-export-with-creator}). + +@item d: +@vindex org-export-with-drawers +Toggle inclusion of drawers, or list drawers to include +(@code{org-export-with-drawers}). + +@item e: +@vindex org-export-with-entities +Toggle inclusion of entities (@code{org-export-with-entities}). + +@item email: +@vindex org-export-with-email +Toggle inclusion of the author's e-mail into exported file +(@code{org-export-with-email}). + +@item f: +@vindex org-export-with-footnotes +Toggle the inclusion of footnotes (@code{org-export-with-footnotes}). + +@item H: +@vindex org-export-headline-levels +Set the number of headline levels for export +(@code{org-export-headline-levels}). Below that level, headlines are treated +differently. In most back-ends, they become list items. + +@item inline: +@vindex org-export-with-inlinetasks +Toggle inclusion of inlinetasks (@code{org-export-with-inlinetasks}). + +@item num: +@vindex org-export-with-section-numbers +Toggle section-numbers (@code{org-export-with-section-numbers}). It can also +be set to a number @samp{n}, so only headlines at that level or above will be +numbered. + +@item p: +@vindex org-export-with-planning +Toggle export of planning information (@code{org-export-with-planning}). +``Planning information'' is the line containing the @code{SCHEDULED:}, the +@code{DEADLINE:} or the @code{CLOSED:} cookies or a combination of them. + +@item pri: +@vindex org-export-with-priority +Toggle inclusion of priority cookies (@code{org-export-with-priority}). + +@item stat: +@vindex org-export-with-statistics-cookies +Toggle inclusion of statistics cookies +(@code{org-export-with-statistics-cookies}). + +@item tags: +@vindex org-export-with-tags +Toggle inclusion of tags, may also be @code{not-in-toc} +(@code{org-export-with-tags}). + +@item tasks: +@vindex org-export-with-tasks +Toggle inclusion of tasks (TODO items), can be @code{nil} to remove all +tasks, @code{todo} to remove DONE tasks, or a list of keywords to keep +(@code{org-export-with-tasks}). + +@item tex: +@vindex org-export-with-latex +Configure export of @LaTeX{} fragments and environments. It may be set to +@code{verbatim} (@code{org-export-with-latex}). + +@item timestamp: @vindex org-export-time-stamp-file -@example -H: @r{set the number of headline levels for export} -num: @r{turn on/off section-numbers} -toc: @r{turn on/off table of contents, or set level limit (integer)} -\n: @r{turn on/off line-break-preservation (DOES NOT WORK)} -@@: @r{turn on/off quoted HTML tags} -:: @r{turn on/off fixed-width sections} -|: @r{turn on/off tables} -^: @r{turn on/off @TeX{}-like syntax for sub- and superscripts. If} - @r{you write "^:@{@}", @code{a_@{b@}} will be interpreted, but} - @r{the simple @code{a_b} will be left as it is.} --: @r{turn on/off conversion of special strings.} -f: @r{turn on/off footnotes like this[1].} -todo: @r{turn on/off inclusion of TODO keywords into exported text} -tasks: @r{turn on/off inclusion of tasks (TODO items), can be nil to remove} - @r{all tasks, @code{todo} to remove DONE tasks, or list of kwds to keep} -pri: @r{turn on/off priority cookies} -tags: @r{turn on/off inclusion of tags, may also be @code{not-in-toc}} -<: @r{turn on/off inclusion of any time/date stamps like DEADLINES} -*: @r{turn on/off emphasized text (bold, italic, underlined)} -TeX: @r{turn on/off simple @TeX{} macros in plain text} -LaTeX: @r{configure export of @LaTeX{} fragments. Default @code{auto}} -skip: @r{turn on/off skipping the text before the first heading} -author: @r{turn on/off inclusion of author name/email into exported file} -email: @r{turn on/off inclusion of author email into exported file} -creator: @r{turn on/off inclusion of creator info into exported file} -timestamp: @r{turn on/off inclusion creation time into exported file} -d: @r{turn on/off inclusion of drawers, or list drawers to include} -@end example -@noindent -These options take effect in both the HTML and @LaTeX{} export, except for -@code{TeX} and @code{LaTeX} options, which are respectively @code{t} and -@code{nil} for the @LaTeX{} export. - -The default values for these and many other options are given by a set of -variables. For a list of such variables, the corresponding OPTIONS keys and -also the publishing keys (@pxref{Project alist}), see the constant -@code{org-export-plist-vars}. - -When exporting only a single subtree by selecting it with @kbd{C-c @@} before -calling an export command, the subtree can overrule some of the file's export -settings with properties @code{EXPORT_FILE_NAME}, @code{EXPORT_TITLE}, -@code{EXPORT_TEXT}, @code{EXPORT_AUTHOR}, @code{EXPORT_DATE}, and -@code{EXPORT_OPTIONS}. - -@node The export dispatcher, ASCII/Latin-1/UTF-8 export, Export options, Exporting -@section The export dispatcher -@cindex dispatcher, for export commands - -All export commands can be reached using the export dispatcher, which is a -prefix key that prompts for an additional key specifying the command. -Normally the entire file is exported, but if there is an active region that -contains one outline tree, the first heading is used as document title and -the subtrees are exported. +Toggle inclusion of the creation time into exported file +(@code{org-export-time-stamp-file}). -@table @kbd -@orgcmd{C-c C-e,org-export} -@vindex org-export-run-in-background -Dispatcher for export and publishing commands. Displays a help-window -listing the additional key(s) needed to launch an export or publishing -command. The prefix arg is passed through to the exporter. A double prefix -@kbd{C-u C-u} causes most commands to be executed in the background, in a -separate Emacs process@footnote{To make this behavior the default, customize -the variable @code{org-export-run-in-background}.}. -@orgcmd{C-c C-e v,org-export-visible} -Like @kbd{C-c C-e}, but only export the text that is currently visible -(i.e., not hidden by outline visibility). -@orgcmd{C-u C-u C-c C-e,org-export} -@vindex org-export-run-in-background -Call the exporter, but reverse the setting of -@code{org-export-run-in-background}, i.e., request background processing if -not set, or force processing in the current Emacs process if set. +@item toc: +@vindex org-export-with-toc +Toggle inclusion of the table of contents, or set the level limit +(@code{org-export-with-toc}). + +@item todo: +@vindex org-export-with-todo-keywords +Toggle inclusion of TODO keywords into exported text +(@code{org-export-with-todo-keywords}). + +@item |: +@vindex org-export-with-tables +Toggle inclusion of tables (@code{org-export-with-tables}). @end table -@node ASCII/Latin-1/UTF-8 export, HTML export, The export dispatcher, Exporting +@cindex property, EXPORT_FILE_NAME +When exporting only a subtree, each of the previous keywords@footnote{With +the exception of @samp{SETUPFILE}.} can be overriden locally by special node +properties. These begin with @samp{EXPORT_}, followed by the name of the +keyword they supplant. For example, @samp{DATE} and @samp{OPTIONS} keywords +become, respectively, @samp{EXPORT_DATE} and @samp{EXPORT_OPTIONS} +properties. Subtree export also supports the self-explicit +@samp{EXPORT_FILE_NAME} property@footnote{There is no buffer-wide equivalent +for this property. The file name in this case is derived from the file +associated to the buffer, if possible, or asked to the user otherwise.}. + +@cindex #+BIND +@vindex org-export-allow-bind-keywords +If @code{org-export-allow-bind-keywords} is non-@code{nil}, Emacs variables +can become buffer-local during export by using the BIND keyword. Its syntax +is @samp{#+BIND: variable value}. This is particularly useful for in-buffer +settings that cannot be changed using specific keywords. + +@node ASCII/Latin-1/UTF-8 export, Beamer export, Export settings, Exporting @section ASCII/Latin-1/UTF-8 export @cindex ASCII export @cindex Latin-1 export @@ -9981,58 +10702,277 @@ ASCII export produces a simple and very readable version of an Org mode file, containing only plain ASCII@. Latin-1 and UTF-8 export augment the file with special characters and symbols available in these encodings. -@cindex region, active -@cindex active region -@cindex transient-mark-mode +@vindex org-ascii-links-to-notes +Links are exported in a footnote-like style, with the descriptive part in the +text and the link in a note before the next heading. See the variable +@code{org-ascii-links-to-notes} for details and other options. + +@subheading ASCII export commands + @table @kbd -@orgcmd{C-c C-e a,org-export-as-ascii} -@cindex property, EXPORT_FILE_NAME +@orgcmd{C-c C-e t a/l/u,org-ascii-export-to-ascii} Export as an ASCII file. For an Org file, @file{myfile.org}, the ASCII file -will be @file{myfile.txt}. The file will be overwritten without -warning. If there is an active region@footnote{This requires -@code{transient-mark-mode} be turned on.}, only the region will be -exported. If the selected region is a single tree@footnote{To select the -current subtree, use @kbd{C-c @@}.}, the tree head will -become the document title. If the tree head entry has or inherits an -@code{EXPORT_FILE_NAME} property, that name will be used for the -export. -@orgcmd{C-c C-e A,org-export-as-ascii-to-buffer} +will be @file{myfile.txt}. The file will be overwritten without warning. +When the original file is @file{myfile.txt}, the resulting file becomes +@file{myfile.txt.txt} in order to prevent data loss. +@orgcmd{C-c C-e t A/L/U,org-ascii-export-as-ascii} Export to a temporary buffer. Do not create a file. -@orgcmd{C-c C-e n,org-export-as-latin1} -@xorgcmd{C-c C-e N,org-export-as-latin1-to-buffer} -Like the above commands, but use Latin-1 encoding. -@orgcmd{C-c C-e u,org-export-as-utf8} -@xorgcmd{C-c C-e U,org-export-as-utf8-to-buffer} -Like the above commands, but use UTF-8 encoding. -@item C-c C-e v a/n/u -Export only the visible part of the document. @end table -@cindex headline levels, for exporting -In the exported version, the first 3 outline levels will become -headlines, defining a general document structure. Additional levels -will be exported as itemized lists. If you want that transition to occur -at a different level, specify it with a prefix argument. For example, +@subheading Header and sectioning structure + +In the exported version, the first three outline levels become headlines, +defining a general document structure. Additional levels are exported as +lists. The transition can also occur at a different level (@pxref{Export +settings}). + +@subheading Quoting ASCII text + +You can insert text that will only appear when using @code{ASCII} back-end +with the following constructs: + +@cindex #+ASCII +@cindex #+BEGIN_ASCII +@example +Text @@@@ascii:and additional text@@@@ within a paragraph. + +#+ASCII: Some text + +#+BEGIN_ASCII +All lines in this block will appear only when using this back-end. +#+END_ASCII +@end example + +@subheading ASCII specific attributes +@cindex #+ATTR_ASCII +@cindex horizontal rules, in ASCII export + +@code{ASCII} back-end only understands one attribute, @code{:width}, which +specifies the length, in characters, of a given horizontal rule. It must be +specified using an @code{ATTR_ASCII} line, directly preceding the rule. + +@example +#+ATTR_ASCII: :width 10 +----- +@end example + +@node Beamer export, HTML export, ASCII/Latin-1/UTF-8 export, Exporting +@section Beamer export +@cindex Beamer export + +The @LaTeX{} class @emph{Beamer} allows production of high quality +presentations using @LaTeX{} and pdf processing. Org mode has special +support for turning an Org mode file or tree into a Beamer presentation. + +@subheading Beamer export commands + +@table @kbd +@orgcmd{C-c C-e l b,org-beamer-export-to-latex} +Export as a @LaTeX{} file. For an Org file @file{myfile.org}, the @LaTeX{} +file will be @file{myfile.tex}. The file will be overwritten without +warning. +@orgcmd{C-c C-e l B,org-beamer-export-as-latex} +Export to a temporary buffer. Do not create a file. +@orgcmd{C-c C-e l P,org-beamer-export-to-pdf} +Export as @LaTeX{} and then process to PDF. +@item C-c C-e l O +Export as @LaTeX{} and then process to PDF, then open the resulting PDF file. +@end table + +@subheading Sectioning, Frames and Blocks + +Any tree with not-too-deep level nesting should in principle be exportable as +a Beamer presentation. Headlines fall into three categories: sectioning +elements, frames and blocks. + +@itemize @minus +@item +@vindex org-beamer-frame-level +Headlines become frames when their level is equal to +@code{org-beamer-frame-level} or @code{H} value in an @code{OPTIONS} line +(@pxref{Export settings}). + +@cindex property, BEAMER_ENV +Though, if a headline in the current tree has a @code{BEAMER_ENV} property +set to either to @code{frame} or @code{fullframe}, its level overrides the +variable. A @code{fullframe} is a frame with an empty (ignored) title. + +@item +@vindex org-beamer-environments-default +@vindex org-beamer-environments-extra +All frame's children become @code{block} environments. Special block types +can be enforced by setting headline's @code{BEAMER_ENV} property@footnote{If +this property is set, the entry will also get a @code{:B_environment:} tag to +make this visible. This tag has no semantic meaning, it is only a visual +aid.} to an appropriate value (see @code{org-beamer-environments-default} for +supported values and @code{org-beamer-environments-extra} for adding more). + +@item +@cindex property, BEAMER_REF +As a special case, if the @code{BEAMER_ENV} property is set to either +@code{appendix}, @code{note}, @code{noteNH} or @code{againframe}, the +headline will become, respectively, an appendix, a note (within frame or +between frame, depending on its level), a note with its title ignored or an +@code{\againframe} command. In the latter case, a @code{BEAMER_REF} property +is mandatory in order to refer to the frame being resumed, and contents are +ignored. + +Also, a headline with an @code{ignoreheading} environment will have its +contents only inserted in the output. This special value is useful to have +data between frames, or to properly close a @code{column} environment. +@end itemize + +@cindex property, BEAMER_ACT +@cindex property, BEAMER_OPT +Headlines also support @code{BEAMER_ACT} and @code{BEAMER_OPT} properties. +The former is translated as an overlay/action specification, or a default +overlay specification when enclosed within square brackets. The latter +specifies options@footnote{The @code{fragile} option is added automatically +if it contains code that requires a verbatim environment, though.} for the +current frame or block. The export back-end will automatically wrap +properties within angular or square brackets when appropriate. + +@cindex property, BEAMER_COL +Moreover, headlines handle the @code{BEAMER_COL} property. Its value should +be a decimal number representing the width of the column as a fraction of the +total text width. If the headline has no specific environment, its title +will be ignored and its contents will fill the column created. Otherwise, +the block will fill the whole column and the title will be preserved. Two +contiguous headlines with a non-@code{nil} @code{BEAMER_COL} value share the same +@code{columns} @LaTeX{} environment. It will end before the next headline +without such a property. This environment is generated automatically. +Although, it can also be explicitly created, with a special @code{columns} +value for @code{BEAMER_ENV} property (if it needs to be set up with some +specific options, for example). + +@subheading Beamer specific syntax + +Beamer back-end is an extension of @LaTeX{} back-end. As such, all @LaTeX{} +specific syntax (e.g., @samp{#+LATEX:} or @samp{#+ATTR_LATEX:}) is +recognized. See @ref{@LaTeX{} and PDF export} for more information. + +@cindex #+BEAMER_THEME +@cindex #+BEAMER_COLOR_THEME +@cindex #+BEAMER_FONT_THEME +@cindex #+BEAMER_INNER_THEME +@cindex #+BEAMER_OUTER_THEME +Beamer export introduces a number of keywords to insert code in the +document's header. Four control appearance of the presentantion: +@code{#+BEAMER_THEME}, @code{#+BEAMER_COLOR_THEME}, +@code{#+BEAMER_FONT_THEME}, @code{#+BEAMER_INNER_THEME} and +@code{#+BEAMER_OUTER_THEME}. All of them accept optional arguments +within square brackets. The last one, @code{#+BEAMER_HEADER}, is more +generic and allows you to append any line of code in the header. + +@example +#+BEAMER_THEME: Rochester [height=20pt] +#+BEAMER_COLOR_THEME: spruce +@end example + +Table of contents generated from @code{toc:t} @code{OPTION} keyword are +wrapped within a @code{frame} environment. Those generated from a @code{TOC} +keyword (@pxref{Table of contents}) are not. In that case, it is also +possible to specify options, enclosed within square brackets. + +@example +#+TOC: headlines [currentsection] +@end example + +Beamer specific code can be inserted with the following constructs: + +@cindex #+BEAMER +@cindex #+BEGIN_BEAMER +@example +#+BEAMER: \pause + +#+BEGIN_BEAMER +All lines in this block will appear only when using this back-end. +#+END_BEAMER + +Text @@@@beamer:some code@@@@ within a paragraph. +@end example + +In particular, this last example can be used to add overlay specifications to +objects whose type is among @code{bold}, @code{item}, @code{link}, +@code{radio-target} and @code{target}, when the value is enclosed within +angular brackets and put at the beginning the object. + +@example +A *@@@@beamer:<2->@@@@useful* feature +@end example + +@cindex #+ATTR_BEAMER +Eventually, every plain list has support for @code{:environment}, +@code{:overlay} and @code{:options} attributes through +@code{ATTR_BEAMER} affiliated keyword. The first one allows the use +of a different environment, the second sets overlay specifications and +the last one inserts optional arguments in current list environment. + +@example +#+ATTR_BEAMER: :overlay +- +- item 1 +- item 2 +@end example + +@subheading Editing support + +You can turn on a special minor mode @code{org-beamer-mode} for faster +editing with: + +@example +#+STARTUP: beamer +@end example + +@table @kbd +@orgcmd{C-c C-b,org-beamer-select-environment} +In @code{org-beamer-mode}, this key offers fast selection of a Beamer +environment or the @code{BEAMER_COL} property. +@end table + +Also, a template for useful in-buffer settings or properties can be inserted +into the buffer with @kbd{M-x org-beamer-insert-options-template}. Among +other things, this will install a column view format which is very handy for +editing special properties used by Beamer. + +@subheading An example -@example -@kbd{C-1 C-c C-e a} -@end example +Here is a simple example Org document that is intended for Beamer export. -@noindent -creates only top level headlines and exports the rest as items. When -headlines are converted to items, the indentation of the text following -the headline is changed to fit nicely under the item. This is done with -the assumption that the first body line indicates the base indentation of -the body text. Any indentation larger than this is adjusted to preserve -the layout relative to the first line. Should there be lines with less -indentation than the first one, these are left alone. - -@vindex org-export-ascii-links-to-notes -Links will be exported in a footnote-like style, with the descriptive part in -the text and the link in a note before the next heading. See the variable -@code{org-export-ascii-links-to-notes} for details and other options. - -@node HTML export, @LaTeX{} and PDF export, ASCII/Latin-1/UTF-8 export, Exporting +@smallexample +#+TITLE: Example Presentation +#+AUTHOR: Carsten Dominik +#+OPTIONS: H:2 +#+LATEX_CLASS: beamer +#+LATEX_CLASS_OPTIONS: [presentation] +#+BEAMER_THEME: Madrid +#+COLUMNS: %45ITEM %10BEAMER_ENV(Env) %10BEAMER_ACT(Act) %4BEAMER_COL(Col) %8BEAMER_OPT(Opt) + +* This is the first structural section + +** Frame 1 +*** Thanks to Eric Fraga :B_block:BMCOL: + :PROPERTIES: + :BEAMER_COL: 0.48 + :BEAMER_ENV: block + :END: + for the first viable Beamer setup in Org +*** Thanks to everyone else :B_block:BMCOL: + :PROPERTIES: + :BEAMER_COL: 0.48 + :BEAMER_ACT: <2-> + :BEAMER_ENV: block + :END: + for contributing to the discussion +**** This will be formatted as a beamer note :B_note: + :PROPERTIES: + :BEAMER_env: note + :END: +** Frame 2 (where we will not use columns) +*** Request + Please test this stuff! +@end smallexample + +@node HTML export, @LaTeX{} and PDF export, Beamer export, Exporting @section HTML export @cindex HTML export @@ -10042,6 +10982,7 @@ language, but with additional support for tables. @menu * HTML Export commands:: How to invoke HTML export +* HTML doctypes:: Org can export to various (X)HTML flavors * HTML preamble and postamble:: How to insert a preamble and a postamble * Quoting HTML tags:: Using direct HTML in Org mode * Links in HTML export:: How links will be interpreted and formatted @@ -10053,100 +10994,161 @@ language, but with additional support for tables. * JavaScript support:: Info and Folding in a web browser @end menu -@node HTML Export commands, HTML preamble and postamble, HTML export, HTML export +@node HTML Export commands, HTML doctypes, HTML export, HTML export @subsection HTML export commands -@cindex region, active -@cindex active region -@cindex transient-mark-mode @table @kbd -@orgcmd{C-c C-e h,org-export-as-html} -@cindex property, EXPORT_FILE_NAME +@orgcmd{C-c C-e h h,org-html-export-to-html} Export as a HTML file. For an Org file @file{myfile.org}, the HTML file will be @file{myfile.html}. The file will be overwritten -without warning. If there is an active region@footnote{This requires -@code{transient-mark-mode} be turned on.}, only the region will be -exported. If the selected region is a single tree@footnote{To select the -current subtree, use @kbd{C-c @@}.}, the tree head will become the document -title. If the tree head entry has, or inherits, an @code{EXPORT_FILE_NAME} -property, that name will be used for the export. -@orgcmd{C-c C-e b,org-export-as-html-and-open} +without warning. +@kbd{C-c C-e h o} Export as a HTML file and immediately open it with a browser. -@orgcmd{C-c C-e H,org-export-as-html-to-buffer} +@orgcmd{C-c C-e h H,org-html-export-as-html} Export to a temporary buffer. Do not create a file. -@orgcmd{C-c C-e R,org-export-region-as-html} -Export the active region to a temporary buffer. With a prefix argument, do -not produce the file header and footer, but just the plain HTML section for -the region. This is good for cut-and-paste operations. -@item C-c C-e v h/b/H/R -Export only the visible part of the document. -@item M-x org-export-region-as-html -Convert the region to HTML under the assumption that it was in Org mode -syntax before. This is a global command that can be invoked in any -buffer. -@item M-x org-replace-region-by-HTML -Replace the active region (assumed to be in Org mode syntax) by HTML -code. @end table -@cindex headline levels, for exporting -In the exported version, the first 3 outline levels will become headlines, -defining a general document structure. Additional levels will be exported as -itemized lists. If you want that transition to occur at a different level, -specify it with a numeric prefix argument. For example, +@c FIXME Exporting sublevels +@c @cindex headline levels, for exporting +@c In the exported version, the first 3 outline levels will become headlines, +@c defining a general document structure. Additional levels will be exported as +@c itemized lists. If you want that transition to occur at a different level, +@c specify it with a numeric prefix argument. For example, + +@c @example +@c @kbd{C-2 C-c C-e b} +@c @end example + +@c @noindent +@c creates two levels of headings and does the rest as items. + +@node HTML doctypes, HTML preamble and postamble, HTML Export commands, HTML export +@subsection HTML doctypes +@vindex org-html-doctype +@vindex org-html-doctype-alist + +Org can export to various (X)HTML flavors. + +Setting the variable @code{org-html-doctype} allows you to export to different +(X)HTML variants. The exported HTML will be adjusted according to the sytax +requirements of that variant. You can either set this variable to a doctype +string directly, in which case the exporter will try to adjust the syntax +automatically, or you can use a ready-made doctype. The ready-made options +are: + +@itemize +@item +``html4-strict'' +@item +``html4-transitional'' +@item +``html4-frameset'' +@item +``xhtml-strict'' +@item +``xhtml-transitional'' +@item +``xhtml-frameset'' +@item +``xhtml-11'' +@item +``html5'' +@item +``xhtml5'' +@end itemize + +See the variable @code{org-html-doctype-alist} for details. The default is +``xhtml-strict''. + +@subsubheading Fancy HTML5 export +@vindex org-html-html5-fancy +@vindex org-html-html5-elements + +HTML5 introduces several new element types. By default, Org will not make +use of these element types, but you can set @code{org-html-html5-fancy} to +@code{t} (or set @code{html5-fancy} item in an @code{OPTIONS} line), to +enable a few new block-level elements. These are created using arbitrary +#+BEGIN and #+END blocks. For instance: @example -@kbd{C-2 C-c C-e b} +#+BEGIN_ASIDE +Lorem ipsum +#+END_ASIDE @end example -@noindent -creates two levels of headings and does the rest as items. +Will export to: + +@example + +@end example + +While this: + +@example +#+ATTR_HTML: :controls controls :width 350 +#+BEGIN_VIDEO +#+HTML: +#+HTML: +Your browser does not support the video tag. +#+END_VIDEO +@end example + +Becomes: + +@example + +@end example + +Special blocks that do not correspond to HTML5 elements (see +@code{org-html-html5-elements}) will revert to the usual behavior, +i.e. #+BEGIN_LEDERHOSEN will still export to
. +Headlines cannot appear within special blocks. To wrap a headline and its +contents in e.g.
or
tags, set the @code{HTML_CONTAINER} +property on the headline itself. -@node HTML preamble and postamble, Quoting HTML tags, HTML Export commands, HTML export +@node HTML preamble and postamble, Quoting HTML tags, HTML doctypes, HTML export @subsection HTML preamble and postamble -@vindex org-export-html-preamble -@vindex org-export-html-postamble -@vindex org-export-html-preamble-format -@vindex org-export-html-postamble-format -@vindex org-export-html-validation-link -@vindex org-export-author-info -@vindex org-export-email-info -@vindex org-export-creator-info +@vindex org-html-preamble +@vindex org-html-postamble +@vindex org-html-preamble-format +@vindex org-html-postamble-format +@vindex org-html-validation-link +@vindex org-export-creator-string @vindex org-export-time-stamp-file The HTML exporter lets you define a preamble and a postamble. -The default value for @code{org-export-html-preamble} is @code{t}, which -means that the preamble is inserted depending on the relevant format string -in @code{org-export-html-preamble-format}. - -Setting @code{org-export-html-preamble} to a string will override the default -format string. Setting it to a function, will insert the output of the -function, which must be a string; such a function takes no argument but you -can check against the value of @code{opt-plist}, which contains the list of -publishing properties for the current file. Setting to @code{nil} will not -insert any preamble. - -The default value for @code{org-export-html-postamble} is @code{'auto}, which -means that the HTML exporter will look for the value of -@code{org-export-author-info}, @code{org-export-email-info}, -@code{org-export-creator-info} and @code{org-export-time-stamp-file}, -@code{org-export-html-validation-link} and build the postamble from these -values. Setting @code{org-export-html-postamble} to @code{t} will insert the -postamble from the relevant format string found in -@code{org-export-html-postamble-format}. Setting it to @code{nil} will not -insert any postamble. +The default value for @code{org-html-preamble} is @code{t}, which means +that the preamble is inserted depending on the relevant format string in +@code{org-html-preamble-format}. + +Setting @code{org-html-preamble} to a string will override the default format +string. If you set it to a function, it will insert the output of the +function, which must be a string. Setting to @code{nil} will not insert any +preamble. + +The default value for @code{org-html-postamble} is @code{'auto}, which means +that the HTML exporter will look for information about the author, the email, +the creator and the date, and build the postamble from these values. Setting +@code{org-html-postamble} to @code{t} will insert the postamble from the +relevant format string found in @code{org-html-postamble-format}. Setting it +to @code{nil} will not insert any postamble. @node Quoting HTML tags, Links in HTML export, HTML preamble and postamble, HTML export @subsection Quoting HTML tags Plain @samp{<} and @samp{>} are always transformed to @samp{<} and -@samp{>} in HTML export. If you want to include simple HTML tags -which should be interpreted as such, mark them with @samp{@@} as in -@samp{@@bold text@@}. Note that this really works only for -simple tags. For more extensive HTML that should be copied verbatim to -the exported file use either +@samp{>} in HTML export. If you want to include raw HTML code, which +should only appear in HTML export, mark it with @samp{@@@@html:} as in +@samp{@@@@html:@@@@bold text@@@@html:@@@@}. For more extensive HTML +that should be copied verbatim to the exported file use either @cindex #+HTML @cindex #+BEGIN_HTML @@ -10187,37 +11189,42 @@ and @code{style} attributes for a link: @cindex #+ATTR_HTML @example -#+ATTR_HTML: title="The Org mode homepage" style="color:red;" +#+ATTR_HTML: :title The Org mode homepage :style color:red; [[http://orgmode.org]] @end example @node Tables in HTML export, Images in HTML export, Links in HTML export, HTML export @subsection Tables @cindex tables, in HTML -@vindex org-export-html-table-tag +@vindex org-html-table-default-attributes -Org mode tables are exported to HTML using the table tag defined in -@code{org-export-html-table-tag}. The default setting makes tables without -cell borders and frame. If you would like to change this for individual -tables, place something like the following before the table: +Org mode tables are exported to HTML using the table attributes defined in +@code{org-html-table-default-attributes}. The default setting makes tables +without cell borders and frame. If you would like to change this for +individual tables, place something like the following before the table: @cindex #+CAPTION @cindex #+ATTR_HTML @example #+CAPTION: This is a table with lines around and between cells -#+ATTR_HTML: border="2" rules="all" frame="border" +#+ATTR_HTML: :border 2 :rules all :frame border @end example +@vindex org-html-table-row-tags +You can also modify the default tags used for each row by setting +@code{org-html-table-row-tags}. See the docstring for an example on +how to use this option. + @node Images in HTML export, Math formatting in HTML export, Tables in HTML export, HTML export @subsection Images in HTML export @cindex images, inline in HTML @cindex inlining images in HTML -@vindex org-export-html-inline-images +@vindex org-html-inline-images HTML export can inline images given as links in the Org file, and it can make an image the clickable part of a link. By default@footnote{But see the variable -@code{org-export-html-inline-images}.}, images are inlined if a link does +@code{org-html-inline-images}.}, images are inlined if a link does not have a description. So @samp{[[file:myimg.jpg]]} will be inlined, while @samp{[[file:myimg.jpg][the image]]} will just produce a link @samp{the image} that points to the image. If the description part @@ -10238,7 +11245,7 @@ support text viewers and accessibility, and align it to the right. @cindex #+ATTR_HTML @example #+CAPTION: A black cat stalking a spider -#+ATTR_HTML: alt="cat/spider image" title="Action!" align="right" +#+ATTR_HTML: :alt cat/spider image :title Action! :align right [[./img/a.jpg]] @end example @@ -10249,36 +11256,43 @@ You could use @code{http} addresses just as well. @subsection Math formatting in HTML export @cindex MathJax @cindex dvipng +@cindex imagemagick @LaTeX{} math snippets (@pxref{@LaTeX{} fragments}) can be displayed in two different ways on HTML pages. The default is to use the @uref{http://www.mathjax.org, MathJax system} which should work out of the -box with Org mode installation because @code{http://orgmode.org} serves +box with Org mode installation because @uref{http://orgmode.org} serves @file{MathJax} for Org mode users for small applications and for testing purposes. @b{If you plan to use this regularly or on pages with significant page views, you should install@footnote{Installation instructions can be found on the MathJax website, see @uref{http://www.mathjax.org/resources/docs/?installation.html}.} MathJax on your own server in order to limit the load of our server.} To configure -@file{MathJax}, use the variable @code{org-export-html-mathjax-options} or +@file{MathJax}, use the variable @code{org-html-mathjax-options} or insert something like the following into the buffer: @example -#+MATHJAX: align:"left" mathml:t path:"/MathJax/MathJax.js" +#+HTML_MATHJAX: align:"left" mathml:t path:"/MathJax/MathJax.js" @end example @noindent See the docstring of the variable -@code{org-export-html-mathjax-options} for the meaning of the parameters in +@code{org-html-mathjax-options} for the meaning of the parameters in this line. If you prefer, you can also request that @LaTeX{} fragments are processed into small images that will be inserted into the browser page. Before the availability of MathJax, this was the default method for Org files. This -method requires that the @file{dvipng} program is available on your system. -You can still get this processing with +method requires that the @file{dvipng} program or @file{imagemagick} suite is +available on your system. You can still get this processing with + +@example +#+OPTIONS: tex:dvipng +@end example + +or: @example -#+OPTIONS: LaTeX:dvipng +#+OPTIONS: tex:imagemagick @end example @node Text areas in HTML export, CSS support, Math formatting in HTML export, HTML export @@ -10287,15 +11301,16 @@ You can still get this processing with @cindex text areas, in HTML An alternative way to publish literal code examples in HTML is to use text areas, where the example can even be edited before pasting it into an -application. It is triggered by a @code{-t} switch at an @code{example} or -@code{src} block. Using this switch disables any options for syntax and -label highlighting, and line numbering, which may be present. You may also -use @code{-h} and @code{-w} switches to specify the height and width of the -text area, which default to the number of lines in the example, and 80, -respectively. For example +application. It is triggered by @code{:textarea} attribute at an +@code{example} or @code{src} block. + +You may also use @code{:height} and @code{:width} attributes to specify the +height and width of the text area, which default to the number of lines in +the example, and 80, respectively. For example @example -#+BEGIN_EXAMPLE -t -w 40 +#+ATTR_HTML: :textarea t :width 40 +#+BEGIN_EXAMPLE (defun org-xor (a b) "Exclusive or." (if a (not b) b)) @@ -10308,15 +11323,15 @@ respectively. For example @cindex CSS, for HTML export @cindex HTML export, CSS -@vindex org-export-html-todo-kwd-class-prefix -@vindex org-export-html-tag-class-prefix -You can also give style information for the exported file. The HTML exporter -assigns the following special CSS classes@footnote{If the classes on TODO -keywords and tags lead to conflicts, use the variables -@code{org-export-html-todo-kwd-class-prefix} and -@code{org-export-html-tag-class-prefix} to make them unique.} to appropriate -parts of the document---your style specifications may change these, in -addition to any of the standard classes like for headlines, tables, etc. +@vindex org-html-todo-kwd-class-prefix +@vindex org-html-tag-class-prefix +You can modify the CSS style definitions for the exported file. The HTML +exporter assigns the following special CSS classes@footnote{If the classes on +TODO keywords and tags lead to conflicts, use the variables +@code{org-html-todo-kwd-class-prefix} and @code{org-html-tag-class-prefix} to +make them unique.} to appropriate parts of the document---your style +specifications may change these, in addition to any of the standard classes +like for headlines, tables, etc. @example p.author @r{author information, including email} p.date @r{publishing date} @@ -10336,6 +11351,9 @@ p.creator @r{creator info, about org mode version} div.outline-N @r{div for outline level N (headline plus text))} div.outline-text-N @r{extra div for text at outline level N} .section-number-N @r{section number in headlines, different for each level} +.figure-number @r{label like "Figure 1:"} +.table-number @r{label like "Table 1:"} +.listing-number @r{label like "Listing 1:"} div.figure @r{how to format an inlined image} pre.src @r{formatted source code} pre.example @r{normal example} @@ -10346,24 +11364,26 @@ p.footnote @r{footnote definition paragraph, containing a footnote} .footnum @r{footnote number in footnote definition (always )} @end example -@vindex org-export-html-style-default -@vindex org-export-html-style-include-default -@vindex org-export-html-style -@vindex org-export-html-extra -@vindex org-export-html-style-default +@vindex org-html-style-default +@vindex org-html-head-include-default-style +@vindex org-html-head +@vindex org-html-head-extra +@cindex #+HTML_INCLUDE_STYLE Each exported file contains a compact default style that defines these classes in a basic way@footnote{This style is defined in the constant -@code{org-export-html-style-default}, which you should not modify. To turn +@code{org-html-style-default}, which you should not modify. To turn inclusion of these defaults off, customize -@code{org-export-html-style-include-default}}. You may overwrite these -settings, or add to them by using the variables @code{org-export-html-style} -(for Org-wide settings) and @code{org-export-html-style-extra} (for more -fine-grained settings, like file-local settings). To set the latter variable -individually for each file, you can use +@code{org-html-head-include-default-style} or set @code{html-style} to +@code{nil} in an @code{OPTIONS} line.}. You may overwrite these settings, or +add to them by using the variables @code{org-html-head} and +@code{org-html-head-extra}. You can override the global values of these +variables for each file by using these keywords: -@cindex #+STYLE +@cindex #+HTML_HEAD +@cindex #+HTML_HEAD_EXTRA @example -#+STYLE: +#+HTML_HEAD: +#+HTML_HEAD_EXTRA: @end example @noindent @@ -10392,15 +11412,12 @@ as well, press @kbd{?} for an overview of the available keys). The second view type is a @emph{folding} view much like Org provides inside Emacs. The script is available at @url{http://orgmode.org/org-info.js} and you can find the documentation for it at @url{http://orgmode.org/worg/code/org-info-js/}. -We host the script at our site, but if you use it a lot, you might -not want to be dependent on @url{http://orgmode.org} and prefer to install a local +We host the script at our site, but if you use it a lot, you might not want +to be dependent on @url{http://orgmode.org} and prefer to install a local copy on your own web server. -To use the script, you need to make sure that the @file{org-jsinfo.el} module -gets loaded. It should be loaded by default, but you can try @kbd{M-x -customize-variable @key{RET} org-modules @key{RET}} to convince yourself that -this is indeed the case. All it then takes to make use of the program is -adding a single line to the Org file: +All it then takes to use this program is adding a single line to the Org +file: @cindex #+INFOJS_OPT @example @@ -10440,92 +11457,61 @@ buttons: @r{Should view-toggle buttons be everywhere? When @code{nil} (the} @r{default), only one such button will be present.} @end example @noindent -@vindex org-infojs-options -@vindex org-export-html-use-infojs +@vindex org-html-infojs-options +@vindex org-html-use-infojs You can choose default values for these options by customizing the variable -@code{org-infojs-options}. If you always want to apply the script to your -pages, configure the variable @code{org-export-html-use-infojs}. +@code{org-html-infojs-options}. If you always want to apply the script to your +pages, configure the variable @code{org-html-use-infojs}. -@node @LaTeX{} and PDF export, DocBook export, HTML export, Exporting +@node @LaTeX{} and PDF export, Markdown export, HTML export, Exporting @section @LaTeX{} and PDF export @cindex @LaTeX{} export @cindex PDF export -@cindex Guerry, Bastien - -Org mode contains a @LaTeX{} exporter written by Bastien Guerry. With -further processing@footnote{The default @LaTeX{} output is designed for -processing with @code{pdftex} or @LaTeX{}. It includes packages that are not -compatible with @code{xetex} and possibly @code{luatex}. See the variables -@code{org-export-latex-default-packages-alist} and -@code{org-export-latex-packages-alist}.}, this backend is also used to -produce PDF output. Since the @LaTeX{} output uses @file{hyperref} to -implement links and cross references, the PDF output file will be fully -linked. Beware of the fact that your @code{org} file has to be properly -structured in order to be correctly exported: respect the hierarchy of -sections. + +@LaTeX{} export can produce an arbitrarily complex LaTeX document of any +standard or custom document class. With further processing@footnote{The +default @LaTeX{} output is designed for processing with @code{pdftex} or +@LaTeX{}. It includes packages that are not compatible with @code{xetex} and +possibly @code{luatex}. The @LaTeX{} exporter can be configured to support +alternative TeX engines, see the options +@code{org-latex-default-packages-alist} and @code{org-latex-packages-alist}.}, +which the @LaTeX{} exporter is able to control, this back-end is able to +produce PDF output. Because the @LaTeX{} exporter can be configured to use +the @code{hyperref} package, the default setup produces fully-linked PDF +output. + +As in @LaTeX{}, blank lines are meaningful for this back-end: a paragraph +will not be started if two contiguous syntactical elements are not separated +by an empty line. + +This back-end also offers enhanced support for footnotes. Thus, it handles +nested footnotes, footnotes in tables and footnotes in a list item's +description. @menu -* @LaTeX{}/PDF export commands:: +* @LaTeX{} export commands:: How to export to LaTeX and PDF * Header and sectioning:: Setting up the export file structure * Quoting @LaTeX{} code:: Incorporating literal @LaTeX{} code -* Tables in @LaTeX{} export:: Options for exporting tables to @LaTeX{} -* Images in @LaTeX{} export:: How to insert figures into @LaTeX{} output -* Beamer class export:: Turning the file into a presentation +* @LaTeX{} specific attributes:: Controlling @LaTeX{} output @end menu -@node @LaTeX{}/PDF export commands, Header and sectioning, @LaTeX{} and PDF export, @LaTeX{} and PDF export +@node @LaTeX{} export commands, Header and sectioning, @LaTeX{} and PDF export, @LaTeX{} and PDF export @subsection @LaTeX{} export commands -@cindex region, active -@cindex active region -@cindex transient-mark-mode @table @kbd -@orgcmd{C-c C-e l,org-export-as-latex} -@cindex property EXPORT_FILE_NAME -Export as a @LaTeX{} file. For an Org file -@file{myfile.org}, the @LaTeX{} file will be @file{myfile.tex}. The file will -be overwritten without warning. If there is an active region@footnote{This -requires @code{transient-mark-mode} be turned on.}, only the region will be -exported. If the selected region is a single tree@footnote{To select the -current subtree, use @kbd{C-c @@}.}, the tree head will become the document -title. If the tree head entry has or inherits an @code{EXPORT_FILE_NAME} -property, that name will be used for the export. -@orgcmd{C-c C-e L,org-export-as-latex-to-buffer} +@orgcmd{C-c C-e l l,org-latex-export-to-latex} +Export as a @LaTeX{} file. For an Org file @file{myfile.org}, the @LaTeX{} +file will be @file{myfile.tex}. The file will be overwritten without +warning. +@orgcmd{C-c C-e l L,org-latex-export-as-latex} Export to a temporary buffer. Do not create a file. -@item C-c C-e v l/L -Export only the visible part of the document. -@item M-x org-export-region-as-latex -Convert the region to @LaTeX{} under the assumption that it was in Org mode -syntax before. This is a global command that can be invoked in any -buffer. -@item M-x org-replace-region-by-latex -Replace the active region (assumed to be in Org mode syntax) by @LaTeX{} -code. -@orgcmd{C-c C-e p,org-export-as-pdf} +@orgcmd{C-c C-e l p,org-latex-export-to-pdf} Export as @LaTeX{} and then process to PDF. -@orgcmd{C-c C-e d,org-export-as-pdf-and-open} +@item C-c C-e l o Export as @LaTeX{} and then process to PDF, then open the resulting PDF file. @end table -@cindex headline levels, for exporting -@vindex org-latex-low-levels -In the exported version, the first 3 outline levels will become -headlines, defining a general document structure. Additional levels -will be exported as description lists. The exporter can ignore them or -convert them to a custom string depending on -@code{org-latex-low-levels}. - -If you want that transition to occur at a different level, specify it -with a numeric prefix argument. For example, - -@example -@kbd{C-2 C-c C-e l} -@end example - -@noindent -creates two levels of headings and does the rest as items. - -@node Header and sectioning, Quoting @LaTeX{} code, @LaTeX{}/PDF export commands, @LaTeX{} and PDF export +@node Header and sectioning, Quoting @LaTeX{} code, @LaTeX{} export commands, @LaTeX{} and PDF export @subsection Header and sectioning structure @cindex @LaTeX{} class @cindex @LaTeX{} sectioning structure @@ -10533,493 +11519,368 @@ creates two levels of headings and does the rest as items. @cindex header, for @LaTeX{} files @cindex sectioning structure, for @LaTeX{} export +By default, the first three outline levels become headlines, defining a +general document structure. Additional levels are exported as @code{itemize} +or @code{enumerate} lists. The transition can also occur at a different +level (@pxref{Export settings}). + By default, the @LaTeX{} output uses the class @code{article}. -@vindex org-export-latex-default-class -@vindex org-export-latex-classes -@vindex org-export-latex-default-packages-alist -@vindex org-export-latex-packages-alist -@cindex #+LaTeX_HEADER -@cindex #+LaTeX_CLASS -@cindex #+LaTeX_CLASS_OPTIONS -@cindex property, LaTeX_CLASS -@cindex property, LaTeX_CLASS_OPTIONS +@vindex org-latex-default-class +@vindex org-latex-classes +@vindex org-latex-default-packages-alist +@vindex org-latex-packages-alist You can change this globally by setting a different value for -@code{org-export-latex-default-class} or locally by adding an option like -@code{#+LaTeX_CLASS: myclass} in your file, or with a @code{:LaTeX_CLASS:} -property that applies when exporting a region containing only this (sub)tree. -The class must be listed in @code{org-export-latex-classes}. This variable -defines a header template for each class@footnote{Into which the values of -@code{org-export-latex-default-packages-alist} and -@code{org-export-latex-packages-alist} are spliced.}, and allows you to -define the sectioning structure for each class. You can also define your own -classes there. @code{#+LaTeX_CLASS_OPTIONS} or a @code{:LaTeX_CLASS_OPTIONS:} -property can specify the options for the @code{\documentclass} macro. The -options to documentclass have to be provided, as expected by @LaTeX{}, within -square brackets. You can also use @code{#+LaTeX_HEADER: \usepackage@{xyz@}} -to add lines to the header. See the docstring of -@code{org-export-latex-classes} for more information. An example is shown -below. - -@example -#+LaTeX_CLASS: article -#+LaTeX_CLASS_OPTIONS: [a4paper] -#+LaTeX_HEADER: \usepackage@{xyz@} +@code{org-latex-default-class} or locally by adding an option like +@code{#+LATEX_CLASS: myclass} in your file, or with +a @code{EXPORT_LATEX_CLASS} property that applies when exporting a region +containing only this (sub)tree. The class must be listed in +@code{org-latex-classes}. This variable defines a header template for each +class@footnote{Into which the values of +@code{org-latex-default-packages-alist} and @code{org-latex-packages-alist} +are spliced.}, and allows you to define the sectioning structure for each +class. You can also define your own classes there. + +@cindex #+LATEX_CLASS +@cindex #+LATEX_CLASS_OPTIONS +@cindex property, EXPORT_LATEX_CLASS +@cindex property, EXPORT_LATEX_CLASS_OPTIONS +The @code{LATEX_CLASS_OPTIONS} keyword or @code{EXPORT_LATEX_CLASS_OPTIONS} +property can specify the options for the @code{\documentclass} macro. These +options have to be provided, as expected by @LaTeX{}, within square brackets. + +@cindex #+LATEX_HEADER +@cindex #+LATEX_HEADER_EXTRA +You can also use the @code{LATEX_HEADER} and +@code{LATEX_HEADER_EXTRA}@footnote{Unlike @code{LATEX_HEADER}, contents +from @code{LATEX_HEADER_EXTRA} keywords will not be loaded when previewing +@LaTeX{} snippets (@pxref{Previewing @LaTeX{} fragments}).} keywords in order +to add lines to the header. See the docstring of @code{org-latex-classes} for +more information. + +An example is shown below. + +@example +#+LATEX_CLASS: article +#+LATEX_CLASS_OPTIONS: [a4paper] +#+LATEX_HEADER: \usepackage@{xyz@} * Headline 1 some text @end example -@node Quoting @LaTeX{} code, Tables in @LaTeX{} export, Header and sectioning, @LaTeX{} and PDF export +@node Quoting @LaTeX{} code, @LaTeX{} specific attributes, Header and sectioning, @LaTeX{} and PDF export @subsection Quoting @LaTeX{} code Embedded @LaTeX{} as described in @ref{Embedded @LaTeX{}}, will be correctly -inserted into the @LaTeX{} file. This includes simple macros like -@samp{\ref@{LABEL@}} to create a cross reference to a figure. Furthermore, -you can add special code that should only be present in @LaTeX{} export with -the following constructs: +inserted into the @LaTeX{} file. Furthermore, you can add special code that +should only be present in @LaTeX{} export with the following constructs: -@cindex #+LaTeX -@cindex #+BEGIN_LaTeX +@cindex #+LATEX +@cindex #+BEGIN_LATEX @example -#+LaTeX: Literal @LaTeX{} code for export -@end example +Code within @@@@latex:some code@@@@ a paragraph. -@noindent or -@cindex #+BEGIN_LaTeX +#+LATEX: Literal @LaTeX{} code for export -@example -#+BEGIN_LaTeX +#+BEGIN_LATEX All lines between these markers are exported literally -#+END_LaTeX +#+END_LATEX @end example +@node @LaTeX{} specific attributes, , Quoting @LaTeX{} code, @LaTeX{} and PDF export +@subsection @LaTeX{} specific attributes +@cindex #+ATTR_LATEX -@node Tables in @LaTeX{} export, Images in @LaTeX{} export, Quoting @LaTeX{} code, @LaTeX{} and PDF export -@subsection Tables in @LaTeX{} export +@LaTeX{} understands attributes specified in an @code{ATTR_LATEX} line. They +affect tables, images, plain lists, special blocks and source blocks. + +@subsubheading Tables in @LaTeX{} export @cindex tables, in @LaTeX{} export -For @LaTeX{} export of a table, you can specify a label, a caption and -placement options (@pxref{Images and tables}). You can also use the -@code{ATTR_LaTeX} line to request a @code{longtable} environment for the -table, so that it may span several pages, or to change the default table -environment from @code{table} to @code{table*} or to change the default inner -tabular environment to @code{tabularx} or @code{tabulary}. Finally, you can -set the alignment string, and (with @code{tabularx} or @code{tabulary}) the -width: +For @LaTeX{} export of a table, you can specify a label and a caption +(@pxref{Images and tables}). You can also use attributes to control table +layout and contents. Valid @LaTeX{} attributes include: + +@table @code +@item :mode +@vindex org-latex-default-table-mode +Nature of table's contents. It can be set to @code{table}, @code{math}, +@code{inline-math} or @code{verbatim}. In particular, when in @code{math} or +@code{inline-math} mode, every cell is exported as-is, horizontal rules are +ignored and the table will be wrapped in a math environment. Also, +contiguous tables sharing the same math mode will be wrapped within the same +environment. Default mode is determined in +@code{org-latex-default-table-mode}. +@item :environment +@vindex org-latex-default-table-environment +Environment used for the table. It can be set to any @LaTeX{} table +environment, like @code{tabularx}@footnote{Requires adding the +@code{tabularx} package to @code{org-latex-packages-alist}.}, +@code{longtable}, @code{array}, @code{tabu}@footnote{Requires adding the +@code{tabu} package to @code{org-latex-packages-alist}.}, +@code{bmatrix}@enddots{} It defaults to +@code{org-latex-default-table-environment} value. +@item :caption +@code{#+CAPTION} keyword is the simplest way to set a caption for a table +(@pxref{Images and tables}). If you need more advanced commands for that +task, you can use @code{:caption} attribute instead. Its value should be raw +@LaTeX{} code. It has precedence over @code{#+CAPTION}. +@item :float +@itemx :placement +Float environment for the table. Possible values are @code{sidewaystable}, +@code{multicolumn}, @code{t} and @code{nil}. When unspecified, a table with +a caption will have a @code{table} environment. Moreover, @code{:placement} +attribute can specify the positioning of the float. +@item :align +@itemx :font +@itemx :width +Set, respectively, the alignment string of the table, its font size and its +width. They only apply on regular tables. +@item :spread +Boolean specific to the @code{tabu} and @code{longtabu} environments, and +only takes effect when used in conjunction with the @code{:width} attribute. +When @code{:spread} is non-@code{nil}, the table will be spread or shrunk by the +value of @code{:width}. +@item :booktabs +@itemx :center +@itemx :rmlines +@vindex org-latex-tables-booktabs +@vindex org-latex-tables-centered +They toggle, respectively, @code{booktabs} usage (assuming the package is +properly loaded), table centering and removal of every horizontal rule but +the first one (in a "table.el" table only). In particular, +@code{org-latex-tables-booktabs} (respectively @code{org-latex-tables-centered}) +activates the first (respectively second) attribute globally. +@item :math-prefix +@itemx :math-suffix +@itemx :math-arguments +A string that will be inserted, respectively, before the table within the +math environment, after the table within the math environment, and between +the macro name and the contents of the table. The @code{:math-arguments} +attribute is used for matrix macros that require more than one argument +(e.g., @code{qbordermatrix}). +@end table + +Thus, attributes can be used in a wide array of situations, like writing +a table that will span over multiple pages, or a matrix product: -@cindex #+CAPTION -@cindex #+LABEL -@cindex #+ATTR_LaTeX @example -#+CAPTION: A long table -#+LABEL: tbl:long -#+ATTR_LaTeX: longtable align=l|lp@{3cm@}r|l +#+ATTR_LATEX: :environment longtable :align l|lp@{3cm@}r|l | ..... | ..... | | ..... | ..... | + +#+ATTR_LATEX: :mode math :environment bmatrix :math-suffix \times +| a | b | +| c | d | +#+ATTR_LATEX: :mode math :environment bmatrix +| 1 | 2 | +| 3 | 4 | @end example -or to specify a multicolumn table with @code{tabulary} +In the example below, @LaTeX{} command +@code{\bicaption@{HeadingA@}@{HeadingB@}} will set the caption. -@cindex #+CAPTION -@cindex #+LABEL -@cindex #+ATTR_LaTeX @example -#+CAPTION: A wide table with tabulary -#+LABEL: tbl:wide -#+ATTR_LaTeX: table* tabulary width=\textwidth +#+ATTR_LATEX: :caption \bicaption@{HeadingA@}@{HeadingB@} | ..... | ..... | | ..... | ..... | @end example -@node Images in @LaTeX{} export, Beamer class export, Tables in @LaTeX{} export, @LaTeX{} and PDF export -@subsection Images in @LaTeX{} export + +@subsubheading Images in @LaTeX{} export @cindex images, inline in @LaTeX{} @cindex inlining images in @LaTeX{} Images that are linked to without a description part in the link, like @samp{[[file:img.jpg]]} or @samp{[[./img.jpg]]} will be inserted into the PDF output file resulting from @LaTeX{} processing. Org will use an -@code{\includegraphics} macro to insert the image. If you have specified a -caption and/or a label as described in @ref{Images and tables}, the figure -will be wrapped into a @code{figure} environment and thus become a floating -element. You can use an @code{#+ATTR_LaTeX:} line to specify various other -options. You can ask org to export an image as a float without specifying -a label or a caption by using the keyword @code{float} in this line. Various -optional arguments to the @code{\includegraphics} macro can also be specified -in this fashion. To modify the placement option of the floating environment, -add something like @samp{placement=[h!]} to the attributes. It is to be noted -this option can be used with tables as well@footnote{One can also take -advantage of this option to pass other, unrelated options into the figure or -table environment. For an example see the section ``Exporting org files'' in -@url{http://orgmode.org/worg/org-hacks.html}}. - -If you would like to let text flow around the image, add the word @samp{wrap} -to the @code{#+ATTR_LaTeX:} line, which will make the figure occupy the left -half of the page. To fine-tune, the @code{placement} field will be the set -of additional arguments needed by the @code{wrapfigure} environment. Note -that if you change the size of the image, you need to use compatible settings -for @code{\includegraphics} and @code{wrapfigure}. +@code{\includegraphics} macro to insert the image@footnote{In the case of +TikZ (@url{http://sourceforge.net/projects/pgf/}) images, it will become an +@code{\input} macro wrapped within a @code{tikzpicture} environment.}. + +You can specify specify image width or height with, respectively, +@code{:width} and @code{:height} attributes. It is also possible to add any +other option with the @code{:options} attribute, as shown in the following +example: -@cindex #+CAPTION -@cindex #+LABEL -@cindex #+ATTR_LaTeX @example -#+CAPTION: The black-body emission of the disk around HR 4049 -#+LABEL: fig:SED-HR4049 -#+ATTR_LaTeX: width=5cm,angle=90 +#+ATTR_LATEX: :width 5cm :options angle=90 [[./img/sed-hr4049.pdf]] - -#+ATTR_LaTeX: width=0.38\textwidth wrap placement=@{r@}@{0.4\textwidth@} -[[./img/hst.png]] @end example -If you wish to include an image which spans multiple columns in a page, you -can use the keyword @code{multicolumn} in the @code{#+ATTR_LaTeX} line. This -will export the image wrapped in a @code{figure*} environment. +If you need a specific command for the caption, use @code{:caption} +attribute. It will override standard @code{#+CAPTION} value, if any. -If you need references to a label created in this way, write -@samp{\ref@{fig:SED-HR4049@}} just like in @LaTeX{}. - -@node Beamer class export, , Images in @LaTeX{} export, @LaTeX{} and PDF export -@subsection Beamer class export - -The @LaTeX{} class @file{beamer} allows production of high quality presentations -using @LaTeX{} and pdf processing. Org mode has special support for turning an -Org mode file or tree into a @file{beamer} presentation. - -When the @LaTeX{} class for the current buffer (as set with @code{#+LaTeX_CLASS: -beamer}) or subtree (set with a @code{LaTeX_CLASS} property) is -@code{beamer}, a special export mode will turn the file or tree into a beamer -presentation. Any tree with not-too-deep level nesting should in principle be -exportable as a beamer presentation. By default, the top-level entries (or -the first level below the selected subtree heading) will be turned into -frames, and the outline structure below this level will become itemize lists. -You can also configure the variable @code{org-beamer-frame-level} to a -different level---then the hierarchy above frames will produce the sectioning -structure of the presentation. - -A template for useful in-buffer settings or properties can be inserted into -the buffer with @kbd{M-x org-insert-beamer-options-template}. Among other -things, this will install a column view format which is very handy for -editing special properties used by beamer. - -You can influence the structure of the presentation using the following -properties: +@example +#+ATTR_LATEX: :caption \bicaption@{HeadingA@}@{HeadingB@} +[[./img/sed-hr4049.pdf]] +@end example -@table @code -@item BEAMER_env -The environment that should be used to format this entry. Valid environments -are defined in the constant @code{org-beamer-environments-default}, and you -can define more in @code{org-beamer-environments-extra}. If this property is -set, the entry will also get a @code{:B_environment:} tag to make this -visible. This tag has no semantic meaning, it is only a visual aid. -@item BEAMER_envargs -The beamer-special arguments that should be used for the environment, like -@code{[t]} or @code{[<+->]} of @code{<2-3>}. If the @code{BEAMER_col} -property is also set, something like @code{C[t]} can be added here as well to -set an options argument for the implied @code{columns} environment. -@code{c[t]} or @code{c<2->} will set an options for the implied @code{column} +If you have specified a caption as described in @ref{Images and tables}, the +picture will be wrapped into a @code{figure} environment and thus become +a floating element. You can also ask Org to export an image as a float +without specifying caption by setting the @code{:float} attribute. You may +also set it to: +@itemize @minus +@item +@code{t}: if you want to use the standard @samp{figure} environment. It is +used by default if you provide a caption to the image. +@item +@code{multicolumn}: if you wish to include an image which spans multiple +columns in a page. This will export the image wrapped in a @code{figure*} environment. -@item BEAMER_col -The width of a column that should start with this entry. If this property is -set, the entry will also get a @code{:BMCOL:} property to make this visible. -Also this tag is only a visual aid. When this is a plain number, it will be -interpreted as a fraction of @code{\textwidth}. Otherwise it will be assumed -that you have specified the units, like @samp{3cm}. The first such property -in a frame will start a @code{columns} environment to surround the columns. -This environment is closed when an entry has a @code{BEAMER_col} property -with value 0 or 1, or automatically at the end of the frame. -@item BEAMER_extra -Additional commands that should be inserted after the environment has been -opened. For example, when creating a frame, this can be used to specify -transitions. -@end table - -Frames will automatically receive a @code{fragile} option if they contain -source code that uses the verbatim environment. Special @file{beamer} -specific code can be inserted using @code{#+BEAMER:} and -@code{#+BEGIN_BEAMER...#+END_BEAMER} constructs, similar to other export -backends, but with the difference that @code{#+LaTeX:} stuff will be included -in the presentation as well. - -Outline nodes with @code{BEAMER_env} property value @samp{note} or -@samp{noteNH} will be formatted as beamer notes, i,e, they will be wrapped -into @code{\note@{...@}}. The former will include the heading as part of the -note text, the latter will ignore the heading of that node. To simplify note -generation, it is actually enough to mark the note with a @emph{tag} (either -@code{:B_note:} or @code{:B_noteNH:}) instead of creating the -@code{BEAMER_env} property. - -You can turn on a special minor mode @code{org-beamer-mode} for editing -support with +@item +@code{wrap}: if you would like to let text flow around the image. It will +make the figure occupy the left half of the page. +@item +@code{nil}: if you need to avoid any floating environment, even when +a caption is provided. +@end itemize +@noindent +To modify the placement option of any floating environment, set the +@code{placement} attribute. @example -#+STARTUP: beamer +#+ATTR_LATEX: :float wrap :width 0.38\textwidth :placement @{r@}@{0.4\textwidth@} +[[./img/hst.png]] @end example -@table @kbd -@orgcmd{C-c C-b,org-beamer-select-environment} -In @code{org-beamer-mode}, this key offers fast selection of a beamer -environment or the @code{BEAMER_col} property. -@end table - -Column view provides a great way to set the environment of a node and other -important parameters. Make sure you are using a COLUMN format that is geared -toward this special purpose. The command @kbd{M-x -org-insert-beamer-options-template} defines such a format. - -Here is a simple example Org document that is intended for beamer export. - -@smallexample -#+LaTeX_CLASS: beamer -#+TITLE: Example Presentation -#+AUTHOR: Carsten Dominik -#+LaTeX_CLASS_OPTIONS: [presentation] -#+BEAMER_FRAME_LEVEL: 2 -#+BEAMER_HEADER_EXTRA: \usetheme@{Madrid@}\usecolortheme@{default@} -#+COLUMNS: %35ITEM %10BEAMER_env(Env) %10BEAMER_envargs(Args) %4BEAMER_col(Col) %8BEAMER_extra(Ex) - -* This is the first structural section - -** Frame 1 \\ with a subtitle -*** Thanks to Eric Fraga :BMCOL:B_block: - :PROPERTIES: - :BEAMER_env: block - :BEAMER_envargs: C[t] - :BEAMER_col: 0.5 - :END: - for the first viable beamer setup in Org -*** Thanks to everyone else :BMCOL:B_block: - :PROPERTIES: - :BEAMER_col: 0.5 - :BEAMER_env: block - :BEAMER_envargs: <2-> - :END: - for contributing to the discussion -**** This will be formatted as a beamer note :B_note: -** Frame 2 \\ where we will not use columns -*** Request :B_block: - Please test this stuff! - :PROPERTIES: - :BEAMER_env: block - :END: -@end smallexample - -For more information, see the documentation on Worg. +If the @code{:comment-include} attribute is set to a non-@code{nil} value, +the @LaTeX{} @code{\includegraphics} macro will be commented out. -@node DocBook export, OpenDocument Text export, @LaTeX{} and PDF export, Exporting -@section DocBook export -@cindex DocBook export -@cindex PDF export -@cindex Cui, Baoqiu +@subsubheading Plain lists in @LaTeX{} export +@cindex plain lists, in @LaTeX{} export -Org contains a DocBook exporter written by Baoqiu Cui. Once an Org file is -exported to DocBook format, it can be further processed to produce other -formats, including PDF, HTML, man pages, etc., using many available DocBook -tools and stylesheets. +Plain lists accept two optional attributes: @code{:environment} and +@code{:options}. The first one allows the use of a non-standard +environment (e.g., @samp{inparaenum}). The second one specifies +optional arguments for that environment (square brackets may be +omitted). -Currently DocBook exporter only supports DocBook V5.0. +@example +#+ATTR_LATEX: :environment compactitem :options $\circ$ +- you need ``paralist'' package to reproduce this example. +@end example -@menu -* DocBook export commands:: How to invoke DocBook export -* Quoting DocBook code:: Incorporating DocBook code in Org files -* Recursive sections:: Recursive sections in DocBook -* Tables in DocBook export:: Tables are exported as HTML tables -* Images in DocBook export:: How to insert figures into DocBook output -* Special characters:: How to handle special characters -@end menu +@subsubheading Source blocks in @LaTeX{} export +@cindex source blocks, in @LaTeX{} export -@node DocBook export commands, Quoting DocBook code, DocBook export, DocBook export -@subsection DocBook export commands +In addition to syntax defined in @ref{Literal examples}, names and captions +(@pxref{Images and tables}), source blocks also accept a @code{:float} +attribute. You may set it to: +@itemize @minus +@item +@code{t}: if you want to make the source block a float. It is the default +value when a caption is provided. +@item +@code{mulicolumn}: if you wish to include a source block which spans multiple +colums in a page. +@item +@code{nil}: if you need to avoid any floating evironment, even when a caption +is provided. It is useful for source code that may not fit in a single page. +@end itemize -@cindex region, active -@cindex active region -@cindex transient-mark-mode -@table @kbd -@orgcmd{C-c C-e D,org-export-as-docbook} -@cindex property EXPORT_FILE_NAME -Export as a DocBook file. For an Org file, @file{myfile.org}, the DocBook XML -file will be @file{myfile.xml}. The file will be overwritten without -warning. If there is an active region@footnote{This requires -@code{transient-mark-mode} to be turned on}, only the region will be -exported. If the selected region is a single tree@footnote{To select the -current subtree, use @kbd{C-c @@}.}, the tree head will become the document -title. If the tree head entry has, or inherits, an @code{EXPORT_FILE_NAME} -property, that name will be used for the export. -@orgcmd{C-c C-e V,org-export-as-docbook-pdf-and-open} -Export as a DocBook file, process to PDF, then open the resulting PDF file. - -@vindex org-export-docbook-xslt-proc-command -@vindex org-export-docbook-xsl-fo-proc-command -Note that, in order to produce PDF output based on an exported DocBook file, -you need to have XSLT processor and XSL-FO processor software installed on your -system. Check variables @code{org-export-docbook-xslt-proc-command} and -@code{org-export-docbook-xsl-fo-proc-command}. - -@vindex org-export-docbook-xslt-stylesheet -The stylesheet argument @code{%s} in variable -@code{org-export-docbook-xslt-proc-command} is replaced by the value of -variable @code{org-export-docbook-xslt-stylesheet}, which needs to be set by -the user. You can also overrule this global setting on a per-file basis by -adding an in-buffer setting @code{#+XSLT:} to the Org file. - -@orgkey{C-c C-e v D} -Export only the visible part of the document. -@end table +@example +#+ATTR_LATEX: :float nil +#+BEGIN_SRC emacs-lisp +Code that may not fit in a single page. +#+END_SRC +@end example -@node Quoting DocBook code, Recursive sections, DocBook export commands, DocBook export -@subsection Quoting DocBook code +@subsubheading Special blocks in @LaTeX{} export +@cindex special blocks, in @LaTeX{} export -You can quote DocBook code in Org files and copy it verbatim into exported -DocBook file with the following constructs: +In @LaTeX{} back-end, special blocks become environments of the same name. +Value of @code{:options} attribute will be appended as-is to that +environment's opening string. For example: -@cindex #+DOCBOOK -@cindex #+BEGIN_DOCBOOK @example -#+DOCBOOK: Literal DocBook code for export +#+ATTR_LATEX: :options [Proof of important theorem] +#+BEGIN_PROOF +... +Therefore, any even number greater than 2 is the sum of two primes. +#+END_PROOF @end example -@noindent or -@cindex #+BEGIN_DOCBOOK +@noindent +becomes @example -#+BEGIN_DOCBOOK -All lines between these markers are exported by DocBook exporter -literally. -#+END_DOCBOOK +\begin@{proof@}[Proof of important theorem] +... +Therefore, any even number greater than 2 is the sum of two primes. +\end@{proof@} @end example -For example, you can use the following lines to include a DocBook warning -admonition. As to what this warning says, you should pay attention to the -document context when quoting DocBook code in Org files. You may make -exported DocBook XML files invalid by not quoting DocBook code correctly. +If you need to insert a specific caption command, use @code{:caption} +attribute. It will override standard @code{#+CAPTION} value, if any. For +example: @example -#+BEGIN_DOCBOOK - - You should know what you are doing when quoting DocBook XML code - in your Org file. Invalid DocBook XML may be generated by - DocBook exporter if you are not careful! - -#+END_DOCBOOK +#+ATTR_LATEX: :caption \MyCaption@{HeadingA@} +#+BEGIN_PROOF +... +#+END_PROOF @end example -@node Recursive sections, Tables in DocBook export, Quoting DocBook code, DocBook export -@subsection Recursive sections -@cindex DocBook recursive sections - -DocBook exporter exports Org files as articles using the @code{article} -element in DocBook. Recursive sections, i.e., @code{section} elements, are -used in exported articles. Top level headlines in Org files are exported as -top level sections, and lower level headlines are exported as nested -sections. The entire structure of Org files will be exported completely, no -matter how many nested levels of headlines there are. - -Using recursive sections makes it easy to port and reuse exported DocBook -code in other DocBook document types like @code{book} or @code{set}. +@subsubheading Horizontal rules +@cindex horizontal rules, in @LaTeX{} export -@node Tables in DocBook export, Images in DocBook export, Recursive sections, DocBook export -@subsection Tables in DocBook export -@cindex tables, in DocBook export +Width and thickness of a given horizontal rule can be controlled with, +respectively, @code{:width} and @code{:thickness} attributes: -Tables in Org files are exported as HTML tables, which have been supported since -DocBook V4.3. - -If a table does not have a caption, an informal table is generated using the -@code{informaltable} element; otherwise, a formal table will be generated -using the @code{table} element. - -@node Images in DocBook export, Special characters, Tables in DocBook export, DocBook export -@subsection Images in DocBook export -@cindex images, inline in DocBook -@cindex inlining images in DocBook - -Images that are linked to without a description part in the link, like -@samp{[[file:img.jpg]]} or @samp{[[./img.jpg]]}, will be exported to DocBook -using @code{mediaobject} elements. Each @code{mediaobject} element contains -an @code{imageobject} that wraps an @code{imagedata} element. If you have -specified a caption for an image as described in @ref{Images and tables}, a -@code{caption} element will be added in @code{mediaobject}. If a label is -also specified, it will be exported as an @code{xml:id} attribute of the -@code{mediaobject} element. - -@vindex org-export-docbook-default-image-attributes -Image attributes supported by the @code{imagedata} element, like @code{align} -or @code{width}, can be specified in two ways: you can either customize -variable @code{org-export-docbook-default-image-attributes} or use the -@code{#+ATTR_DOCBOOK:} line. Attributes specified in variable -@code{org-export-docbook-default-image-attributes} are applied to all inline -images in the Org file to be exported (unless they are overridden by image -attributes specified in @code{#+ATTR_DOCBOOK:} lines). - -The @code{#+ATTR_DOCBOOK:} line can be used to specify additional image -attributes or override default image attributes for individual images. If -the same attribute appears in both the @code{#+ATTR_DOCBOOK:} line and -variable @code{org-export-docbook-default-image-attributes}, the former -takes precedence. Here is an example about how image attributes can be -set: - -@cindex #+CAPTION -@cindex #+LABEL -@cindex #+ATTR_DOCBOOK @example -#+CAPTION: The logo of Org mode -#+LABEL: unicorn-svg -#+ATTR_DOCBOOK: scalefit="1" width="100%" depth="100%" -[[./img/org-mode-unicorn.svg]] +#+ATTR_LATEX: :width .6\textwidth :thickness 0.8pt +----- @end example -@vindex org-export-docbook-inline-image-extensions -By default, DocBook exporter recognizes the following image file types: -@file{jpeg}, @file{jpg}, @file{png}, @file{gif}, and @file{svg}. You can -customize variable @code{org-export-docbook-inline-image-extensions} to add -more types to this list as long as DocBook supports them. +@node Markdown export, OpenDocument Text export, @LaTeX{} and PDF export, Exporting +@section Markdown export +@cindex Markdown export -@node Special characters, , Images in DocBook export, DocBook export -@subsection Special characters in DocBook export -@cindex Special characters in DocBook export +@code{md} export back-end generates Markdown syntax@footnote{Vanilla flavour, +as defined at @url{http://daringfireball.net/projects/markdown/}.} for an Org +mode buffer. -@vindex org-export-docbook-doctype -@vindex org-entities -Special characters that are written in @TeX{}-like syntax, such as @code{\alpha}, -@code{\Gamma}, and @code{\Zeta}, are supported by DocBook exporter. These -characters are rewritten to XML entities, like @code{α}, -@code{Γ}, and @code{Ζ}, based on the list saved in variable -@code{org-entities}. As long as the generated DocBook file includes the -corresponding entities, these special characters are recognized. +It is built over HTML back-end: any construct not supported by Markdown +syntax (e.g., tables) will be controlled and translated by @code{html} +back-end (@pxref{HTML export}). -You can customize variable @code{org-export-docbook-doctype} to include the -entities you need. For example, you can set variable -@code{org-export-docbook-doctype} to the following value to recognize all -special characters included in XHTML entities: +@subheading Markdown export commands -@example -" -%xhtml1-symbol; -]> -" -@end example +@table @kbd +@orgcmd{C-c C-e m m,org-md-export-to-markdown} +Export as a text file written in Markdown syntax. For an Org file, +@file{myfile.org}, the resulting file will be @file{myfile.md}. The file +will be overwritten without warning. +@orgcmd{C-c C-e m M,org-md-export-as-markdown} +Export to a temporary buffer. Do not create a file. +@item C-c C-e m o +Export as a text file with Markdown syntax, then open it. +@end table + +@subheading Header and sectioning structure + +@vindex org-md-headline-style +Markdown export can generate both @code{atx} and @code{setext} types for +headlines, according to @code{org-md-headline-style}. The former introduces +a hard limit of two levels, whereas the latter pushes it to six. Headlines +below that limit are exported as lists. You can also set a soft limit before +that one (@pxref{Export settings}). @c begin opendocument -@node OpenDocument Text export, TaskJuggler export, DocBook export, Exporting +@node OpenDocument Text export, iCalendar export, Markdown export, Exporting @section OpenDocument Text export -@cindex K, Jambunathan @cindex ODT @cindex OpenDocument @cindex export, OpenDocument @cindex LibreOffice -@cindex org-odt.el -@cindex org-modules -Org Mode@footnote{Versions 7.8 or later} supports export to OpenDocument Text -(ODT) format using the @file{org-odt.el} module. Documents created -by this exporter use the @cite{OpenDocument-v1.2 +Org mode@footnote{Versions 7.8 or later} supports export to OpenDocument Text +(ODT) format. Documents created by this exporter use the +@cite{OpenDocument-v1.2 specification}@footnote{@url{http://docs.oasis-open.org/office/v1.2/OpenDocument-v1.2.html, Open Document Format for Office Applications (OpenDocument) Version 1.2}} and are compatible with LibreOffice 3.4. @@ -11054,14 +11915,14 @@ output. Check the availability of this program before proceeding further. @cindex active region @cindex transient-mark-mode @table @kbd -@orgcmd{C-c C-e o,org-export-as-odt} +@orgcmd{C-c C-e o o,org-odt-export-to-odt} @cindex property EXPORT_FILE_NAME Export as OpenDocument Text file. -@vindex org-export-odt-preferred-output-format -If @code{org-export-odt-preferred-output-format} is specified, automatically -convert the exported file to that format. @xref{x-export-to-other-formats, , +@vindex org-odt-preferred-output-format +If @code{org-odt-preferred-output-format} is specified, automatically convert +the exported file to that format. @xref{x-export-to-other-formats, , Automatically exporting to other formats}. For an Org file @file{myfile.org}, the ODT file will be @@ -11073,13 +11934,13 @@ tree head will become the document title. If the tree head entry has, or inherits, an @code{EXPORT_FILE_NAME} property, that name will be used for the export. -@orgcmd{C-c C-e O,org-export-as-odt-and-open} +@kbd{C-c C-e o O} Export as an OpenDocument Text file and open the resulting file. -@vindex org-export-odt-preferred-output-format -If @code{org-export-odt-preferred-output-format} is specified, open the -converted file instead. @xref{x-export-to-other-formats, , Automatically -exporting to other formats}. +@vindex org-odt-preferred-output-format +If @code{org-odt-preferred-output-format} is specified, open the converted +file instead. @xref{x-export-to-other-formats, , Automatically exporting to +other formats}. @end table @node Extending ODT export, Applying custom styles, ODT export commands, OpenDocument Text export @@ -11095,7 +11956,7 @@ one format (say @samp{csv}) to another format (say @samp{ods} or @samp{xls}). If you have a working installation of LibreOffice, a document converter is pre-configured for you and you can use it right away. If you would like to use @file{unoconv} as your preferred converter, customize the variable -@code{org-export-odt-convert-process} to point to @code{unoconv}. You can +@code{org-odt-convert-process} to point to @code{unoconv}. You can also use your own favorite converter or tweak the default settings of the @file{LibreOffice} and @samp{unoconv} converters. @xref{Configuring a document converter}. @@ -11103,12 +11964,12 @@ document converter}. @subsubsection Automatically exporting to other formats @anchor{x-export-to-other-formats} -@vindex org-export-odt-preferred-output-format +@vindex org-odt-preferred-output-format Very often, you will find yourself exporting to ODT format, only to immediately save the exported document to other formats like @samp{doc}, @samp{docx}, @samp{rtf}, @samp{pdf} etc. In such cases, you can specify your preferred output format by customizing the variable -@code{org-export-odt-preferred-output-format}. This way, the export commands +@code{org-odt-preferred-output-format}. This way, the export commands (@pxref{x-export-to-odt,,Exporting to ODT}) can be extended to export to a format that is of immediate interest to you. @@ -11121,10 +11982,10 @@ ODT format. LibreOffice converter, mentioned above, is one such converter. Once a converter is configured, you can interact with it using the following command. -@vindex org-export-odt-convert +@vindex org-odt-convert @table @kbd -@item M-x org-export-odt-convert +@item M-x org-odt-convert RET Convert an existing document from one format to another. With a prefix argument, also open the newly produced file. @end table @@ -11161,8 +12022,8 @@ OpenDocument Text (@file{.odt}) or OpenDocument Template (@file{.ott}) file. @item @cindex #+ODT_STYLES_FILE -@vindex org-export-odt-styles-file -Customize the variable @code{org-export-odt-styles-file} and point it to the +@vindex org-odt-styles-file +Customize the variable @code{org-odt-styles-file} and point it to the newly created file. For additional configuration options @pxref{x-overriding-factory-styles,,Overriding factory styles}. @@ -11192,7 +12053,7 @@ the factory settings. @node Links in ODT export, Tables in ODT export, Applying custom styles, OpenDocument Text export @subsection Links in ODT export -@cindex tables, in DocBook export +@cindex links, in ODT export ODT exporter creates native cross-references for internal links. It creates Internet-style links for all other links. @@ -11206,7 +12067,7 @@ with a cross-reference and sequence number of the labeled entity. @node Tables in ODT export, Images in ODT export, Links in ODT export, OpenDocument Text export @subsection Tables in ODT export -@cindex tables, in DocBook export +@cindex tables, in ODT export Export of native Org mode tables (@pxref{Tables}) and simple @file{table.el} tables is supported. However, export of complex @file{table.el} tables---tables @@ -11285,17 +12146,17 @@ You can control the size and scale of the embedded images using the @code{#+ATTR_ODT} attribute. @cindex identify, ImageMagick -@vindex org-export-odt-pixels-per-inch +@vindex org-odt-pixels-per-inch The exporter specifies the desired size of the image in the final document in units of centimeters. In order to scale the embedded images, the exporter queries for pixel dimensions of the images using one of a) ImageMagick's @file{identify} program or b) Emacs `create-image' and `image-size' -APIs.@footnote{Use of @file{ImageMagick} is only desirable. However, if you +APIs@footnote{Use of @file{ImageMagick} is only desirable. However, if you routinely produce documents that have large images or you export your Org files that has images using a Emacs batch script, then the use of -@file{ImageMagick} is mandatory.} The pixel dimensions are subsequently +@file{ImageMagick} is mandatory.}. The pixel dimensions are subsequently converted in to units of centimeters using -@code{org-export-odt-pixels-per-inch}. The default value of this variable is +@code{org-odt-pixels-per-inch}. The default value of this variable is set to @code{display-pixels-per-inch}. You can tweak this variable to achieve the best results. @@ -11404,27 +12265,34 @@ You can use the following commands to quickly verify the reliability of the @LaTeX{}-to-MathML converter. @table @kbd - -@item M-x org-export-as-odf +@item M-x org-odt-export-as-odf RET Convert a @LaTeX{} math snippet to an OpenDocument formula (@file{.odf}) file. -@item M-x org-export-as-odf-and-open +@item M-x org-odt-export-as-odf-and-open RET Convert a @LaTeX{} math snippet to an OpenDocument formula (@file{.odf}) file and open the formula file with the system-registered application. @end table @cindex dvipng +@cindex imagemagick @item PNG images This option is activated on a per-file basis with @example -#+OPTIONS: LaTeX:dvipng +#+OPTIONS: tex:dvipng +@end example + +or: + +@example +#+OPTIONS: tex:imagemagick @end example With this option, @LaTeX{} fragments are processed into PNG images and the resulting images are embedded in the exported document. This method requires -that the @file{dvipng} program be available on your system. +that the @file{dvipng} program or @file{imagemagick} suite be available on +your system. @end enumerate @node Working with MathML or OpenDocument formula files, , Working with @LaTeX{} math snippets, Math formatting in ODT export @@ -11471,15 +12339,15 @@ It could be rendered as shown below in the exported document. Figure 2: Bell curve @end example -@vindex org-export-odt-category-strings +@vindex org-odt-category-map-alist You can modify the category component of the caption by customizing the -variable @code{org-export-odt-category-strings}. For example, to tag all -embedded images with the string @samp{Illustration} (instead of the default -@samp{Figure}) use the following setting. +option @code{org-odt-category-map-alist}. For example, to tag all embedded +images with the string @samp{Illustration} (instead of the default +@samp{Figure}) use the following setting: @lisp -(setq org-export-odt-category-strings - '(("en" "Table" "Illustration" "Equation" "Equation"))) +(setq org-odt-category-map-alist + (("__Figure__" "Illustration" "value" "Figure" org-odt--enumerable-image-p))) @end lisp With this, previous image will be captioned as below in the exported @@ -11500,14 +12368,14 @@ fontification to be turned on.} The auto-generated styles have @samp{OrgSrc} as prefix and inherit their color from the faces used by Emacs @code{font-lock} library for the source language. -@vindex org-export-odt-fontify-srcblocks -If you prefer to use your own custom styles for fontification, you can do so -by customizing the variable -@code{org-export-odt-create-custom-styles-for-srcblocks}. +@vindex org-odt-fontify-srcblocks +If you prefer to use your own custom styles for fontification, you can do +so by customizing the option +@code{org-odt-create-custom-styles-for-srcblocks}. -@vindex org-export-odt-create-custom-styles-for-srcblocks +@vindex org-odt-create-custom-styles-for-srcblocks You can turn off fontification of literal examples by customizing the -variable @code{org-export-odt-fontify-srcblocks}. +option @code{org-odt-fontify-srcblocks}. @node Advanced topics in ODT export, , Literal examples in ODT export, OpenDocument Text export @subsection Advanced topics in ODT export @@ -11538,27 +12406,27 @@ like to tweak the default converter settings, proceed as below. @enumerate @item Register the converter -@vindex org-export-odt-convert-processes -Name your converter and add it to the list of known converters by customizing -the variable @code{org-export-odt-convert-processes}. Also specify how the -converter can be invoked via command-line to effect the conversion. +@vindex org-odt-convert-processes +Name your converter and add it to the list of known converters by +customizing the option @code{org-odt-convert-processes}. Also specify how +the converter can be invoked via command-line to effect the conversion. @item Configure its capabilities -@vindex org-export-odt-convert-capabilities -@anchor{x-odt-converter-capabilities} -Specify the set of formats the converter can handle by customizing the -variable @code{org-export-odt-convert-capabilities}. Use the default value -for this variable as a guide for configuring your converter. As suggested by -the default setting, you can specify the full set of formats supported by the +@vindex org-odt-convert-capabilities +@anchor{x-odt-converter-capabilities} Specify the set of formats the +converter can handle by customizing the variable +@code{org-odt-convert-capabilities}. Use the default value for this +variable as a guide for configuring your converter. As suggested by the +default setting, you can specify the full set of formats supported by the converter and not limit yourself to specifying formats that are related to just the OpenDocument Text format. @item Choose the converter -@vindex org-export-odt-convert-process +@vindex org-odt-convert-process Select the newly added converter as the preferred one by customizing the -variable @code{org-export-odt-convert-process}. +option @code{org-odt-convert-process}. @end enumerate @node Working with OpenDocument style files, Creating one-off styles, Configuring a document converter, Advanced topics in ODT export @@ -11626,9 +12494,9 @@ customize these variables to override the factory styles used by the exporter. @itemize -@anchor{x-org-export-odt-styles-file} +@anchor{x-org-odt-styles-file} @item -@code{org-export-odt-styles-file} +@code{org-odt-styles-file} Use this variable to specify the @file{styles.xml} that will be used in the final output. You can specify one of the following values: @@ -11657,9 +12525,9 @@ like header and footer images. Use the default @file{styles.xml} @end enumerate -@anchor{x-org-export-odt-content-template-file} +@anchor{x-org-odt-content-template-file} @item -@code{org-export-odt-content-template-file} +@code{org-odt-content-template-file} Use this variable to specify the blank @file{content.xml} that will be used in the final output. @@ -11709,7 +12577,7 @@ custom @samp{PageBreak} style as shown below. @example + style:parent-style-name="Text_20_body"> @end example @@ -11746,22 +12614,21 @@ OpenDocument-v1.2 specification.@footnote{@url{http://docs.oasis-open.org/office/v1.2/OpenDocument-v1.2.html, OpenDocument-v1.2 Specification}} - - @subsubheading Custom table styles: an illustration -To have a quick preview of this feature, install the below setting and export -the table that follows. +@vindex org-odt-table-styles +To have a quick preview of this feature, install the below setting and +export the table that follows: @lisp -(setq org-export-odt-table-styles - (append org-export-odt-table-styles - '(("TableWithHeaderRowAndColumn" "Custom" - ((use-first-row-styles . t) - (use-first-column-styles . t))) - ("TableWithFirstRowandLastRow" "Custom" - ((use-first-row-styles . t) - (use-last-row-styles . t)))))) +(setq org-odt-table-styles + (append org-odt-table-styles + '(("TableWithHeaderRowAndColumn" "Custom" + ((use-first-row-styles . t) + (use-first-column-styles . t))) + ("TableWithFirstRowandLastRow" "Custom" + ((use-first-row-styles . t) + (use-last-row-styles . t)))))) @end lisp @example @@ -11774,9 +12641,9 @@ the table that follows. In the above example, you used a template named @samp{Custom} and installed two table styles with the names @samp{TableWithHeaderRowAndColumn} and @samp{TableWithFirstRowandLastRow}. (@strong{Important:} The OpenDocument -styles needed for producing the above template have been pre-defined for you. -These styles are available under the section marked @samp{Custom Table -Template} in @file{OrgOdtContentTemplate.xml} +styles needed for producing the above template have been pre-defined for +you. These styles are available under the section marked @samp{Custom +Table Template} in @file{OrgOdtContentTemplate.xml} (@pxref{x-orgodtcontenttemplate-xml,,Factory styles}). If you need additional templates you have to define these styles yourselves. @@ -11860,9 +12727,9 @@ Define a table style@footnote{See the attributes @code{table:template-name}, @code{table:use-banding-column-styles} of the @code{} element in the OpenDocument-v1.2 specification} -@vindex org-export-odt-table-styles +@vindex org-odt-table-styles To define a table style, create an entry for the style in the variable -@code{org-export-odt-table-styles} and specify the following: +@code{org-odt-table-styles} and specify the following: @itemize @minus @item the name of the table template created in step (1) @@ -11875,211 +12742,53 @@ based on the same template @samp{Custom}. The styles achieve their intended effect by selectively activating the individual cell styles in that template. @lisp -(setq org-export-odt-table-styles - (append org-export-odt-table-styles - '(("TableWithHeaderRowAndColumn" "Custom" - ((use-first-row-styles . t) - (use-first-column-styles . t))) - ("TableWithFirstRowandLastRow" "Custom" - ((use-first-row-styles . t) - (use-last-row-styles . t)))))) +(setq org-odt-table-styles + (append org-odt-table-styles + '(("TableWithHeaderRowAndColumn" "Custom" + ((use-first-row-styles . t) + (use-first-column-styles . t))) + ("TableWithFirstRowandLastRow" "Custom" + ((use-first-row-styles . t) + (use-last-row-styles . t)))))) @end lisp -@item -Associate a table with the table style - -To do this, specify the table style created in step (2) as part of -the @code{ATTR_ODT} line as shown below. - -@example -#+ATTR_ODT: :style "TableWithHeaderRowAndColumn" -| Name | Phone | Age | -| Peter | 1234 | 17 | -| Anna | 4321 | 25 | -@end example -@end enumerate - -@node Validating OpenDocument XML, , Customizing tables in ODT export, Advanced topics in ODT export -@subsubsection Validating OpenDocument XML - -Occasionally, you will discover that the document created by the -ODT exporter cannot be opened by your favorite application. One of -the common reasons for this is that the @file{.odt} file is corrupt. In such -cases, you may want to validate the document against the OpenDocument RELAX -NG Compact Syntax (RNC) schema. - -For de-compressing the @file{.odt} file@footnote{@file{.odt} files are -nothing but @samp{zip} archives}: @inforef{File Archives,,emacs}. For -general help with validation (and schema-sensitive editing) of XML files: -@inforef{Introduction,,nxml-mode}. - -@vindex org-export-odt-schema-dir -If you have ready access to OpenDocument @file{.rnc} files and the needed -schema-locating rules in a single folder, you can customize the variable -@code{org-export-odt-schema-dir} to point to that directory. The -ODT exporter will take care of updating the -@code{rng-schema-locating-files} for you. - -@c end opendocument - -@node TaskJuggler export, Freemind export, OpenDocument Text export, Exporting -@section TaskJuggler export -@cindex TaskJuggler export -@cindex Project management - -@uref{http://www.taskjuggler.org/, TaskJuggler} is a project management tool. -It provides an optimizing scheduler that computes your project time lines and -resource assignments based on the project outline and the constraints that -you have provided. - -The TaskJuggler exporter is a bit different from other exporters, such as the -@code{HTML} and @LaTeX{} exporters for example, in that it does not export all the -nodes of a document or strictly follow the order of the nodes in the -document. - -Instead the TaskJuggler exporter looks for a tree that defines the tasks and -a optionally tree that defines the resources for this project. It then -creates a TaskJuggler file based on these trees and the attributes defined in -all the nodes. - -@subsection TaskJuggler export commands - -@table @kbd -@orgcmd{C-c C-e j,org-export-as-taskjuggler} -Export as a TaskJuggler file. - -@orgcmd{C-c C-e J,org-export-as-taskjuggler-and-open} -Export as a TaskJuggler file and then open the file with TaskJugglerUI. -@end table - -@subsection Tasks - -@vindex org-export-taskjuggler-project-tag -Create your tasks as you usually do with Org mode. Assign efforts to each -task using properties (it is easiest to do this in the column view). You -should end up with something similar to the example by Peter Jones in -@url{http://www.contextualdevelopment.com/static/artifacts/articles/2008/project-planning/project-planning.org}. -Now mark the top node of your tasks with a tag named -@code{:taskjuggler_project:} (or whatever you customized -@code{org-export-taskjuggler-project-tag} to). You are now ready to export -the project plan with @kbd{C-c C-e J} which will export the project plan and -open a gantt chart in TaskJugglerUI. - -@subsection Resources - -@vindex org-export-taskjuggler-resource-tag -Next you can define resources and assign those to work on specific tasks. You -can group your resources hierarchically. Tag the top node of the resources -with @code{:taskjuggler_resource:} (or whatever you customized -@code{org-export-taskjuggler-resource-tag} to). You can optionally assign an -identifier (named @samp{resource_id}) to the resources (using the standard -Org properties commands, @pxref{Property syntax}) or you can let the exporter -generate identifiers automatically (the exporter picks the first word of the -headline as the identifier as long as it is unique---see the documentation of -@code{org-taskjuggler-get-unique-id}). Using that identifier you can then -allocate resources to tasks. This is again done with the @samp{allocate} -property on the tasks. Do this in column view or when on the task type -@kbd{C-c C-x p allocate @key{RET} @key{RET}}. - -Once the allocations are done you can again export to TaskJuggler and check -in the Resource Allocation Graph which person is working on what task at what -time. - -@subsection Export of properties - -The exporter also takes TODO state information into consideration, i.e., if a -task is marked as done it will have the corresponding attribute in -TaskJuggler (@samp{complete 100}). Also it will export any property on a task -resource or resource node which is known to TaskJuggler, such as -@samp{limits}, @samp{vacation}, @samp{shift}, @samp{booking}, -@samp{efficiency}, @samp{journalentry}, @samp{rate} for resources or -@samp{account}, @samp{start}, @samp{note}, @samp{duration}, @samp{end}, -@samp{journalentry}, @samp{milestone}, @samp{reference}, @samp{responsible}, -@samp{scheduling}, etc.@: for tasks. - -@subsection Dependencies - -The exporter will handle dependencies that are defined in the tasks either -with the @samp{ORDERED} attribute (@pxref{TODO dependencies}), with the -@samp{BLOCKER} attribute (see @file{org-depend.el}) or alternatively with a -@samp{depends} attribute. Both the @samp{BLOCKER} and the @samp{depends} -attribute can be either @samp{previous-sibling} or a reference to an -identifier (named @samp{task_id}) which is defined for another task in the -project. @samp{BLOCKER} and the @samp{depends} attribute can define multiple -dependencies separated by either space or comma. You can also specify -optional attributes on the dependency by simply appending it. The following -examples should illustrate this: - -@example -* Preparation - :PROPERTIES: - :task_id: preparation - :ORDERED: t - :END: -* Training material - :PROPERTIES: - :task_id: training_material - :ORDERED: t - :END: -** Markup Guidelines - :PROPERTIES: - :Effort: 2d - :END: -** Workflow Guidelines - :PROPERTIES: - :Effort: 2d - :END: -* Presentation - :PROPERTIES: - :Effort: 2d - :BLOCKER: training_material @{ gapduration 1d @} preparation - :END: -@end example - -@subsection Reports - -@vindex org-export-taskjuggler-default-reports -TaskJuggler can produce many kinds of reports (e.g., gantt chart, resource -allocation, etc). The user defines what kind of reports should be generated -for a project in the TaskJuggler file. The exporter will automatically insert -some default reports in the file. These defaults are defined in -@code{org-export-taskjuggler-default-reports}. They can be modified using -customize along with a number of other options. For a more complete list, see -@kbd{M-x customize-group @key{RET} org-export-taskjuggler @key{RET}}. +@item +Associate a table with the table style -For more information and examples see the Org-taskjuggler tutorial at -@uref{http://orgmode.org/worg/org-tutorials/org-taskjuggler.html}. +To do this, specify the table style created in step (2) as part of +the @code{ATTR_ODT} line as shown below. -@node Freemind export, XOXO export, TaskJuggler export, Exporting -@section Freemind export -@cindex Freemind export -@cindex mind map +@example +#+ATTR_ODT: :style "TableWithHeaderRowAndColumn" +| Name | Phone | Age | +| Peter | 1234 | 17 | +| Anna | 4321 | 25 | +@end example +@end enumerate -The Freemind exporter was written by Lennart Borgman. +@node Validating OpenDocument XML, , Customizing tables in ODT export, Advanced topics in ODT export +@subsubsection Validating OpenDocument XML -@table @kbd -@orgcmd{C-c C-e m,org-export-as-freemind} -Export as a Freemind mind map. For an Org file @file{myfile.org}, the Freemind -file will be @file{myfile.mm}. -@end table +Occasionally, you will discover that the document created by the +ODT exporter cannot be opened by your favorite application. One of +the common reasons for this is that the @file{.odt} file is corrupt. In such +cases, you may want to validate the document against the OpenDocument RELAX +NG Compact Syntax (RNC) schema. -@node XOXO export, iCalendar export, Freemind export, Exporting -@section XOXO export -@cindex XOXO export +For de-compressing the @file{.odt} file@footnote{@file{.odt} files are +nothing but @samp{zip} archives}: @inforef{File Archives,,emacs}. For +general help with validation (and schema-sensitive editing) of XML files: +@inforef{Introduction,,nxml-mode}. -Org mode contains an exporter that produces XOXO-style output. -Currently, this exporter only handles the general outline structure and -does not interpret any additional Org mode features. +@vindex org-odt-schema-dir +If you have ready access to OpenDocument @file{.rnc} files and the needed +schema-locating rules in a single folder, you can customize the variable +@code{org-odt-schema-dir} to point to that directory. The ODT exporter +will take care of updating the @code{rng-schema-locating-files} for you. -@table @kbd -@orgcmd{C-c C-e x,org-export-as-xoxo} -Export as an XOXO file. For an Org file @file{myfile.org}, the XOXO file will be -@file{myfile.html}. -@orgkey{C-c C-e v x} -Export only the visible part of the document. -@end table +@c end opendocument -@node iCalendar export, , XOXO export, Exporting +@node iCalendar export, Other built-in back-ends, OpenDocument Text export, Exporting @section iCalendar export @cindex iCalendar export @@ -12118,19 +12827,19 @@ In this way the UID remains unique, but a synchronization program can still figure out from which entry all the different instances originate. @table @kbd -@orgcmd{C-c C-e i,org-export-icalendar-this-file} -Create iCalendar entries for the current file and store them in the same +@orgcmd{C-c C-e c f,org-icalendar-export-to-ics} +Create iCalendar entries for the current buffer and store them in the same directory, using a file extension @file{.ics}. -@orgcmd{C-c C-e I, org-export-icalendar-all-agenda-files} +@orgcmd{C-c C-e c a, org-icalendar-export-agenda-files} @vindex org-agenda-files -Like @kbd{C-c C-e i}, but do this for all files in +Like @kbd{C-c C-e c f}, but do this for all files in @code{org-agenda-files}. For each of these files, a separate iCalendar file will be written. -@orgcmd{C-c C-e c,org-export-icalendar-combine-agenda-files} -@vindex org-combined-agenda-icalendar-file +@orgcmd{C-c C-e c c,org-icalendar-combine-agenda-files} +@vindex org-icalendar-combined-agenda-file Create a single large iCalendar file from all files in @code{org-agenda-files} and write it to the file given by -@code{org-combined-agenda-icalendar-file}. +@code{org-icalendar-combined-agenda-file}. @end table @vindex org-use-property-inheritance @@ -12148,6 +12857,233 @@ and the description from the body (limited to How this calendar is best read and updated, depends on the application you are using. The FAQ covers this issue. +@node Other built-in back-ends, Export in foreign buffers, iCalendar export, Exporting +@section Other built-in back-ends +@cindex export back-ends, built-in +@vindex org-export-backends + +On top of the aforemetioned back-ends, Org comes with other built-in ones: + +@itemize +@item @file{ox-man.el}: export to a man page. +@item @file{ox-texinfo.el}: export to @code{Texinfo} format. +@item @file{ox-org.el}: export to an Org document. +@end itemize + +To activate these export back-end, customize @code{org-export-backends} or +load them directly with e.g., @code{(require 'ox-texinfo)}. This will add +new keys in the export dispatcher (@pxref{The Export Dispatcher}). + +See the comment section of these files for more information on how to use +them. + +@node Export in foreign buffers, Advanced configuration, Other built-in back-ends, Exporting +@section Export in foreign buffers + +Most built-in back-ends come with a command to convert the selected region +into a selected format and replace this region by the exported output. Here +is a list of such conversion commands: + +@table @code +@item org-html-convert-region-to-html +Convert the selected region into HTML. +@item org-latex-convert-region-to-latex +Convert the selected region into @LaTeX{}. +@item org-texinfo-convert-region-to-texinfo +Convert the selected region into @code{Texinfo}. +@item org-md-convert-region-to-md +Convert the selected region into @code{MarkDown}. +@end table + +This is particularily useful for converting tables and lists in foreign +buffers. E.g., in a HTML buffer, you can turn on @code{orgstruct-mode}, then +use Org commands for editing a list, and finally select and convert the list +with @code{M-x org-html-convert-region-to-html RET}. + +@node Advanced configuration, , Export in foreign buffers, Exporting +@section Advanced configuration + +@subheading Hooks + +@vindex org-export-before-processing-hook +@vindex org-export-before-parsing-hook +Two hooks are run during the first steps of the export process. The first +one, @code{org-export-before-processing-hook} is called before expanding +macros, Babel code and include keywords in the buffer. The second one, +@code{org-export-before-parsing-hook}, as its name suggests, happens just +before parsing the buffer. Their main use is for heavy duties, that is +duties involving structural modifications of the document. For example, one +may want to remove every headline in the buffer during export. The following +code can achieve this: + +@lisp +@group +(defun my-headline-removal (backend) + "Remove all headlines in the current buffer. +BACKEND is the export back-end being used, as a symbol." + (org-map-entries + (lambda () (delete-region (point) (progn (forward-line) (point)))))) + +(add-hook 'org-export-before-parsing-hook 'my-headline-removal) +@end group +@end lisp + +Note that functions used in these hooks require a mandatory argument, +a symbol representing the back-end used. + +@subheading Filters + +@cindex Filters, exporting +Filters are lists of functions applied on a specific part of the output from +a given back-end. More explicitly, each time a back-end transforms an Org +object or element into another language, all functions within a given filter +type are called in turn on the string produced. The string returned by the +last function will be the one used in the final output. + +There are filters sets for each type of element or object, for plain text, +for the parse tree, for the export options and for the final output. They +are all named after the same scheme: @code{org-export-filter-TYPE-functions}, +where @code{TYPE} is the type targeted by the filter. Valid types are: + +@multitable @columnfractions .33 .33 .33 +@item bold +@tab babel-call +@tab center-block +@item clock +@tab code +@tab comment +@item comment-block +@tab diary-sexp +@tab drawer +@item dynamic-block +@tab entity +@tab example-block +@item export-block +@tab export-snippet +@tab final-output +@item fixed-width +@tab footnote-definition +@tab footnote-reference +@item headline +@tab horizontal-rule +@tab inline-babel-call +@item inline-src-block +@tab inlinetask +@tab italic +@item item +@tab keyword +@tab latex-environment +@item latex-fragment +@tab line-break +@tab link +@item node-property +@tab options +@tab paragraph +@item parse-tree +@tab plain-list +@tab plain-text +@item planning +@tab property-drawer +@tab quote-block +@item quote-section +@tab radio-target +@tab section +@item special-block +@tab src-block +@tab statistics-cookie +@item strike-through +@tab subscript +@tab superscript +@item table +@tab table-cell +@tab table-row +@item target +@tab timestamp +@tab underline +@item verbatim +@tab verse-block +@tab +@end multitable + +For example, the following snippet allows me to use non-breaking spaces in +the Org buffer and get them translated into @LaTeX{} without using the +@code{\nbsp} macro (where @code{_} stands for the non-breaking space): + +@lisp +@group +(defun my-latex-filter-nobreaks (text backend info) + "Ensure \" \" are properly handled in LaTeX export." + (when (org-export-derived-backend-p backend 'latex) + (replace-regexp-in-string " " "~" text))) + +(add-to-list 'org-export-filter-plain-text-functions + 'my-latex-filter-nobreaks) +@end group +@end lisp + +Three arguments must be provided to a filter: the code being changed, the +back-end used, and some information about the export process. You can safely +ignore the third argument for most purposes. Note the use of +@code{org-export-derived-backend-p}, which ensures that the filter will only +be applied when using @code{latex} back-end or any other back-end derived +from it (e.g., @code{beamer}). + +@subheading Extending an existing back-end + +This is obviously the most powerful customization, since the changes happen +at the parser level. Indeed, some export back-ends are built as extensions +of other ones (e.g. Markdown back-end an extension of HTML back-end). + +Extending a back-end means that if an element type is not transcoded by the +new back-end, it will be handled by the original one. Hence you can extend +specific parts of a back-end without too much work. + +As an example, imagine we want the @code{ascii} back-end to display the +language used in a source block, when it is available, but only when some +attribute is non-@code{nil}, like the following: + +@example +#+ATTR_ASCII: :language t +@end example + +Because that back-end is lacking in that area, we are going to create a new +back-end, @code{my-ascii} that will do the job. + +@lisp +@group +(defun my-ascii-src-block (src-block contents info) + "Transcode a SRC-BLOCK element from Org to ASCII. +CONTENTS is nil. INFO is a plist used as a communication +channel." + (if (not (org-export-read-attribute :attr_ascii src-block :language)) + (org-export-with-backend 'ascii src-block contents info) + (concat + (format ",--[ %s ]--\n%s`----" + (org-element-property :language src-block) + (replace-regexp-in-string + "^" "| " + (org-element-normalize-string + (org-export-format-code-default src-block info))))))) + +(org-export-define-derived-backend 'my-ascii 'ascii + :translate-alist '((src-block . my-ascii-src-block))) +@end group +@end lisp + +The @code{my-ascii-src-block} function looks at the attribute above the +element. If it isn’t true, it gives hand to the @code{ascii} back-end. +Otherwise, it creates a box around the code, leaving room for the language. +A new back-end is then created. It only changes its behaviour when +translating @code{src-block} type element. Now, all it takes to use the new +back-end is calling the following from an Org buffer: + +@smalllisp +(org-export-to-buffer 'my-ascii "*Org MY-ASCII Export*") +@end smalllisp + +It is obviously possible to write an interactive function for this, install +it in the export dispatcher menu, and so on. + @node Publishing, Working With Source Code, Exporting, Top @chapter Publishing @cindex publishing @@ -12227,7 +13163,7 @@ and where to put published files. @tab Directory containing publishing source files @item @code{:publishing-directory} @tab Directory where output files will be published. You can directly -publish to a webserver using a file name syntax appropriate for +publish to a web server using a file name syntax appropriate for the Emacs @file{tramp} package. Or you can publish to a local directory and use external tools to upload your website (@pxref{Uploading files}). @item @code{:preparation-function} @@ -12266,7 +13202,7 @@ extension. and @code{:exclude}. @item @code{:recursive} -@tab Non-nil means, check base-directory recursively for files to publish. +@tab non-@code{nil} means, check base-directory recursively for files to publish. @end multitable @node Publishing action, Publishing options, Selecting files, Configuration @@ -12276,201 +13212,164 @@ and @code{:exclude}. Publishing means that a file is copied to the destination directory and possibly transformed in the process. The default transformation is to export Org files as HTML files, and this is done by the function -@code{org-publish-org-to-html} which calls the HTML exporter (@pxref{HTML +@code{org-html-publish-to-html}, which calls the HTML exporter (@pxref{HTML export}). But you also can publish your content as PDF files using -@code{org-publish-org-to-pdf}, or as @code{ascii}, @code{latin1} or -@code{utf8} encoded files using the corresponding functions. If you want to -publish the Org file itself, but with @i{archived}, @i{commented}, and -@i{tag-excluded} trees removed, use @code{org-publish-org-to-org} and set the -parameters @code{:plain-source} and/or @code{:htmlized-source}. This will -produce @file{file.org} and @file{file.org.html} in the publishing -directory@footnote{@file{file-source.org} and @file{file-source.org.html} if -source and publishing directories are equal. Note that with this kind of -setup, you need to add @code{:exclude "-source\\.org"} to the project -definition in @code{org-publish-project-alist} to prevent the published -source files from being considered as new org files the next time the project -is published.}. Other files like images only need to be copied to the -publishing destination; for this you may use @code{org-publish-attachment}. -For non-Org files, you always need to specify the publishing function: +@code{org-latex-publish-to-pdf} or as @code{ascii}, @code{Texinfo}, etc., +using the corresponding functions. + +If you want to publish the Org file as an @code{.org} file but with the +@i{archived}, @i{commented} and @i{tag-excluded} trees removed, use the +function @code{org-org-publish-to-org}. This will produce @file{file.org} +and put it in the publishing directory. If you want a htmlized version of +this file, set the parameter @code{:htmlized-source} to @code{t}, it will +produce @file{file.org.html} in the publishing directory@footnote{If the +publishing directory is the same than the source directory, @file{file.org} +will be exported as @file{file.org.org}, so probably don't want to do this.}. + +Other files like images only need to be copied to the publishing destination. +For this you can use @code{org-publish-attachment}. For non-org files, you +always need to specify the publishing function: @multitable @columnfractions 0.3 0.7 @item @code{:publishing-function} @tab Function executing the publication of a file. This may also be a list of functions, which will all be called in turn. -@item @code{:plain-source} -@tab Non-nil means, publish plain source. @item @code{:htmlized-source} -@tab Non-nil means, publish htmlized source. +@tab non-@code{nil} means, publish htmlized source. @end multitable The function must accept three arguments: a property list containing at least -a @code{:publishing-directory} property, the name of the file to be -published, and the path to the publishing directory of the output file. It -should take the specified file, make the necessary transformation (if any) -and place the result into the destination folder. +a @code{:publishing-directory} property, the name of the file to be published +and the path to the publishing directory of the output file. It should take +the specified file, make the necessary transformation (if any) and place the +result into the destination folder. @node Publishing options, Publishing links, Publishing action, Configuration -@subsection Options for the HTML/@LaTeX{} exporters +@subsection Options for the exporters @cindex options, for publishing -The property list can be used to set many export options for the HTML -and @LaTeX{} exporters. In most cases, these properties correspond to user -variables in Org. The table below lists these properties along -with the variable they belong to. See the documentation string for the -respective variable for details. +The property list can be used to set many export options for the exporters. +In most cases, these properties correspond to user variables in Org. The +first table below lists these properties along with the variable they belong +to. The second table list HTML specific properties. See the documentation +string of these options for details. -@vindex org-export-html-link-up -@vindex org-export-html-link-home -@vindex org-export-default-language @vindex org-display-custom-times +@vindex org-export-default-language +@vindex org-export-exclude-tags @vindex org-export-headline-levels -@vindex org-export-with-section-numbers -@vindex org-export-section-number-format -@vindex org-export-with-toc @vindex org-export-preserve-breaks +@vindex org-export-publishing-directory +@vindex org-export-select-tags @vindex org-export-with-archived-trees +@vindex org-export-with-author +@vindex org-export-with-creator +@vindex org-export-with-drawers +@vindex org-export-with-email @vindex org-export-with-emphasize -@vindex org-export-with-sub-superscripts -@vindex org-export-with-special-strings +@vindex org-export-with-fixed-width @vindex org-export-with-footnotes -@vindex org-export-with-drawers +@vindex org-export-with-latex +@vindex org-export-with-planning +@vindex org-export-with-priority +@vindex org-export-with-section-numbers +@vindex org-export-with-special-strings +@vindex org-export-with-sub-superscripts +@vindex org-export-with-tables @vindex org-export-with-tags -@vindex org-export-with-todo-keywords @vindex org-export-with-tasks -@vindex org-export-with-done-tasks -@vindex org-export-with-priority -@vindex org-export-with-TeX-macros -@vindex org-export-with-LaTeX-fragments -@vindex org-export-skip-text-before-1st-heading -@vindex org-export-with-fixed-width @vindex org-export-with-timestamps -@vindex org-export-author-info -@vindex org-export-email-info -@vindex org-export-creator-info -@vindex org-export-time-stamp-file -@vindex org-export-with-tables -@vindex org-export-highlight-first-table-line -@vindex org-export-html-style-include-default -@vindex org-export-html-style-include-scripts -@vindex org-export-html-style -@vindex org-export-html-style-extra -@vindex org-export-html-link-org-files-as-html -@vindex org-export-html-inline-images -@vindex org-export-html-extension -@vindex org-export-html-table-tag -@vindex org-export-html-expand -@vindex org-export-html-with-timestamp -@vindex org-export-publishing-directory -@vindex org-export-html-preamble -@vindex org-export-html-postamble -@vindex user-full-name +@vindex org-export-with-toc +@vindex org-export-with-todo-keywords @vindex user-mail-address -@vindex org-export-select-tags -@vindex org-export-exclude-tags @multitable @columnfractions 0.32 0.68 -@item @code{:link-up} @tab @code{org-export-html-link-up} -@item @code{:link-home} @tab @code{org-export-html-link-home} -@item @code{:language} @tab @code{org-export-default-language} -@item @code{:customtime} @tab @code{org-display-custom-times} +@item @code{:archived-trees} @tab @code{org-export-with-archived-trees} +@item @code{:exclude-tags} @tab @code{org-export-exclude-tags} @item @code{:headline-levels} @tab @code{org-export-headline-levels} -@item @code{:section-numbers} @tab @code{org-export-with-section-numbers} -@item @code{:section-number-format} @tab @code{org-export-section-number-format} -@item @code{:table-of-contents} @tab @code{org-export-with-toc} +@item @code{:language} @tab @code{org-export-default-language} @item @code{:preserve-breaks} @tab @code{org-export-preserve-breaks} -@item @code{:archived-trees} @tab @code{org-export-with-archived-trees} -@item @code{:emphasize} @tab @code{org-export-with-emphasize} -@item @code{:sub-superscript} @tab @code{org-export-with-sub-superscripts} -@item @code{:special-strings} @tab @code{org-export-with-special-strings} -@item @code{:footnotes} @tab @code{org-export-with-footnotes} -@item @code{:drawers} @tab @code{org-export-with-drawers} -@item @code{:tags} @tab @code{org-export-with-tags} -@item @code{:todo-keywords} @tab @code{org-export-with-todo-keywords} -@item @code{:tasks} @tab @code{org-export-with-tasks} -@item @code{:priority} @tab @code{org-export-with-priority} -@item @code{:TeX-macros} @tab @code{org-export-with-TeX-macros} -@item @code{:LaTeX-fragments} @tab @code{org-export-with-LaTeX-fragments} -@item @code{:latex-listings} @tab @code{org-export-latex-listings} -@item @code{:skip-before-1st-heading} @tab @code{org-export-skip-text-before-1st-heading} -@item @code{:fixed-width} @tab @code{org-export-with-fixed-width} -@item @code{:timestamps} @tab @code{org-export-with-timestamps} -@item @code{:author} @tab @code{user-full-name} -@item @code{:email} @tab @code{user-mail-address} : @code{addr;addr;..} -@item @code{:author-info} @tab @code{org-export-author-info} -@item @code{:email-info} @tab @code{org-export-email-info} -@item @code{:creator-info} @tab @code{org-export-creator-info} -@item @code{:tables} @tab @code{org-export-with-tables} -@item @code{:table-auto-headline} @tab @code{org-export-highlight-first-table-line} -@item @code{:style-include-default} @tab @code{org-export-html-style-include-default} -@item @code{:style-include-scripts} @tab @code{org-export-html-style-include-scripts} -@item @code{:style} @tab @code{org-export-html-style} -@item @code{:style-extra} @tab @code{org-export-html-style-extra} -@item @code{:convert-org-links} @tab @code{org-export-html-link-org-files-as-html} -@item @code{:inline-images} @tab @code{org-export-html-inline-images} -@item @code{:html-extension} @tab @code{org-export-html-extension} -@item @code{:html-preamble} @tab @code{org-export-html-preamble} -@item @code{:html-postamble} @tab @code{org-export-html-postamble} -@item @code{:xml-declaration} @tab @code{org-export-html-xml-declaration} -@item @code{:html-table-tag} @tab @code{org-export-html-table-tag} -@item @code{:expand-quoted-html} @tab @code{org-export-html-expand} -@item @code{:timestamp} @tab @code{org-export-html-with-timestamp} @item @code{:publishing-directory} @tab @code{org-export-publishing-directory} +@item @code{:section-numbers} @tab @code{org-export-with-section-numbers} @item @code{:select-tags} @tab @code{org-export-select-tags} -@item @code{:exclude-tags} @tab @code{org-export-exclude-tags} -@item @code{:latex-image-options} @tab @code{org-export-latex-image-default-option} +@item @code{:with-author} @tab @code{org-export-with-author} +@item @code{:with-creator} @tab @code{org-export-with-creator} +@item @code{:with-drawers} @tab @code{org-export-with-drawers} +@item @code{:with-email} @tab @code{org-export-with-email} +@item @code{:with-emphasize} @tab @code{org-export-with-emphasize} +@item @code{:with-fixed-width} @tab @code{org-export-with-fixed-width} +@item @code{:with-footnotes} @tab @code{org-export-with-footnotes} +@item @code{:with-latex} @tab @code{org-export-with-latex} +@item @code{:with-planning} @tab @code{org-export-with-planning} +@item @code{:with-priority} @tab @code{org-export-with-priority} +@item @code{:with-special-strings} @tab @code{org-export-with-special-strings} +@item @code{:with-sub-superscript} @tab @code{org-export-with-sub-superscripts} +@item @code{:with-tables} @tab @code{org-export-with-tables} +@item @code{:with-tags} @tab @code{org-export-with-tags} +@item @code{:with-tasks} @tab @code{org-export-with-tasks} +@item @code{:with-timestamps} @tab @code{org-export-with-timestamps} +@item @code{:with-toc} @tab @code{org-export-with-toc} +@item @code{:with-todo-keywords} @tab @code{org-export-with-todo-keywords} @end multitable -Most of the @code{org-export-with-*} variables have the same effect in -both HTML and @LaTeX{} exporters, except for @code{:TeX-macros} and -@code{:LaTeX-fragments} options, respectively @code{nil} and @code{t} in the -@LaTeX{} export. See @code{org-export-plist-vars} to check this list of -options. - +@vindex org-html-doctype +@vindex org-html-xml-declaration +@vindex org-html-link-up +@vindex org-html-link-home +@vindex org-html-link-org-files-as-html +@vindex org-html-head +@vindex org-html-head-extra +@vindex org-html-inline-images +@vindex org-html-extension +@vindex org-html-preamble +@vindex org-html-postamble +@vindex org-html-table-default-attributes +@vindex org-html-head-include-default-style +@vindex org-html-head-include-scripts +@multitable @columnfractions 0.32 0.68 +@item @code{:html-doctype} @tab @code{org-html-doctype} +@item @code{:html-xml-declaration} @tab @code{org-html-xml-declaration} +@item @code{:html-link-up} @tab @code{org-html-link-up} +@item @code{:html-link-home} @tab @code{org-html-link-home} +@item @code{:html-link-org-as-html} @tab @code{org-html-link-org-files-as-html} +@item @code{:html-head} @tab @code{org-html-head} +@item @code{:html-head-extra} @tab @code{org-html-head-extra} +@item @code{:html-inline-images} @tab @code{org-html-inline-images} +@item @code{:html-extension} @tab @code{org-html-extension} +@item @code{:html-preamble} @tab @code{org-html-preamble} +@item @code{:html-postamble} @tab @code{org-html-postamble} +@item @code{:html-table-attributes} @tab @code{org-html-table-default-attributes} +@item @code{:html-head-include-default-style} @tab @code{org-html-head-include-default-style} +@item @code{:html-head-include-scripts} @tab @code{org-html-head-include-scripts} +@end multitable +Most of the @code{org-export-with-*} variables have the same effect in each +exporter. @vindex org-publish-project-alist -When a property is given a value in @code{org-publish-project-alist}, -its setting overrides the value of the corresponding user variable (if -any) during publishing. Options set within a file (@pxref{Export -options}), however, override everything. +When a property is given a value in @code{org-publish-project-alist}, its +setting overrides the value of the corresponding user variable (if any) +during publishing. Options set within a file (@pxref{Export settings}), +however, override everything. @node Publishing links, Sitemap, Publishing options, Configuration @subsection Links between published files @cindex links, publishing -To create a link from one Org file to another, you would use -something like @samp{[[file:foo.org][The foo]]} or simply -@samp{file:foo.org.} (@pxref{Hyperlinks}). When published, this link -becomes a link to @file{foo.html}. In this way, you can interlink the -pages of your "org web" project and the links will work as expected when -you publish them to HTML@. If you also publish the Org source file and want -to link to that, use an @code{http:} link instead of a @code{file:} link, -because @code{file:} links are converted to link to the corresponding -@file{html} file. +To create a link from one Org file to another, you would use something like +@samp{[[file:foo.org][The foo]]} or simply @samp{file:foo.org.} +(@pxref{Hyperlinks}). When published, this link becomes a link to +@file{foo.html}. You can thus interlink the pages of your "org web" project +and the links will work as expected when you publish them to HTML@. If you +also publish the Org source file and want to link to it, use an @code{http:} +link instead of a @code{file:} link, because @code{file:} links are converted +to link to the corresponding @file{html} file. You may also link to related files, such as images. Provided you are careful with relative file names, and provided you have also configured Org to upload the related files, these links will work too. See @ref{Complex example}, for an example of this usage. -Sometimes an Org file to be published may contain links that are -only valid in your production environment, but not in the publishing -location. In this case, use the property - -@multitable @columnfractions 0.4 0.6 -@item @code{:link-validation-function} -@tab Function to validate links -@end multitable - -@noindent -to define a function for checking link validity. This function must -accept two arguments, the file name and a directory relative to which -the file name is interpreted in the production environment. If this -function returns @code{nil}, then the HTML generator will only insert a -description into the HTML file, but no link. One option for this -function is @code{org-publish-validate-link} which checks if the given -file is part of any project in @code{org-publish-project-alist}. - @node Sitemap, Generating an index, Publishing links, Configuration @subsection Generating a sitemap @cindex sitemap, of published pages @@ -12480,7 +13379,7 @@ a map of files for a given project. @multitable @columnfractions 0.35 0.65 @item @code{:auto-sitemap} -@tab When non-nil, publish a sitemap during @code{org-publish-current-project} +@tab When non-@code{nil}, publish a sitemap during @code{org-publish-current-project} or @code{org-publish-all}. @item @code{:sitemap-filename} @@ -12525,7 +13424,7 @@ a sitemap entry's date is to be formatted. This property bypasses @code{org-publish-sitemap-date-format} which defaults to @code{%Y-%m-%d}. @item @code{:sitemap-sans-extension} -@tab When non-nil, remove filenames' extensions from the generated sitemap. +@tab When non-@code{nil}, remove filenames' extensions from the generated sitemap. Useful to have cool URIs (see @uref{http://www.w3.org/Provider/Style/URI}). Defaults to @code{nil}. @@ -12539,7 +13438,7 @@ Org mode can generate an index across the files of a publishing project. @multitable @columnfractions 0.25 0.75 @item @code{:makeindex} -@tab When non-nil, generate in index in the file @file{theindex.org} and +@tab When non-@code{nil}, generate in index in the file @file{theindex.org} and publish it as @file{theindex.html}. @end multitable @@ -12605,10 +13504,10 @@ directory on the local machine. :base-directory "~/org/" :publishing-directory "~/public_html" :section-numbers nil - :table-of-contents nil - :style ""))) + :with-toc nil + :html-head ""))) @end lisp @node Complex example, , Simple example, Sample configuration @@ -12638,12 +13537,12 @@ right place on the web server, and publishing images to it. :base-directory "~/org/" :base-extension "org" :publishing-directory "/ssh:user@@host:~/html/notebook/" - :publishing-function org-publish-org-to-html + :publishing-function org-html-publish-to-html :exclude "PrivatePage.org" ;; regexp :headline-levels 3 :section-numbers nil - :table-of-contents nil - :style "" :html-preamble t) @@ -12667,13 +13566,13 @@ right place on the web server, and publishing images to it. Once properly configured, Org can publish with the following commands: @table @kbd -@orgcmd{C-c C-e X,org-publish} +@orgcmd{C-c C-e P x,org-publish} Prompt for a specific project and publish all files that belong to it. -@orgcmd{C-c C-e P,org-publish-current-project} +@orgcmd{C-c C-e P p,org-publish-current-project} Publish the project containing the current file. -@orgcmd{C-c C-e F,org-publish-current-file} +@orgcmd{C-c C-e P f,org-publish-current-file} Publish only the current file. -@orgcmd{C-c C-e E,org-publish-all} +@orgcmd{C-c C-e P a,org-publish-all} Publish every project. @end table @@ -12770,7 +13669,7 @@ src_[
]@{@} @table @code @item <#+NAME: name> This line associates a name with the code block. This is similar to the -@code{#+TBLNAME: NAME} lines that can be used to name tables in Org mode +@code{#+NAME: Name} lines that can be used to name tables in Org mode files. Referencing the name of a code block makes it possible to evaluate the block from other places in the file, from other files, or from Org mode table formulas (see @ref{The spreadsheet}). Names are assumed to be unique @@ -12802,11 +13701,16 @@ Source code in the specified language. @cindex code block, editing @cindex source code, editing +@vindex org-edit-src-auto-save-idle-delay +@vindex org-edit-src-turn-on-auto-save @kindex C-c ' -Use @kbd{C-c '} to edit the current code block. This brings up -a language major-mode edit buffer containing the body of the code -block. Saving this buffer will write the new contents back to the Org -buffer. Use @kbd{C-c '} again to exit. +Use @kbd{C-c '} to edit the current code block. This brings up a language +major-mode edit buffer containing the body of the code block. Manually +saving this buffer with @key{C-x C-s} will write the contents back to the Org +buffer. You can also set @code{org-edit-src-auto-save-idle-delay} to save the +base buffer after some idle delay, or @code{org-edit-src-turn-on-auto-save} +to auto-save this buffer into a separate file using @code{auto-save-mode}. +Use @kbd{C-c '} again to exit. The @code{org-src-mode} minor mode will be active in the edit buffer. The following variables can be used to configure the behavior of the edit @@ -12826,7 +13730,7 @@ This variable is especially useful for tangling languages such as Python, in which whitespace indentation in the output is critical. @item org-src-ask-before-returning-to-edit-buffer By default, Org will ask before returning to an open edit buffer. Set this -variable to nil to switch without asking. +variable to @code{nil} to switch without asking. @end table To turn on native code fontification in the @emph{Org} buffer, configure the @@ -12851,6 +13755,7 @@ The @code{:exports} header argument can be used to specify export behavior: @subsubheading Header arguments: + @table @code @item :exports code The default in most languages. The body of the code block is exported, as @@ -12872,7 +13777,12 @@ Setting the @code{org-export-babel-evaluate} variable to @code{nil} will ensure that no code blocks are evaluated as part of the export process. This can be useful in situations where potentially untrusted Org mode files are exported in an automated fashion, for example when Org mode is used as the -markup language for a wiki. +markup language for a wiki. It is also possible to set this variable to +@code{‘inline-only}. In that case, only inline code blocks will be +evaluated, in order to insert their results. Non-inline code blocks are +assumed to have their results already inserted in the buffer by manual +evaluation. This setting is useful to avoid expensive recalculations during +export, not to provide security. @comment node-name, next, previous, up @comment Extracting source code, Evaluating code blocks, Exporting code blocks, Working With Source Code @@ -12889,6 +13799,7 @@ using @code{org-babel-expand-src-block} which can expand both variable and ``noweb'' style references (see @ref{Noweb reference syntax}). @subsubheading Header arguments + @table @code @item :tangle no The default. The code block is not included in the tangled output. @@ -12902,14 +13813,18 @@ Include the code block in the tangled output to file @samp{filename}. @kindex C-c C-v t @subsubheading Functions + @table @code @item org-babel-tangle Tangle the current file. Bound to @kbd{C-c C-v t}. + +With prefix argument only tangle the current code block. @item org-babel-tangle-file Choose a file to tangle. Bound to @kbd{C-c C-v f}. @end table @subsubheading Hooks + @table @code @item org-babel-post-tangle-hook This hook is run from within code files tangled by @code{org-babel-tangle}. @@ -12917,6 +13832,21 @@ Example applications could include post-processing, compilation or evaluation of tangled code files. @end table +@subsubheading Jumping between code and Org + +When tangling code from an Org-mode buffer to a source code file, you'll +frequently find yourself viewing the file of tangled source code (e.g., many +debuggers point to lines of the source code file). It is useful to be able +to navigate from the tangled source to the Org-mode buffer from which the +code originated. + +The @code{org-babel-tangle-jump-to-org} function provides this jumping from +code to Org-mode functionality. Two header arguments are required for +jumping to work, first the @code{padline} (@ref{padline}) option must be set +to true (the default setting), second the @code{comments} (@ref{comments}) +header argument must be set to @code{links}, which will insert comments into +the source code buffer which point back to the original Org-mode file. + @node Evaluating code blocks, Library of Babel, Extracting source code, Working With Source Code @section Evaluating code blocks @cindex code block, evaluating @@ -12943,7 +13873,7 @@ used to define a code block). @kindex C-c C-c There are a number of ways to evaluate code blocks. The simplest is to press @kbd{C-c C-c} or @kbd{C-c C-v e} with the point on a code block@footnote{The -@code{org-babel-no-eval-on-ctrl-c-ctrl-c} variable can be used to remove code +option @code{org-babel-no-eval-on-ctrl-c-ctrl-c} can be used to remove code evaluation from the @kbd{C-c C-c} key binding.}. This will call the @code{org-babel-execute-src-block} function to evaluate the block and insert its results into the Org mode buffer. @@ -13054,10 +13984,10 @@ Language-specific documentation is available for some languages. If available, it can be found at @uref{http://orgmode.org/worg/org-contrib/babel/languages.html}. -The @code{org-babel-load-languages} controls which languages are enabled for -evaluation (by default only @code{emacs-lisp} is enabled). This variable can -be set using the customization interface or by adding code like the following -to your emacs configuration. +The option @code{org-babel-load-languages} controls which languages are +enabled for evaluation (by default only @code{emacs-lisp} is enabled). This +variable can be set using the customization interface or by adding code like +the following to your emacs configuration. @quotation The following disables @code{emacs-lisp} evaluation and enables evaluation of @@ -13099,13 +14029,16 @@ describes each header argument in detail. @node Using header arguments, Specific header arguments, Header arguments, Header arguments @subsection Using header arguments -The values of header arguments can be set in six different ways, each more -specific (and having higher priority) than the last. +The values of header arguments can be set in several way. When the header +arguments in each layer have been determined, they are combined in order from +the first, least specific (having the lowest priority) up to the last, most +specific (having the highest priority). A header argument with a higher +priority replaces the same header argument specified at lower priority. @menu * System-wide header arguments:: Set global default values * Language-specific header arguments:: Set default values by language -* Buffer-wide header arguments:: Set default values for a specific buffer * Header arguments in Org mode properties:: Set default values for a buffer or heading +* Language-specific header arguments in Org mode properties:: Set language-specific default values for a buffer or heading * Code block specific header arguments:: The most common way to set values * Header arguments in function calls:: The most specific level @end menu @@ -13114,7 +14047,7 @@ specific (and having higher priority) than the last. @node System-wide header arguments, Language-specific header arguments, Using header arguments, Using header arguments @subsubheading System-wide header arguments @vindex org-babel-default-header-args -System-wide values of header arguments can be specified by customizing the +System-wide values of header arguments can be specified by adapting the @code{org-babel-default-header-args} variable: @example @@ -13125,20 +14058,6 @@ System-wide values of header arguments can be specified by customizing the :noweb => "no" @end example -@c @example -@c org-babel-default-header-args is a variable defined in `org-babel.el'. -@c Its value is -@c ((:session . "none") -@c (:results . "replace") -@c (:exports . "code") -@c (:cache . "no") -@c (:noweb . "no")) - - -@c Documentation: -@c Default arguments to use when evaluating a code block. -@c @end example - For example, the following example could be used to set the default value of @code{:noweb} header arguments to @code{yes}. This would have the effect of expanding @code{:noweb} references by default when evaluating source code @@ -13147,64 +14066,88 @@ blocks. @lisp (setq org-babel-default-header-args (cons '(:noweb . "yes") - (assq-delete-all :noweb org-babel-default-header-args))) + (assq-delete-all :noweb org-babel-default-header-args))) @end lisp -@node Language-specific header arguments, Buffer-wide header arguments, System-wide header arguments, Using header arguments +@node Language-specific header arguments, Header arguments in Org mode properties, System-wide header arguments, Using header arguments @subsubheading Language-specific header arguments -Each language can define its own set of default header arguments. See the -language-specific documentation available online at +Each language can define its own set of default header arguments in variable +@code{org-babel-default-header-args:}, where @code{} is the name +of the language. See the language-specific documentation available online at @uref{http://orgmode.org/worg/org-contrib/babel}. -@node Buffer-wide header arguments, Header arguments in Org mode properties, Language-specific header arguments, Using header arguments -@subsubheading Buffer-wide header arguments +@node Header arguments in Org mode properties, Language-specific header arguments in Org mode properties, Language-specific header arguments, Using header arguments +@subsubheading Header arguments in Org mode properties + Buffer-wide header arguments may be specified as properties through the use of @code{#+PROPERTY:} lines placed anywhere in an Org mode file (see @ref{Property syntax}). -For example the following would set @code{session} to @code{*R*}, and -@code{results} to @code{silent} for every code block in the buffer, ensuring -that all execution took place in the same session, and no results would be -inserted into the buffer. +For example the following would set @code{session} to @code{*R*} (only for R +code blocks), and @code{results} to @code{silent} for every code block in the +buffer, ensuring that all execution took place in the same session, and no +results would be inserted into the buffer. @example -#+PROPERTY: session *R* -#+PROPERTY: results silent -@end example - -@node Header arguments in Org mode properties, Code block specific header arguments, Buffer-wide header arguments, Using header arguments -@subsubheading Header arguments in Org mode properties - -Header arguments are also read from Org mode properties (see @ref{Property -syntax}), which can be set on a buffer-wide or per-heading basis. An example -of setting a header argument for all code blocks in a buffer is - -@example -#+PROPERTY: tangle yes +#+PROPERTY: header-args:R :session *R* +#+PROPERTY: header-args :results silent @end example +Header arguments read from Org mode properties can also be set on a +per-subtree basis using property drawers (see @ref{Property syntax}). @vindex org-use-property-inheritance -When properties are used to set default header arguments, they are looked up -with inheritance, regardless of the value of -@code{org-use-property-inheritance}. In the following example the value of +When properties are used to set default header arguments, they are always +looked up with inheritance, regardless of the value of +@code{org-use-property-inheritance}. Properties are evaluated as seen by the +outermost call or source block.@footnote{The deprecated syntax for default +header argument properties, using the name of the header argument as a +property name directly, evaluates the property as seen by the corresponding +source block definition. This behaviour has been kept for backwards +compatibility.} + +In the following example the value of the @code{:cache} header argument will default to @code{yes} in all code blocks in the subtree rooted at the following heading: @example * outline header :PROPERTIES: - :cache: yes + :header-args: :cache yes :END: @end example @kindex C-c C-x p @vindex org-babel-default-header-args Properties defined in this way override the properties set in -@code{org-babel-default-header-args}. It is convenient to use the -@code{org-set-property} function bound to @kbd{C-c C-x p} to set properties -in Org mode documents. +@code{org-babel-default-header-args} and are applied for all activated +languages. It is convenient to use the @code{org-set-property} function +bound to @kbd{C-c C-x p} to set properties in Org mode documents. + +@node Language-specific header arguments in Org mode properties, Code block specific header arguments, Header arguments in Org mode properties, Using header arguments +@subsubheading Language-specific header arguments in Org mode properties + +Language-specific header arguments are also read from properties +@code{header-args:} where @code{} is the name of the language +targeted. As an example + +@example +* Heading + :PROPERTIES: + :header-args:clojure: :session *clojure-1* + :header-args:R: :session *R* + :END: +** Subheading + :PROPERTIES: + :header-args:clojure: :session *clojure-2* + :END: +@end example + +would independently set a default session header argument for R and clojure +for calls and source blocks under subtree ``Heading'' and change to a +different clojure setting for evaluations under subtree ``Subheading'', while +the R session is inherited from ``Heading'' and therefore unchanged. -@node Code block specific header arguments, Header arguments in function calls, Header arguments in Org mode properties, Using header arguments +@node Code block specific header arguments, Header arguments in function calls, Language-specific header arguments in Org mode properties, Using header arguments @subsubheading Code block specific header arguments The most common way to assign values to header arguments is at the @@ -13318,8 +14261,12 @@ argument in lowercase letters. The following header arguments are defined: * colnames:: Handle column names in tables * rownames:: Handle row names in tables * shebang:: Make tangled files executable +* tangle-mode:: Set permission of tangled files * eval:: Limit evaluation of specific code blocks * wrap:: Mark source block evaluation results +* post:: Post processing of code block results +* prologue:: Text to prepend to code block body +* epilogue:: Text to append to code block body @end menu Additional header arguments are defined on a language-specific basis, see @@ -13334,11 +14281,13 @@ syntax used to specify arguments is the same across all languages. In every case, variables require a default value when they are declared. The values passed to arguments can either be literal values, references, or -Emacs Lisp code (see @ref{var, Emacs Lisp evaluation of variables}). References -include anything in the Org mode file that takes a @code{#+NAME:}, -@code{#+TBLNAME:}, or @code{#+RESULTS:} line. This includes tables, lists, -@code{#+BEGIN_EXAMPLE} blocks, other code blocks, and the results of other -code blocks. +Emacs Lisp code (see @ref{var, Emacs Lisp evaluation of variables}). +References include anything in the Org mode file that takes a @code{#+NAME:} +or @code{#+RESULTS:} line: tables, lists, @code{#+BEGIN_EXAMPLE} blocks, +other code blocks and the results of other code blocks. + +Note: When a reference is made to another code block, the referenced block +will be evaluated unless it has current cached results (see @ref{cache}). Argument values can be indexed in a manner similar to arrays (see @ref{var, Indexable variable values}). @@ -13360,10 +14309,10 @@ Here are examples of passing values by reference: @table @dfn @item table -an Org mode table named with either a @code{#+NAME:} or @code{#+TBLNAME:} line +an Org mode table named with either a @code{#+NAME:} line @example -#+TBLNAME: example-table +#+NAME: example-table | 1 | | 2 | | 3 | @@ -13456,19 +14405,6 @@ on two lines @end table -@subsubheading Alternate argument syntax -It is also possible to specify arguments in a potentially more natural way -using the @code{#+NAME:} line of a code block. As in the following -example, arguments can be packed inside of parentheses, separated by commas, -following the source name. - -@example -#+NAME: double(input=0, x=2) -#+BEGIN_SRC emacs-lisp -(* 2 (+ input x)) -#+END_SRC -@end example - @subsubheading Indexable variable values It is possible to reference portions of variable values by ``indexing'' into the variables. Indexes are 0 based with negative values counting back from @@ -13593,7 +14529,7 @@ Emacs Lisp, as shown in the following example. @node results, file, var, Specific header arguments @subsubsection @code{:results} -There are three classes of @code{:results} header argument. Only one option +There are four classes of @code{:results} header argument. Only one option per class may be supplied per code block. @itemize @bullet @@ -13602,6 +14538,10 @@ per class may be supplied per code block. from the code block @item @b{type} header arguments specify what type of result the code block will +return---which has implications for how they will be processed before +insertion into the Org mode buffer +@item +@b{format} header arguments specify what type of result the code block will return---which has implications for how they will be inserted into the Org mode buffer @item @@ -13647,6 +14587,15 @@ buffer as quoted text. E.g., @code{:results value verbatim}. @item @code{file} The results will be interpreted as the path to a file, and will be inserted into the Org mode buffer as a file link. E.g., @code{:results value file}. +@end itemize + +@subsubheading Format + +The following options are mutually exclusive and specify what type of results +the code block will return. By default, results are inserted according to the +type as specified above. + +@itemize @bullet @item @code{raw} The results are interpreted as raw Org mode code and are inserted directly into the buffer. If the results look like a table they will be aligned as @@ -13728,7 +14677,7 @@ While the @code{:file} header argument can be used to specify the path to the output file, @code{:dir} specifies the default directory during code block execution. If it is absent, then the directory associated with the current buffer is used. In other words, supplying @code{:dir path} temporarily has -the same effect as changing the current directory with @kbd{M-x cd path}, and +the same effect as changing the current directory with @kbd{M-x cd path RET}, and then not supplying @code{:dir}. Under the surface, @code{:dir} simply sets the value of the Emacs variable @code{default-directory}. @@ -13853,7 +14802,6 @@ original Org file from which the code was tangled. A synonym for ``link'' to maintain backwards compatibility. @item @code{org} Include text from the Org mode file as a comment. - The text is picked from the leading context of the tangled code and is limited by the nearest headline or source block as the case may be. @item @code{both} @@ -13925,7 +14873,7 @@ references will not be expanded when the code block is exported. @item @code{strip-export} ``Noweb'' syntax references in the body of the code block will be expanded before the block is evaluated or tangled. However, ``noweb'' syntax -references will not be removed when the code block is exported. +references will be removed when the code block is exported. @item @code{eval} ``Noweb'' syntax references in the body of the code block will only be expanded before the block is evaluated. @@ -14085,7 +15033,7 @@ variable and raises an error. Setting @code{:hlines no} or relying on the default value yields the following results. @example -#+TBLNAME: many-cols +#+NAME: many-cols | a | b | c | |---+---+---| | d | e | f | @@ -14107,7 +15055,7 @@ default value yields the following results. Leaves hlines in the table. Setting @code{:hlines yes} has this effect. @example -#+TBLNAME: many-cols +#+NAME: many-cols | a | b | c | |---+---+---| | d | e | f | @@ -14134,9 +15082,7 @@ Leaves hlines in the table. Setting @code{:hlines yes} has this effect. The @code{:colnames} header argument accepts the values @code{yes}, @code{no}, or @code{nil} for unassigned. The default value is @code{nil}. Note that the behavior of the @code{:colnames} header argument may differ -across languages. For example Emacs Lisp code blocks ignore the -@code{:colnames} header argument entirely given the ease with which tables -with column names may be handled directly in Emacs Lisp. +across languages. @itemize @bullet @item @code{nil} @@ -14146,7 +15092,7 @@ names will be removed from the table before processing, then reapplied to the results. @example -#+TBLNAME: less-cols +#+NAME: less-cols | a | |---| | b | @@ -14179,8 +15125,10 @@ hline) @node rownames, shebang, colnames, Specific header arguments @subsubsection @code{:rownames} -The @code{:rownames} header argument can take on the values @code{yes} -or @code{no}, with a default value of @code{no}. +The @code{:rownames} header argument can take on the values @code{yes} or +@code{no}, with a default value of @code{no}. Note that Emacs Lisp code +blocks ignore the @code{:rownames} header argument entirely given the ease +with which tables with row names may be handled directly in Emacs Lisp. @itemize @bullet @item @code{no} @@ -14191,7 +15139,7 @@ The first column of the table is removed from the table before processing, and is then reapplied to the results. @example -#+TBLNAME: with-rownames +#+NAME: with-rownames | one | 1 | 2 | 3 | 4 | 5 | | two | 6 | 7 | 8 | 9 | 10 | @@ -14210,7 +15158,7 @@ variable indexing @xref{var, Indexable variable values}. @end itemize -@node shebang, eval, rownames, Specific header arguments +@node shebang, tangle-mode, rownames, Specific header arguments @subsubsection @code{:shebang} Setting the @code{:shebang} header argument to a string value @@ -14218,7 +15166,21 @@ Setting the @code{:shebang} header argument to a string value first line of any tangled file holding the code block, and the file permissions of the tangled file are set to make it executable. -@node eval, wrap, shebang, Specific header arguments + +@node tangle-mode, eval, shebang, Specific header arguments +@subsubsection @code{:tangle-mode} + +The @code{tangle-mode} header argument controls the permission set on tangled +files. The value of this header argument will be passed to +@code{set-file-modes}. For example, to set a tangled file as read only use +@code{:tangle-mode (identity #o444)}, or to set a tangled file as executable +use @code{:tangle-mode (identity #o755)}. Blocks with @code{shebang} +(@ref{shebang}) header arguments will automatically be made executable unless +the @code{tangle-mode} header argument is also used. The behavior is +undefined if multiple code blocks with different values for the +@code{tangle-mode} header argument are tangled to the same file. + +@node eval, wrap, tangle-mode, Specific header arguments @subsubsection @code{:eval} The @code{:eval} header argument can be used to limit the evaluation of specific code blocks. The @code{:eval} header argument can be useful for @@ -14243,7 +15205,7 @@ If this header argument is not set then evaluation is determined by the value of the @code{org-confirm-babel-evaluate} variable see @ref{Code evaluation security}. -@node wrap, , eval, Specific header arguments +@node wrap, post, eval, Specific header arguments @subsubsection @code{:wrap} The @code{:wrap} header argument is used to mark the results of source block evaluation. The header argument can be passed a string that will be appended @@ -14251,6 +15213,59 @@ to @code{#+BEGIN_} and @code{#+END_}, which will then be used to wrap the results. If not string is specified then the results will be wrapped in a @code{#+BEGIN/END_RESULTS} block. +@node post, prologue, wrap, Specific header arguments +@subsubsection @code{:post} +The @code{:post} header argument is used to post-process the results of a +code block execution. When a post argument is given, the results of the code +block will temporarily be bound to the @code{*this*} variable. This variable +may then be included in header argument forms such as those used in @ref{var} +header argument specifications allowing passing of results to other code +blocks, or direct execution via Emacs Lisp. + +The following example illustrates the usage of the @code{:post} header +argument. + +@example +#+name: attr_wrap +#+begin_src sh :var data="" :var width="\\textwidth" :results output + echo "#+ATTR_LATEX :width $width" + echo "$data" +#+end_src + +#+header: :file /tmp/it.png +#+begin_src dot :post attr_wrap(width="5cm", data=*this*) :results drawer + digraph@{ + a -> b; + b -> c; + c -> a; + @} +#+end_src + +#+RESULTS: +:RESULTS: +#+ATTR_LATEX :width 5cm +[[file:/tmp/it.png]] +:END: +@end example + +@node prologue, epilogue, post, Specific header arguments +@subsubsection @code{:prologue} +The value of the @code{prologue} header argument will be prepended to the +code block body before execution. For example, @code{:prologue "reset"} may +be used to reset a gnuplot session before execution of a particular code +block, or the following configuration may be used to do this for all gnuplot +code blocks. Also see @ref{epilogue}. + +@lisp +(add-to-list 'org-babel-default-header-args:gnuplot + '((:prologue . "reset"))) +@end lisp + +@node epilogue, , prologue, Specific header arguments +@subsubsection @code{:epilogue} +The value of the @code{epilogue} header argument will be appended to the code +block body before execution. Also see @ref{prologue}. + @node Results of evaluation, Noweb reference syntax, Header arguments, Working With Source Code @section Results of evaluation @cindex code block, results of evaluation @@ -14380,7 +15395,7 @@ syntactically valid in languages that you use, then please consider setting the default value. Note: if noweb tangling is slow in large Org mode files consider setting the -@code{*org-babel-use-quick-and-dirty-noweb-expansion*} variable to true. +@code{org-babel-use-quick-and-dirty-noweb-expansion} variable to @code{t}. This will result in faster noweb reference resolution at the expense of not correctly resolving inherited values of the @code{:noweb-ref} header argument. @@ -14540,7 +15555,7 @@ emacs -Q --batch \ * Clean view:: Getting rid of leading stars in the outline * TTY keys:: Using Org on a tty * Interaction:: Other Emacs packages -* org-crypt.el:: Encrypting Org files +* org-crypt:: Encrypting Org files @end menu @@ -14694,19 +15709,19 @@ which take off the default security brakes. @defopt org-confirm-babel-evaluate When t (the default), the user is asked before every code block evaluation. -When nil, the user is not asked. When set to a function, it is called with +When @code{nil}, the user is not asked. When set to a function, it is called with two arguments (language and body of the code block) and should return t to -ask and nil not to ask. +ask and @code{nil} not to ask. @end defopt For example, here is how to execute "ditaa" code (which is considered safe) without asking: -@example +@lisp (defun my-org-confirm-babel-evaluate (lang body) (not (string= lang "ditaa"))) ; don't ask for ditaa (setq org-confirm-babel-evaluate 'my-org-confirm-babel-evaluate) -@end example +@end lisp @item Following @code{shell} and @code{elisp} links Org has two link types that can directly evaluate code (@pxref{External @@ -14734,7 +15749,7 @@ either by the @i{calc} interpreter, or by the @i{Emacs Lisp} interpreter. There are more than 500 variables that can be used to customize Org. For the sake of compactness of the manual, I am not describing the variables here. A structured overview of customization -variables is available with @kbd{M-x org-customize}. Or select +variables is available with @kbd{M-x org-customize RET}. Or select @code{Browse Org Group} from the @code{Org->Customization} menu. Many settings can also be activated on a per-file basis, by putting special lines into the buffer (@pxref{In-buffer settings}). @@ -14809,7 +15824,7 @@ as if they had been included in the buffer. In particular, the file can be any other Org mode file with internal setup. You can visit the file the cursor is in the line with @kbd{C-c '}. @item #+STARTUP: -@cindex #+STARTUP: +@cindex #+STARTUP This line sets options to be used at startup of Org mode, when an Org file is being visited. @@ -14862,6 +15877,18 @@ inlineimages @r{show inline images} noinlineimages @r{don't show inline images on startup} @end example +@vindex org-startup-with-latex-preview +When visiting a file, @LaTeX{} fragments can be converted to images +automatically. The variable @code{org-startup-with-latex-preview} which +controls this behavior, is set to @code{nil} by default to avoid delays on +startup. +@cindex @code{latexpreview}, STARTUP keyword +@cindex @code{nolatexpreview}, STARTUP keyword +@example +latexpreview @r{preview @LaTeX{} fragments} +nolatexpreview @r{don't preview @LaTeX{} fragments} +@end example + @vindex org-log-done @vindex org-log-note-clock-out @vindex org-log-repeat @@ -14885,25 +15912,34 @@ configured using these options (see variables @code{org-log-done}, @cindex @code{logrefile}, STARTUP keyword @cindex @code{lognoterefile}, STARTUP keyword @cindex @code{nologrefile}, STARTUP keyword -@example -logdone @r{record a timestamp when an item is marked DONE} -lognotedone @r{record timestamp and a note when DONE} -nologdone @r{don't record when items are marked DONE} -logrepeat @r{record a time when reinstating a repeating item} -lognoterepeat @r{record a note when reinstating a repeating item} -nologrepeat @r{do not record when reinstating repeating item} -lognoteclock-out @r{record a note when clocking out} -nolognoteclock-out @r{don't record a note when clocking out} -logreschedule @r{record a timestamp when scheduling time changes} -lognotereschedule @r{record a note when scheduling time changes} -nologreschedule @r{do not record when a scheduling date changes} -logredeadline @r{record a timestamp when deadline changes} -lognoteredeadline @r{record a note when deadline changes} -nologredeadline @r{do not record when a deadline date changes} -logrefile @r{record a timestamp when refiling} -lognoterefile @r{record a note when refiling} -nologrefile @r{do not record when refiling} +@cindex @code{logdrawer}, STARTUP keyword +@cindex @code{nologdrawer}, STARTUP keyword +@cindex @code{logstatesreversed}, STARTUP keyword +@cindex @code{nologstatesreversed}, STARTUP keyword +@example +logdone @r{record a timestamp when an item is marked DONE} +lognotedone @r{record timestamp and a note when DONE} +nologdone @r{don't record when items are marked DONE} +logrepeat @r{record a time when reinstating a repeating item} +lognoterepeat @r{record a note when reinstating a repeating item} +nologrepeat @r{do not record when reinstating repeating item} +lognoteclock-out @r{record a note when clocking out} +nolognoteclock-out @r{don't record a note when clocking out} +logreschedule @r{record a timestamp when scheduling time changes} +lognotereschedule @r{record a note when scheduling time changes} +nologreschedule @r{do not record when a scheduling date changes} +logredeadline @r{record a timestamp when deadline changes} +lognoteredeadline @r{record a note when deadline changes} +nologredeadline @r{do not record when a deadline date changes} +logrefile @r{record a timestamp when refiling} +lognoterefile @r{record a note when refiling} +nologrefile @r{do not record when refiling} +logdrawer @r{store log into drawer} +nologdrawer @r{store log outside of drawer} +logstatesreversed @r{reverse the order of states notes} +nologstatesreversed @r{do not reverse the order of states notes} @end example + @vindex org-hide-leading-stars @vindex org-odd-levels-only Here are the options for hiding leading stars in outline headings, and for @@ -14922,6 +15958,7 @@ noindent @r{no virtual indentation according to outline level} odd @r{allow only odd outline levels (1,3,...)} oddeven @r{allow all outline levels} @end example + @vindex org-put-time-stamp-overlays @vindex org-time-stamp-overlay-formats To turn on custom format overlays over timestamps (variables @@ -14931,6 +15968,7 @@ To turn on custom format overlays over timestamps (variables @example customtime @r{overlay custom time format} @end example + @vindex constants-unit-system The following options influence the table spreadsheet (variable @code{constants-unit-system}). @@ -14940,6 +15978,7 @@ The following options influence the table spreadsheet (variable constcgs @r{@file{constants.el} should use the c-g-s unit system} constSI @r{@file{constants.el} should use the SI unit system} @end example + @vindex org-footnote-define-inline @vindex org-footnote-auto-label @vindex org-footnote-auto-adjust @@ -14966,6 +16005,7 @@ fnplain @r{create @code{[1]}-like labels automatically} fnadjust @r{automatically renumber and sort footnotes} nofnadjust @r{do not renumber and sort automatically} @end example + @cindex org-hide-block-startup To hide blocks on startup, use these keywords. The corresponding variable is @code{org-hide-block-startup}. @@ -14975,6 +16015,7 @@ To hide blocks on startup, use these keywords. The corresponding variable is hideblocks @r{Hide all begin/end blocks on startup} nohideblocks @r{Do not hide blocks on startup} @end example + @cindex org-pretty-entities The display of entities as UTF-8 characters is governed by the variable @code{org-pretty-entities} and the keywords @@ -14984,20 +16025,29 @@ The display of entities as UTF-8 characters is governed by the variable entitiespretty @r{Show entities as UTF-8 characters where possible} entitiesplain @r{Leave entities plain} @end example + @item #+TAGS: TAG1(c1) TAG2(c2) @vindex org-tag-alist These lines (several such lines are allowed) specify the valid tags in this file, and (potentially) the corresponding @emph{fast tag selection} keys. The corresponding variable is @code{org-tag-alist}. +@cindex #+TBLFM @item #+TBLFM: This line contains the formulas for the table directly above the line. -@item #+TITLE:, #+AUTHOR:, #+EMAIL:, #+LANGUAGE:, #+TEXT:, #+DATE:, -@itemx #+OPTIONS:, #+BIND:, #+XSLT:, + +Table can have multiple lines containing @samp{#+TBLFM:}. Note +that only the first line of @samp{#+TBLFM:} will be applied when +you recalculate the table. For more details see @ref{Using +multiple #+TBLFM lines} in @ref{Editing and debugging formulas}. + +@item #+TITLE:, #+AUTHOR:, #+EMAIL:, #+LANGUAGE:, #+DATE:, +@itemx #+OPTIONS:, #+BIND:, @itemx #+DESCRIPTION:, #+KEYWORDS:, -@itemx #+LaTeX_HEADER:, #+STYLE:, #+LINK_UP:, #+LINK_HOME:, -@itemx #+EXPORT_SELECT_TAGS:, #+EXPORT_EXCLUDE_TAGS: +@itemx #+LaTeX_HEADER:, #+LaTeX_HEADER_EXTRA:, +@itemx #+HTML_HEAD:, #+HTML_HEAD_EXTRA:, #+HTML_LINK_UP:, #+HTML_LINK_HOME:, +@itemx #+SELECT_TAGS:, #+EXCLUDE_TAGS: These lines provide settings for exporting files. For more details see -@ref{Export options}. +@ref{Export settings}. @item #+TODO: #+SEQ_TODO: #+TYP_TODO: @vindex org-todo-keywords These lines set the TODO keywords and their interpretation in the @@ -15042,7 +16092,7 @@ If the cursor is in a property line or at the start or end of a property drawer, offer property commands. @item If the cursor is at a footnote reference, go to the corresponding -definition, and vice versa. +definition, and @emph{vice versa}. @item If the cursor is on a statistics cookie, update it. @item @@ -15221,7 +16271,7 @@ tty you would rather use @kbd{C-c .} to re-insert the timestamp. @end multitable -@node Interaction, org-crypt.el, TTY keys, Miscellaneous +@node Interaction, org-crypt, TTY keys, Miscellaneous @section Interaction with other packages @cindex packages, interaction with other Org lives in the world of GNU Emacs and interacts in various ways @@ -15367,6 +16417,18 @@ Yes, these are unfortunately more difficult to remember. If you want to have other replacement keys, look at the variable @code{org-disputed-keys}. +@item @file{ecomplete.el} by Lars Magne Ingebrigtsen @email{larsi@@gnus.org} +@cindex @file{ecomplete.el} + +Ecomplete provides ``electric'' address completion in address header +lines in message buffers. Sadly Orgtbl mode cuts ecompletes power +supply: No completion happens when Orgtbl mode is enabled in message +buffers while entering text in address header lines. If one wants to +use ecomplete one should @emph{not} follow the advice to automagically +turn on Orgtbl mode in message buffers (see @ref{Orgtbl mode}), but +instead---after filling in the message headers---turn on Orgtbl mode +manually when needed in the messages body. + @item @file{filladapt.el} by Kyle Jones @cindex @file{filladapt.el} @@ -15381,7 +16443,7 @@ this: @item @file{yasnippet.el} @cindex @file{yasnippet.el} -The way Org mode binds the TAB key (binding to @code{[tab]} instead of +The way Org mode binds the @key{TAB} key (binding to @code{[tab]} instead of @code{"\t"}) overrules YASnippet's access to this key. The following code fixed this problem: @@ -15406,10 +16468,10 @@ Then, tell Org mode what to do with the new function: @lisp (add-hook 'org-mode-hook (lambda () - (make-variable-buffer-local 'yas/trigger-key) - (setq yas/trigger-key [tab]) - (add-to-list 'org-tab-first-hook 'yas/org-very-safe-expand) - (define-key yas/keymap [tab] 'yas/next-field))) + (make-variable-buffer-local 'yas/trigger-key) + (setq yas/trigger-key [tab]) + (add-to-list 'org-tab-first-hook 'yas/org-very-safe-expand) + (define-key yas/keymap [tab] 'yas/next-field))) @end lisp @item @file{windmove.el} by Hovav Shacham @@ -15440,9 +16502,11 @@ another key for this command, or override the key in (define-key viper-vi-global-user-map "C-c /" 'org-sparse-tree) @end lisp + + @end table -@node org-crypt.el, , Interaction, Miscellaneous +@node org-crypt, , Interaction, Miscellaneous @section org-crypt.el @cindex @file{org-crypt.el} @cindex @code{org-decrypt-entry} @@ -15458,7 +16522,7 @@ customize the @code{org-crypt-tag-matcher} setting. To use org-crypt it is suggested that you have the following in your @file{.emacs}: -@example +@lisp (require 'org-crypt) (org-crypt-use-before-save-magic) (setq org-tags-exclude-from-inheritance (quote ("crypt"))) @@ -15476,7 +16540,7 @@ To use org-crypt it is suggested that you have the following in your ;; To turn it off only locally, you can insert this: ;; ;; # -*- buffer-auto-save-file-name: nil; -*- -@end example +@end lisp Excluding the crypt tag from inheritance prevents already encrypted text being encrypted again. @@ -15492,11 +16556,13 @@ Org. * Hooks:: How to reach into Org's internals * Add-on packages:: Available extensions * Adding hyperlink types:: New custom link types +* Adding export back-ends:: How to write new export back-ends * Context-sensitive commands:: How to add functionality to such commands * Tables in arbitrary syntax:: Orgtbl for @LaTeX{} and other programs * Dynamic blocks:: Automatically filled blocks * Special agenda views:: Customized views -* Extracting agenda information:: Postprocessing of agenda information +* Speeding up your agendas:: Tips on how to speed up your agendas +* Extracting agenda information:: Post-processing of agenda information * Using the property API:: Writing programs that use entry properties * Using the mapping API:: Mapping over all or selected entries @end menu @@ -15516,15 +16582,14 @@ maintained by the Worg project and can be found at @cindex add-on packages A large number of add-on packages have been written by various authors. + These packages are not part of Emacs, but they are distributed as contributed -packages with the separate release available at the Org mode home page at -@uref{http://orgmode.org}. The list of contributed packages, along with -documentation about each package, is maintained by the Worg project at +packages with the separate release available at @uref{http://orgmode.org}. +See the @file{contrib/README} file in the source code directory for a list of +contributed files. You may also find some more information on the Worg page: @uref{http://orgmode.org/worg/org-contrib/}. - - -@node Adding hyperlink types, Context-sensitive commands, Add-on packages, Hacking +@node Adding hyperlink types, Adding export back-ends, Add-on packages, Hacking @section Adding hyperlink types @cindex hyperlinks, adding new types @@ -15627,7 +16692,37 @@ When it makes sense for your new link type, you may also define a function support for inserting such a link with @kbd{C-c C-l}. Such a function should not accept any arguments, and return the full link with prefix. -@node Context-sensitive commands, Tables in arbitrary syntax, Adding hyperlink types, Hacking +@node Adding export back-ends, Context-sensitive commands, Adding hyperlink types, Hacking +@section Adding export back-ends +@cindex Export, writing back-ends + +Org 8.0 comes with a completely rewritten export engine which makes it easy +to write new export back-ends, either from scratch, or from deriving them +from existing ones. + +Your two entry points are respectively @code{org-export-define-backend} and +@code{org-export-define-derived-backend}. To grok these functions, you +should first have a look at @file{ox-latex.el} (for how to define a new +back-end from scratch) and @file{ox-beamer.el} (for how to derive a new +back-end from an existing one. + +When creating a new back-end from scratch, the basic idea is to set the name +of the back-end (as a symbol) and an an alist of elements and export +functions. On top of this, you will need to set additional keywords like +@code{:menu-entry} (to display the back-end in the export dispatcher), +@code{:export-block} (to specify what blocks should not be exported by this +back-end), and @code{:options-alist} (to let the user set export options that +are specific to this back-end.) + +Deriving a new back-end is similar, except that you need to set +@code{:translate-alist} to an alist of export functions that should be used +instead of the parent back-end functions. + +For a complete reference documentation, see +@url{http://orgmode.org/worg/dev/org-export-reference.html, the Org Export +Reference on Worg}. + +@node Context-sensitive commands, Tables in arbitrary syntax, Adding export back-ends, Hacking @section Context-sensitive commands @cindex context-sensitive commands, hooks @cindex add-ons, context-sensitive commands @@ -15696,7 +16791,7 @@ can use Org's facilities to edit and structure lists by turning * Radio tables:: Sending and receiving radio tables * A @LaTeX{} example:: Step by step, almost a tutorial * Translator functions:: Copy and modify -* Radio lists:: Doing the same for lists +* Radio lists:: Sending and receiving lists @end menu @node Radio tables, A @LaTeX{} example, Tables in arbitrary syntax, Tables in arbitrary syntax @@ -15704,9 +16799,10 @@ can use Org's facilities to edit and structure lists by turning @cindex radio tables To define the location of the target table, you first need to create two -lines that are comments in the current mode, but contain magic words for -Orgtbl mode to find. Orgtbl mode will insert the translated table -between these lines, replacing whatever was there before. For example: +lines that are comments in the current mode, but contain magic words +@code{BEGIN/END RECEIVE ORGTBL} for Orgtbl mode to find. Orgtbl mode will +insert the translated table between these lines, replacing whatever was there +before. For example in C mode where comments are between @code{/* ... */}: @example /* BEGIN RECEIVE ORGTBL table_name */ @@ -15744,8 +16840,8 @@ removal of these columns, the function never knows that there have been additional columns. @item :no-escape t -When non-nil, do not escape special characters @code{&%#_^} when exporting -the table. The default value is nil. +When non-@code{nil}, do not escape special characters @code{&%#_^} when exporting +the table. The default value is @code{nil}. @end table @noindent @@ -15766,7 +16862,7 @@ in @LaTeX{}. @item You can just comment the table line-by-line whenever you want to process the file, and uncomment it whenever you need to edit the table. This -only sounds tedious---the command @kbd{M-x orgtbl-toggle-comment} +only sounds tedious---the command @kbd{M-x orgtbl-toggle-comment RET} makes this comment-toggling very easy, in particular if you bind it to a key. @end itemize @@ -15780,8 +16876,8 @@ The best way to wrap the source table in @LaTeX{} is to use the activated by placing @code{\usepackage@{comment@}} into the document header. Orgtbl mode can insert a radio table skeleton@footnote{By default this works only for @LaTeX{}, HTML, and Texinfo. Configure the -variable @code{orgtbl-radio-tables} to install templates for other -modes.} with the command @kbd{M-x orgtbl-insert-radio-table}. You will +variable @code{orgtbl-radio-table-templates} to install templates for other +modes.} with the command @kbd{M-x orgtbl-insert-radio-table RET}. You will be prompted for a table name, let's say we use @samp{salesfigures}. You will then get the following template: @@ -15860,7 +16956,7 @@ interprets the following parameters (see also @pxref{Translator functions}): @table @code @item :splice nil/t When set to t, return only table body lines, don't wrap them into a -tabular environment. Default is nil. +tabular environment. Default is @code{nil}. @item :fmt fmt A format to be used to wrap each field, it should contain @code{%s} for the @@ -16052,7 +17148,7 @@ The corresponding block writer function could look like this: (defun org-dblock-write:block-update-time (params) (let ((fmt (or (plist-get params :format) "%d. %m. %Y"))) (insert "Last block update at: " - (format-time-string fmt (current-time))))) + (format-time-string fmt (current-time))))) @end lisp If you want to make sure that all dynamic blocks are always up-to-date, @@ -16064,21 +17160,25 @@ written in a way such that it does nothing in buffers that are not in You can narrow the current buffer to the current dynamic block (like any other block) with @code{org-narrow-to-block}. -@node Special agenda views, Extracting agenda information, Dynamic blocks, Hacking +@node Special agenda views, Speeding up your agendas, Dynamic blocks, Hacking @section Special agenda views @cindex agenda views, user-defined @vindex org-agenda-skip-function @vindex org-agenda-skip-function-global Org provides a special hook that can be used to narrow down the selection -made by these agenda views: @code{agenda}, @code{todo}, @code{alltodo}, -@code{tags}, @code{tags-todo}, @code{tags-tree}. You may specify a function -that is used at each match to verify if the match should indeed be part of -the agenda view, and if not, how much should be skipped. You can specify a -global condition that will be applied to all agenda views, this condition -would be stored in the variable @code{org-agenda-skip-function-global}. More -commonly, such a definition is applied only to specific custom searches, -using @code{org-agenda-skip-function}. +made by these agenda views: @code{agenda}, @code{agenda*}@footnote{The +@code{agenda*} view is the same than @code{agenda} except that it only +considers @emph{appointments}, i.e., scheduled and deadline items that have a +time specification @code{[h]h:mm} in their time-stamps.}, @code{todo}, +@code{alltodo}, @code{tags}, @code{tags-todo}, @code{tags-tree}. You may +specify a function that is used at each match to verify if the match should +indeed be part of the agenda view, and if not, how much should be skipped. +You can specify a global condition that will be applied to all agenda views, +this condition would be stored in the variable +@code{org-agenda-skip-function-global}. More commonly, such a definition is +applied only to specific custom searches, using +@code{org-agenda-skip-function}. Let's say you want to produce a list of projects that contain a WAITING tag anywhere in the project tree. Let's further assume that you have @@ -16165,7 +17265,48 @@ like this, even without defining a special function: (org-agenda-overriding-header "Projects waiting for something: ")))) @end lisp -@node Extracting agenda information, Using the property API, Special agenda views, Hacking +@node Speeding up your agendas, Extracting agenda information, Special agenda views, Hacking +@section Speeding up your agendas +@cindex agenda views, optimization + +When your Org files grow in both number and size, agenda commands may start +to become slow. Below are some tips on how to speed up the agenda commands. + +@enumerate +@item +Reduce the number of Org agenda files: this will reduce the slowliness caused +by accessing to a hard drive. +@item +Reduce the number of DONE and archived headlines: this way the agenda does +not need to skip them. +@item +@vindex org-agenda-dim-blocked-tasks +Inhibit the dimming of blocked tasks: +@lisp +(setq org-agenda-dim-blocked-tasks nil) +@end lisp +@item +@vindex org-startup-folded +@vindex org-agenda-inhibit-startup +Inhibit agenda files startup options: +@lisp +(setq org-agenda-inhibit-startup nil) +@end lisp +@item +@vindex org-agenda-show-inherited-tags +@vindex org-agenda-use-tag-inheritance +Disable tag inheritance in agenda: +@lisp +(setq org-agenda-use-tag-inheritance nil) +@end lisp +@end enumerate + +You can set these options for specific agenda views only. See the docstrings +of these variables for details on why they affect the agenda generation, and +this @uref{http://orgmode.org/worg/agenda-optimization.html, dedicated Worg +page} for further explanations. + +@node Extracting agenda information, Using the property API, Speeding up your agendas, Hacking @section Extracting agenda information @cindex agenda, pipe @cindex Scripts, for agenda processing @@ -16282,27 +17423,27 @@ This includes the TODO keyword, the tags, time strings for deadline, scheduled, and clocking, and any additional properties defined in the entry. The return value is an alist. Keys may occur multiple times if the property key was used several times.@* -POM may also be nil, in which case the current entry is used. -If WHICH is nil or `all', get all properties. If WHICH is +POM may also be @code{nil}, in which case the current entry is used. +If WHICH is @code{nil} or `all', get all properties. If WHICH is `special' or `standard', only get that subclass. @end defun @vindex org-use-property-inheritance @findex org-insert-property-drawer @defun org-entry-get pom property &optional inherit -Get value of PROPERTY for entry at point-or-marker POM@. By default, -this only looks at properties defined locally in the entry. If INHERIT -is non-nil and the entry does not have the property, then also check -higher levels of the hierarchy. If INHERIT is the symbol +Get value of @code{PROPERTY} for entry at point-or-marker @code{POM}@. By default, +this only looks at properties defined locally in the entry. If @code{INHERIT} +is non-@code{nil} and the entry does not have the property, then also check +higher levels of the hierarchy. If @code{INHERIT} is the symbol @code{selective}, use inheritance if and only if the setting of -@code{org-use-property-inheritance} selects PROPERTY for inheritance. +@code{org-use-property-inheritance} selects @code{PROPERTY} for inheritance. @end defun @defun org-entry-delete pom property -Delete the property PROPERTY from entry at point-or-marker POM. +Delete the property @code{PROPERTY} from entry at point-or-marker POM. @end defun @defun org-entry-put pom property value -Set PROPERTY to VALUE for entry at point-or-marker POM. +Set @code{PROPERTY} to @code{VALUE} for entry at point-or-marker POM. @end defun @defun org-buffer-property-keys &optional include-specials @@ -16314,28 +17455,29 @@ Insert a property drawer for the current entry. Also @end defun @defun org-entry-put-multivalued-property pom property &rest values -Set PROPERTY at point-or-marker POM to VALUES@. VALUES should be a list of -strings. They will be concatenated, with spaces as separators. +Set @code{PROPERTY} at point-or-marker @code{POM} to @code{VALUES}@. +@code{VALUES} should be a list of strings. They will be concatenated, with +spaces as separators. @end defun @defun org-entry-get-multivalued-property pom property -Treat the value of the property PROPERTY as a whitespace-separated list of -values and return the values as a list of strings. +Treat the value of the property @code{PROPERTY} as a whitespace-separated +list of values and return the values as a list of strings. @end defun @defun org-entry-add-to-multivalued-property pom property value -Treat the value of the property PROPERTY as a whitespace-separated list of -values and make sure that VALUE is in this list. +Treat the value of the property @code{PROPERTY} as a whitespace-separated +list of values and make sure that @code{VALUE} is in this list. @end defun @defun org-entry-remove-from-multivalued-property pom property value -Treat the value of the property PROPERTY as a whitespace-separated list of -values and make sure that VALUE is @emph{not} in this list. +Treat the value of the property @code{PROPERTY} as a whitespace-separated +list of values and make sure that @code{VALUE} is @emph{not} in this list. @end defun @defun org-entry-member-in-multivalued-property pom property value -Treat the value of the property PROPERTY as a whitespace-separated list of -values and check if VALUE is in this list. +Treat the value of the property @code{PROPERTY} as a whitespace-separated +list of values and check if @code{VALUE} is in this list. @end defun @defopt org-property-allowed-value-functions @@ -16359,30 +17501,29 @@ functions for each or selected entries. The main entry point for this API is: @defun org-map-entries func &optional match scope &rest skip -Call FUNC at each headline selected by MATCH in SCOPE. +Call @code{FUNC} at each headline selected by @code{MATCH} in @code{SCOPE}. -FUNC is a function or a Lisp form. The function will be called without -arguments, with the cursor positioned at the beginning of the headline. -The return values of all calls to the function will be collected and -returned as a list. +@code{FUNC} is a function or a Lisp form. The function will be called +without arguments, with the cursor positioned at the beginning of the +headline. The return values of all calls to the function will be collected +and returned as a list. -The call to FUNC will be wrapped into a save-excursion form, so FUNC -does not need to preserve point. After evaluation, the cursor will be -moved to the end of the line (presumably of the headline of the -processed entry) and search continues from there. Under some -circumstances, this may not produce the wanted results. For example, -if you have removed (e.g., archived) the current (sub)tree it could -mean that the next entry will be skipped entirely. In such cases, you -can specify the position from where search should continue by making -FUNC set the variable `org-map-continue-from' to the desired buffer -position. +The call to @code{FUNC} will be wrapped into a save-excursion form, so +@code{FUNC} does not need to preserve point. After evaluation, the cursor +will be moved to the end of the line (presumably of the headline of the +processed entry) and search continues from there. Under some circumstances, +this may not produce the wanted results. For example, if you have removed +(e.g., archived) the current (sub)tree it could mean that the next entry will +be skipped entirely. In such cases, you can specify the position from where +search should continue by making @code{FUNC} set the variable +@code{org-map-continue-from} to the desired buffer position. -MATCH is a tags/property/todo match as it is used in the agenda match view. -Only headlines that are matched by this query will be considered during -the iteration. When MATCH is nil or t, all headlines will be -visited by the iteration. +@code{MATCH} is a tags/property/todo match as it is used in the agenda match +view. Only headlines that are matched by this query will be considered +during the iteration. When @code{MATCH} is @code{nil} or @code{t}, all +headlines will be visited by the iteration. -SCOPE determines the scope of this command. It can be any of: +@code{SCOPE} determines the scope of this command. It can be any of: @example nil @r{the current buffer, respecting the restriction if any} @@ -16420,17 +17561,18 @@ Here are a couple of functions that might be handy: @defun org-todo &optional arg Change the TODO state of the entry. See the docstring of the functions for -the many possible values for the argument ARG. +the many possible values for the argument @code{ARG}. @end defun @defun org-priority &optional action Change the priority of the entry. See the docstring of this function for the -possible values for ACTION. +possible values for @code{ACTION}. @end defun @defun org-toggle-tag tag &optional onoff -Toggle the tag TAG in the current entry. Setting ONOFF to either @code{on} -or @code{off} will not toggle tag, but ensure that it is either on or off. +Toggle the tag @code{TAG} in the current entry. Setting @code{ONOFF} to +either @code{on} or @code{off} will not toggle tag, but ensure that it is +either on or off. @end defun @defun org-promote @@ -16466,10 +17608,10 @@ The following example counts the number of entries with TODO keyword @i{MobileOrg} is the name of the mobile companion app for Org mode, currently available for iOS and for Android. @i{MobileOrg} offers offline viewing and capture support for an Org mode system rooted on a ``real'' computer. It -does also allow you to record changes to existing entries. -The @uref{http://mobileorg.ncogni.to/, iOS implementation} for the -@i{iPhone/iPod Touch/iPad} series of devices, was developed by Richard -Moreland. Android users should check out +does also allow you to record changes to existing entries. The +@uref{https://github.com/MobileOrg/, iOS implementation} for the +@i{iPhone/iPod Touch/iPad} series of devices, was started by Richard Moreland +and is now in the hands Sean Escriva. Android users should check out @uref{http://wiki.github.com/matburt/mobileorg-android/, MobileOrg Android} by Matt Jones. The two implementations are not identical but offer similar features. @@ -16479,7 +17621,7 @@ format that can be displayed by @i{MobileOrg}, and for integrating notes captured and changes made by @i{MobileOrg} into the main system. For changing tags and TODO states in MobileOrg, you should have set up the -customization variables @code{org-todo-keywords} and @code{org-tags-alist} to +customization variables @code{org-todo-keywords} and @code{org-tag-alist} to cover all important tags and TODO keywords, even if individual files use only part of these. MobileOrg will also offer you states and tags set up with in-buffer settings, but it will understand the logistics of TODO state @@ -16580,6 +17722,7 @@ should then go through these entries and do whatever actions are necessary. If a note has been stored while flagging an entry in @i{MobileOrg}, that note will be displayed in the echo area when the cursor is on the corresponding agenda line. + @table @kbd @kindex ? @item ? @@ -16596,11 +17739,11 @@ this flagged entry is finished. @kindex C-c a ? If you are not able to process all flagged entries directly, you can always return to this agenda view@footnote{Note, however, that there is a subtle -difference. The view created automatically by @kbd{M-x org-mobile-pull -@key{RET}} is guaranteed to search all files that have been addressed by the -last pull. This might include a file that is not currently in your list of -agenda files. If you later use @kbd{C-c a ?} to regenerate the view, only -the current agenda files will be searched.} using @kbd{C-c a ?}. +difference. The view created automatically by @kbd{M-x org-mobile-pull RET} +is guaranteed to search all files that have been addressed by the last pull. +This might include a file that is not currently in your list of agenda files. +If you later use @kbd{C-c a ?} to regenerate the view, only the current +agenda files will be searched.} using @kbd{C-c a ?}. @node History and Acknowledgments, GNU Free Documentation License, MobileOrg, Top @appendix History and acknowledgments @@ -16660,7 +17803,7 @@ of his great @file{remember.el}. Without Sebastian, the HTML/XHTML publishing of Org would be the pitiful work of an ignorant amateur. Sebastian has pushed this part of Org onto a much higher level. He also wrote @file{org-info.js}, a Java script for displaying -webpages derived from Org using an Info-like or a folding interface with +web pages derived from Org using an Info-like or a folding interface with single-key navigation. @end table @@ -16674,8 +17817,8 @@ would not be complete without adding a few more acknowledgements and thanks to Carsten's ones above. I am first grateful to Carsten for his trust while handing me over the -maintainership of Org. His support as been great since day one of this new -adventure, and it helped a lot. +maintainership of Org. His unremitting support is what really helped me +getting more confident over time, with both the community and the code. When I took over maintainership, I knew I would have to make Org more collaborative than ever, as I would have to rely on people that are more @@ -16689,15 +17832,13 @@ Eric is maintaining the Babel parts of Org. His reactivity here kept me away from worrying about possible bugs here and let me focus on other parts. @item Nicolas Goaziou -Nicolas is maintaining the consistency of the deepest parts of Org. His work -on @file{org-element.el} and @file{org-export.el} has been outstanding, and -opened the doors for many new ideas and features. - -@item Jambunathan K -Jambunathan contributed the ODT exporter, definitely a killer feature of -Org mode. He also contributed the new HTML exporter, which is another core -feature of Org. Here too, I knew I could rely on him to fix bugs in these -areas and to patiently explain the users what was the problems and solutions. +Nicolas is maintaining the consistency of the deepest parts of Org. His +work on @file{org-element.el} and @file{ox.el} has been outstanding, and +opened the doors for many new ideas and features. He rewrote many of the +old exporters to use the new export engine, and helped with documenting +this major change. More importantly (if that's possible), he has been more +than reliable during all the work done for Org 8.0, and always very +reactive on the mailing list. @item Achim Gratz Achim rewrote the building process of Org, turning some @emph{ad hoc} tools @@ -16721,8 +17862,17 @@ complete if the ones above were not mentioned in this manual. @item @i{Russel Adams} came up with the idea for drawers. @item +@i{Suvayu Ali} has steadily helped on the mailing list, providing useful +feedback on many features and several patches. +@item +@i{Luis Anaya} wrote @file{ox-man.el}. +@item @i{Thomas Baumann} wrote @file{org-bbdb.el} and @file{org-mhe.el}. @item +@i{Michael Brand} helped by reporting many bugs and testing many features. +He also implemented the distinction between empty fields and 0-value fields +in Org's spreadsheets. +@item @i{Christophe Bataillon} created the great unicorn logo that we use on the Org mode website. @item @@ -16746,7 +17896,11 @@ calculations and improved XEmacs compatibility, in particular by porting @item @i{Sacha Chua} suggested copying some linking code from Planner. @item -@i{Baoqiu Cui} contributed the DocBook exporter. +@i{Toby S. Cubitt} contributed to the code for clock formats. +@item +@i{Baoqiu Cui} contributed the DocBook exporter. It has been deleted from +Org 8.0: you can now export to Texinfo and export the @file{.texi} file to +DocBook using @code{makeinfo}. @item @i{Eddward DeVilla} proposed and tested checkbox statistics. He also came up with the idea of properties, and that there should be an API for @@ -16758,16 +17912,23 @@ them. inspired some of the early development, including HTML export. He also asked for a way to narrow wide table columns. @item +@i{Jason Dunsmore} has been maintaining the Org-Mode server at Rackspace for +several years now. He also sponsered the hosting costs until Rackspace +started to host us for free. +@item @i{Thomas S. Dye} contributed documentation on Worg and helped integrating the Org-Babel documentation into the manual. @item @i{Christian Egli} converted the documentation into Texinfo format, inspired the agenda, patched CSS formatting into the HTML exporter, and wrote -@file{org-taskjuggler.el}. +@file{org-taskjuggler.el}, which has been rewritten by Nicolas Goaziou as +@file{ox-taskjuggler.el} for Org 8.0. @item @i{David Emery} provided a patch for custom CSS support in exported HTML agendas. @item +@i{Sean Escriva} took over MobileOrg development on the iPhone platform. +@item @i{Nic Ferrier} contributed mailcap and XOXO support. @item @i{Miguel A. Figueroa-Villanueva} implemented hierarchical checkboxes. @@ -16789,7 +17950,9 @@ publication through Network Theory Ltd. @item @i{Niels Giesen} had the idea to automatically archive DONE trees. @item -@i{Nicolas Goaziou} rewrote much of the plain list code. +@i{Nicolas Goaziou} rewrote much of the plain list code. He also wrote +@file{org-element.el} and @file{org-export.el}, which was a huge step forward +in implementing a clean framework for Org exporters. @item @i{Kai Grossjohann} pointed out key-binding conflicts with other packages. @item @@ -16812,6 +17975,8 @@ folded entries, and column view for properties. @item @i{Tokuya Kameshima} wrote @file{org-wl.el} and @file{org-mew.el}. @item +@i{Jonathan Leech-Pepin} wrote @file{ox-texinfo.el}. +@item @i{Shidai Liu} ("Leo") asked for embedded @LaTeX{} and tested it. He also provided frequent feedback and some patches. @item @@ -16824,7 +17989,7 @@ small fixes and patches. @item @i{Jason F. McBrayer} suggested agenda export to CSV format. @item -@i{Max Mikhanosha} came up with the idea of refiling. +@i{Max Mikhanosha} came up with the idea of refiling and sticky agendas. @item @i{Dmitri Minaev} sent a patch to set priority limits on a per-file basis. @@ -16858,9 +18023,14 @@ links, among other things. @i{Pete Phillips} helped during the development of the TAGS feature, and provided frequent feedback. @item +@i{Francesco Pizzolante} provided patches that helped speeding up the agenda +generation. +@item @i{Martin Pohlack} provided the code snippet to bundle character insertion into bundles of 20 for undo. @item +@i{Rackspace.com} is hosting our website for free. Thank you Rackspace! +@item @i{T.V. Raman} reported bugs and suggested improvements. @item @i{Matthias Rempe} (Oelde) provided ideas, Windows support, and quality @@ -16883,6 +18053,9 @@ of feedback, developed and applied standards to the Org documentation. @i{Christian Schlauer} proposed angular brackets around links, among other things. @item +@i{Christopher Schmidt} reworked @code{orgstruct-mode} so that users can +enjoy folding in non-org buffers by using Org headlines in comments. +@item @i{Paul Sexton} wrote @file{org-ctags.el}. @item Linking to VM/BBDB/Gnus was first inspired by @i{Tom Shannon}'s @@ -16914,7 +18087,7 @@ with links transformation to Org syntax. @i{David O'Toole} wrote @file{org-publish.el} and drafted the manual chapter about publishing. @item -@i{Jambunathan K} contributed the ODT exporter. +@i{Jambunathan K} contributed the ODT exporter and rewrote the HTML exporter. @item @i{Sebastien Vauban} reported many issues with @LaTeX{} and BEAMER export and enabled source code highlighting in Gnus. diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS index 4d16d1925eb..0c0152f8eb1 100644 --- a/etc/ORG-NEWS +++ b/etc/ORG-NEWS @@ -1,12 +1,990 @@ ORG NEWS -- history of user-visible changes. -*- org -*- #+LINK: doc http://orgmode.org/worg/doc.html#%s +#+LINK: git http://orgmode.org/w/?p=org-mode.git;a=commit;h=%s Copyright (C) 2012-2013 Free Software Foundation, Inc. See the end of the file for license conditions. Please send Org bug reports to emacs-orgmode@gnu.org. +* Version 8.2.3 + +** Incompatible changes + +*** Combine org-mac-message.el and org-mac-link-grabber into org-mac-link.el + +Please remove calls to =(require 'org-mac-message)= and =(require +'org-mac-link-grabber)= in your =.emacs= initialization file. All you +need now is =(require 'org-mac-link)=. + +Additionally, replace any calls to =ogml-grab-link= to +=org-mac-grab-link=. For example, replace this line: + +: (define-key org-mode-map (kbd "C-c g") 'omgl-grab-link) + +with this: + +: (define-key org-mode-map (kbd "C-c g") 'org-mac-grab-link) + +*** HTML export: Replace =HTML_HTML5_FANCY= by =:html-html5-fancy= (...) + +Some of the HTML specific export options in Org <8.1 are either nil or +t, like =#+HTML_INCLUDE_STYLE=. We replaced these binary options with +option keywords like :html-include-style. + +So you need to replace + +: #+HTML_INCLUDE_STYLE: t + +by + +: #+OPTIONS: :html-include-style t + +Options affected by this change: =HTML5_FANCY=, =HTML_INCLUDE_SCRIPTS= +and =HTML_INCLUDE_STYLE=. + +*** Add an argument to ~org-export-to-file~ and ~org-export-to-buffer~ + +~org-export-to-file~ and ~org-export-to-file~ can run in a different +process when provided a non-nil =ASYNC= optional argument, without +relying on ~org-export-async-start~ macro. + +Since =ASYNC= is the first of optional arguments, you have to shift +the other optional arguments accordingly. + +*** Export back-ends are now structures + +Export back-ends are now structures, and stored as such in the +communication channel during an export process. In other words, from +now on, ~(plist-get info :back-end)~ will return a structure instead +of a symbol. + +Arguments in hooks and in filters are still symbols, though. + +** Important bugfixes + +*** [[doc:org-insert-heading][org-insert-heading]] has been rewritten and bugs are now fixed +*** The replacement of disputed keys is now turned of when reading a date + +*** Match string for sparse trees can now contain a slash in a property value + + You can now have searches like SOMEPROP="aaa/bbb". Until now, + this would break because the slash would be interpreted as the + separator starting a TOTO match string. +** New features + +*** =C-c ^ x= will now sort checklist items by their checked status + +See [[doc:org-sort-list][org-sort-list]]: hitting =C-c ^ x= will put checked items at the end +of the list. +*** Various LaTeX export enhancements + +- Support SVG images +- Support for .pgf files +- LaTeX Babel blocks can now be exported as =.tikz= files +- Allow =latexmk= as an option for [[doc:org-latex-pdf-process][org-latex-pdf-process]] +- When using =\usepackage[AUTO]{babel}=, AUTO will automatically be + replaced with a value compatible with ~org-export-default-language~ + or ~LANGUAGE~ keyword. +- The dependency on the =latexsym= LaTeX package has been removed, we + now use =amssymb= symbols by default instead. + +*** New functions for paragraph motion + + The commands =C-down= and =C-up= now invoke special commands + that use knowledge from the org-elements parser to move the cursor + in a paragraph-like way. + +*** New entities in =org-entities.el= + +Add support for ell, imath, jmath, varphi, varpi, aleph, gimel, beth, +dalet, cdots, S (§), dag, ddag, colon, therefore, because, triangleq, +leq, geq, lessgtr, lesseqgtr, ll, lll, gg, ggg, prec, preceq, +preccurleyeq, succ, succeq, succurleyeq, setminus, nexist(s), mho, +check, frown, diamond. Changes loz, vert, checkmark, smile and tilde. + +*** Anonymous export back-ends + +~org-export-create-backend~ can create anonymous export back-ends, +which can then be passed to export functions like +~org-export-to-file~, ~org-export-to-buffer~ or ~org-export-as~. + +It allows for quick translation of Org syntax without the overhead of +registering a new back-end. + +*** New agenda fortnight view + + The agenda has not, in addition to day, week, month, and year + views, also a fortnight view covering 14 days. +** New options + +*** New option [[doc:org-bookmark-names-plist][org-bookmark-names-plist]] + +This allows to specify the names of automatic bookmarks. +*** New option [[doc:org-agenda-ignore-drawer-properties][org-agenda-ignore-drawer-properties]] + +This allows more flexibility when optimizing the agenda generation. +See http://orgmode.org/worg/agenda-optimization.html for details. +*** New option: [[doc:org-html-link-use-abs-url][org-html-link-use-abs-url]] to force using absolute URLs + +This is an export/publishing option, and should be used either within +the =#+OPTIONS= line(s) or within a [[doc:org-publish-project-alist][org-publish-project-alist]]. + +Setting this option to =t= is needed when the HTML output does not +allow relative URLs. For example, the =contrib/lisp/ox-rss.el= +library produces a RSS feed, and RSS feeds need to use absolute URLs, +so a combination of =:html-link-home "..." and :html-link-use-abs-url +t= is required---see the configuration example in the comment section +of =ox-rss.el=. + +*** New option [[doc:org-babel-ditaa-java-cmd][org-babel-ditaa-java-cmd]] + +This makes java executable configurable for ditaa blocks. + +*** New options [[doc:org-babel-latex-htlatex][org-babel-latex-htlatex]] and [[doc:org-babel-latex-htlatex-packages][org-babel-latex-htlatex-packages]] + +This enables SVG generation from latex code blocks. + +*** New option: [[doc:org-habit-show-done-alwyays-green][org-habit-show-done-alwyays-green]] + +See [[http://lists.gnu.org/archive/html/emacs-orgmode/2013-05/msg00214.html][this message]] from Max Mikhanosha. + +*** New option: [[doc:org-babel-inline-result-wrap][org-babel-inline-result-wrap]] + +If you set this to the following + +: (setq org-babel-inline-result-wrap "$%s$") + +then inline code snippets will be wrapped into the formatting string. + +*** New option: [[doc:org-special-ctrl-o][org-special-ctrl-o]] + + This variable can be used to turn off the special behavior of + =C-o= in tables. +** New contributed packages + +- =ox-bibtex.el= by Nicolas Goaziou :: an utility to handle BibTeX + export to both LaTeX and HTML exports. It uses the [[http://www.lri.fr/~filliatr/bibtex2html/][bibtex2html]] + software. + +- =org-screenshot.el= by Max Mikhanosha :: an utility to handle + screenshots easily from Org, using the external tool [[http://freecode.com/projects/scrot][scrot]]. + +* Version 8.0.1 + +** Installation + +Installation instructions have been updated and simplified. + +If you have troubles installing or updating Org, focus on these +instructions: + +- when updating via a =.zip/.tar.gz= file, you only need to set the + =load-path= in your =.emacs=. Set it before any other Org + customization that would call autoloaded Org functions. + +- when updating by pulling Org's Git repository, make sure to create the + correct autoloads. You can do this by running =~$ make autoloads= (to + only create the autoloads) or by running =~$ make= (to also compile + the Emacs lisp files.) =~$ make help= and =~$ make helpall= gives you + detailed explanations. + +- when updating through ELPA (either from GNU ELPA or from Org ELPA), + you have to install Org's ELPA package in a session where no Org + function has been called already. + +When in doubt, run =M-x org-version RET= and see if you have a mixed-up +installation. + +See http://orgmode.org/org.html#Installation for details. + +** Incompatible changes + +Org 8.0 is the most disruptive major version of Org. + +If you configured export options, you will have to update some of them. + +If you used =#+ATTR_*= keywords, the syntax of the attributes changed and +you will have to update them. + +Below is a list of changes for which you need to take action. + +See http://orgmode.org/worg/org-8.0.html for the most recent version of +this list and for detailed instructions on how to migrate. + +**** New export engine + +Org 8.0 comes with a new export engine written by Nicolas Goaziou. This +export engine relies on ~org-element.el~ (Org's syntax parser), which was +already in Org's core. This new export engine triggered the rewriting of +/all/ export back-ends. + +The most visible change is the export dispatcher, accessible through the +keybinding =C-c C-e=. By default, this menu only shows some of the +built-in export formats, but you can add more formats by loading them +directly (e.g., =(require 'ox-texinfo)= or by configuring the option +[[doc:org-export-backends][org-export-backends]]. + +More contributed back-ends are available from the =contrib/= directory, the +corresponding files start with the =ox-= prefix. + +If you customized an export back-end (like HTML or LaTeX), you will need to +rename some options so that your customization is not lost. Typically, an +option starting with =org-export-html-= is now named =org-html-=. See the +manual for details and check [[http://orgmode.org/worg/org-8.0.html][this Worg page]] for directions. + +**** New syntax for #+ATTR_HTML/LaTeX/... options + + : #+ATTR_HTML width="200px" + + should now be written + + : #+ATTR_HTML :width 200px + + Keywords like =#+ATTR_HTML= and =#+ATTR_LaTeX= are defined in their + respective back-ends, and the list of supported parameters depends on + each backend. See Org's manual for details. + +**** ~org-remember.el~ has been removed + + You cannot use =remember.el= anymore to capture notes. + + Support for remember templates has been obsoleted since long, it is + now fully removed. + + Use =M-x org-capture-import-remember-templates RET= to import your + remember templates into capture templates. + +**** ~org-jsinfo.el~ has been merged into ~ox-html.el~ + + If you were requiring ~ox-jsinfo.el~ in your ~.emacs.el~ file, you + will have to remove this requirement from your initialization file. + +**** Note for third-party developers + + The name of the files for export back-end have changed: we now use the + prefix =ox-= for those files (like we use the =ob-= prefix for Babel + files.) For example ~org-html.el~ is now ~ox-html.el~. + + If your code relies on these files, please update the names in your + code. + +**** Packages moved from core to contrib + + Since packages in Org's core are meant to be part of GNU Emacs, we try + to be minimalist when it comes to adding files into core. For 8.0, we + moved some contributions into the =contrib/= directory. + + The rationale for deciding that these files should live in =contrib/= + is either because they rely on third-part softwares that are not + included in Emacs, or because they are not targetting a significant + user-base. + + - org-colview-xemacs.el + - org-mac-message.el + - org-mew.el + - org-wl.el + - ox-freedmind.el + - ox-taskjuggler.el + + Note that ~ox-freedmind.el~ has been rewritten by Jambunathan, + ~org-mew.el~ has been enhanced by Tokuya Kameshima and + ~ox-taskjuggler.el~ by Nicolas Goaziou and others. + + Also, the Taskjuggler exporter now uses TJ3 by default. John Hendy + wrote [[http://orgmode.org/worg/org-tutorials/org-taskjuggler3.html][a tutorial on Worg]] for the TJ3 export. + +** New packages in core + +*** ~ob-makefile.el~ by Eric Schulte and Thomas S. Dye + + =ob-makefile.el= implements Org Babel support for Makefile tangling. + +*** ~ox-man.el~ by Luis Anaya + + =ox-man.el= allows you to export Org files to =man= pages. + +*** ~ox-md.el~ by Nicolas Goaziou + + =ox-md.el= allows you to export Org files to Markdown files, using the + vanilla [[http://daringfireball.net/projects/markdown/][Markdown syntax]]. + +*** ~ox-texinfo.el~ by Jonathan Leech-Pepin + + =ox-texinfo.el= allows you to export Org files to [[http://www.gnu.org/software/texinfo/][Texinfo]] files. + +** New packages in contrib + +*** ~ob-julia.el~ by G. Jay Kerns + + [[http://julialang.org/][Julia]] is a new programming language. + + =ob-julia.el= provides Org Babel support for evaluating Julia source + code. + +*** ~ob-mathomatic.el~ by Luis Anaya + + [[http://www.mathomatic.org/][mathomatic]] a portable, command-line, educational CAS and calculator + software, written entirely in the C programming language. + + ~ob-mathomatic.el~ provides Org Babel support for evaluating mathomatic + entries. + +*** ~ob-tcl.el~ by Luis Anaya + + ~ob-tcl.el~ provides Org Babel support for evaluating [[http://www.tcl.tk/][Tcl]] source code. + +*** ~org-bullets.el~ by Evgeni Sabof + + Display bullets instead of stars for headlines. + + Also see [[http://orgmode.org/worg/org-faq.html#sec-8-12][this updated FAQ]] on how to display another character than "*" + for starting headlines. + +*** ~org-favtable.el~ by Marc-Oliver Ihm + + ~org-favtable.el~ helps you to create and update a table of favorite + locations in org, keeping the most frequently visited lines right at + the top. This table is called "favtable". See the documentation on + [[http://orgmode.org/worg/org-contrib/org-favtable.html][Worg]]. + +*** ~ox-confluence.el~ by Sébastien Delafond + + ~ox-confluence.el~ lets you convert Org files to [[https://confluence.atlassian.com/display/DOC/Confluence%2BWiki%2BMarkup][Confluence Wiki]] files. + +*** ~ox-deck.el~ and ~ox-s5.el~ by Rick Frankel + + [[http://imakewebthings.com/deck.js/][deck.js]] is a javascript library for displaying HTML ages as + presentations. ~ox-deck.el~ exports Org files to HTML presentations + using =deck.js=. + + [[http://meyerweb.com/eric/tools/s5/][s5]] is a set of scripts which also allows to display HTML pages as + presentations. ~ox-s5.el~ exports Org files to HTML presentations + using =s5=. + +*** ~ox-groff.el~ by Luis Anaya and Nicolas Goaziou + + The [[http://www.gnu.org/software/groff/][groff]] (GNU troff) software is a typesetting package which reads + plain text mixed with formatting commands and produces formatted + output. + + Luis Anaya and Nicolas Goaziou implemented ~ox-groff.el~ to allow + conversion from Org files to groff. + +*** ~ox-koma-letter.el~ by Nicolas Goaziou and Alan Schmitt + + This back-end allow to export Org pages to the =KOMA Scrlttr2= format. + +*** ~ox-rss.el~ by Bastien + + This back-end lets you export Org pages to RSS 2.0 feeds. Combined + with the HTML publishing feature, this allows you to build a blog + entirely with Org. + +** New features + +*** Export + +**** New export generic options + +If you use Org exporter, we advise you to re-read [[http://orgmode.org/org.html#Exporting][the manual section about +it]]. It has been updated and includes new options. + +Among the new/updated export options, three are of particular importance: + +- [[doc:org-export-allow-bind-keywords][org-export-allow-bind-keywords]] :: This option replaces the old option + =org-export-allow-BIND= and the default value is =nil=, not =confirm=. + You will need to explicitely set this to =t= in your initialization + file if you want to allow =#+BIND= keywords. + +- [[doc:org-export-with-planning][org-export-with-planning]] :: This new option controls the export of + =SCHEDULED:, DEADLINE:, CLOSED:= lines, and planning information is + now skipped by default during export. This use to be the job of + [[doc:org-export-with-timestamps][org-export-with-timestamps]], but this latter option has been given a + new role: it controls the export of /standalone time-stamps/. When + set to =nil=, Org will not export active and inactive time-stamps + standing on a line by themselves or within a paragraph that only + contains time-stamps. + +To check if an option has been introduced or its default value changed in +Org 8.0, do =C-h v [option] RET= and check if the documentation says that +the variable has been introduced (or changed) in version 24.4 of Emacs. + +**** Enhanced default stylesheet for the HTML exporter + +See the new default value of [[doc:org-html-style-default][org-html-style-default]]. + +**** New tags, classes and ids for the HTML exporter + +See the new default value of [[doc:org-html-divs][org-html-divs]]. + +**** Support for tikz pictures in LaTeX export +**** ~org-man.el~: New export function for "man" links +**** ~org-docview.el~: New export function for docview links +*** Structure editing + +**** =C-u C-u M-RET= inserts a heading at the end of the parent subtree +**** Cycling to the =CONTENTS= view keeps inline tasks folded + +[[doc:org-cycle-hook][org-cycle-hook]] as a new function [[doc:org-cycle-hide-inline-tasks][org-cycle-hide-inline-tasks]] which +prevents the display of inline tasks when showing the content of a subtree. + +**** =C-c -= in a region makes a list item for each line + +This is the opposite of the previous behavior, where =C-c -= on a region +would create one item for the whole region, and where =C-u C-c -= would +create an item for each line. Now =C-c -= on the selected region creates +an item per line, and =C-u C-c -= creates a single item for the whole +region. + +**** When transposing words, markup characters are now part of the words + +In Emacs, you can transpose words with =M-t=. Transposing =*these* +_words__= will preserve markup. + +**** New command [[doc:org-set-property-and-value][org-set-property-and-value]] bound to =C-c C-x P= + +This command allows you to quickly add both the property and its value. It +is useful in buffers where there are many properties and where =C-c C-x p= +can slow down the flow of editing too much. + +**** New commands [[doc:org-next-block][org-next-block]] and [[doc:org-previous-block][org-previous-block]] + +These commands allow you to go to the previous block (=C-c M-b= or the +speedy key =B=) or to the next block (=C-c M-f= or the speedy key =F=.) + +**** New commands [[doc:org-drag-line-forward][org-drag-line-forward]] and [[doc:org-drag-line-backward][org-drag-line-backward]] + +These commands emulate the old behavior of =M-= and =M-= but are +now bound to =S-M-= and =S-M-= respectively, since =M-= and +=M-= now drag the whole element at point (a paragraph, a table, etc.) +forward and backward. + +**** When a list item has a checkbox, inserting a new item uses a checkbox too +**** When sorting entries/items, only the description of links is considered + +Now Org will sort this list + +: - [[http://abc.org][B]] +: - [[http://def.org][A]] + +like this: + +: - [[http://def.org][A]] +: - [[http://abc.org][B]] + +by comparing the descriptions, not the links. +Same when sorting headlines instead of list items. +**** New option =orgstruct-heading-prefix-regexp= + +For example, setting this option to "^;;; " in Emacs lisp files and using +=orgstruct-mode= in those files will allow you to cycle through visibility +states as if lines starting with ";;; *..." where headlines. + +In general, you want to set =orgstruct-heading-prefix-regexp= as a file +local variable. + +**** New behavior of [[doc:org-clone-subtree-with-time-shift][org-clone-subtree-with-time-shift]] + +The default is now to ask for a time-shift only when there is a time-stamp. +When called with a universal prefix argument =C-u=, it will not ask for a +time-shift even if there is a time-stamp. + +**** New option [[doc:org-agenda-restriction-lock-highlight-subtree][org-agenda-restriction-lock-highlight-subtree]] + +This defaults to =t= so that the whole subtree is highlighted when you +restrict the agenda view to it with =C-c C-x <= (or the speed command =<=). +The default setting helps ensuring that you are not adding tasks after the +restricted region. If you find this highlighting too intrusive, set this +option to =nil=. +**** New option [[doc:org-closed-keep-when-no-todo][org-closed-keep-when-no-todo]] + +When switching back from a =DONE= keyword to a =TODO= keyword, Org now +removes the =CLOSED= planning information, if any. It also removes this +information when going back to a non-TODO state (e.g., with =C-c C-t SPC=). +If you want to keep the =CLOSED= planning information when removing the +TODO keyword, set [[doc:org-closed-keep-when-no-todo][org-closed-keep-when-no-todo]] to =t=. + +**** New option [[doc:org-image-actual-width][org-image-actual-width]] + +This option allows you to change the width of in-buffer displayed images. +The default is to use the actual width of the image, but you can use a +fixed value for all images, or fall back on an attribute like + +: #+attr_html: :width 300px +*** Scheduled/deadline + +**** Implement "delay" cookies for scheduled items + +If you want to delay the display of a scheduled task in the agenda, you can +now use a delay cookie like this: =SCHEDULED: <2004-12-25 Sat -2d>=. The +task is still scheduled on the 25th but will appear in your agenda starting +from two days later (i.e. from March 27th.) + +Imagine for example that your co-workers are not done in due time and tell +you "we need two more days". In that case, you may want to delay the +display of the task in your agenda by two days, but you still want the task +to appear as scheduled on March 25th. + +In case the task contains a repeater, the delay is considered to affect all +occurrences; if you want the delay to only affect the first scheduled +occurrence of the task, use =--2d= instead. See [[doc:org-scheduled-delay-days][org-scheduled-delay-days]] +and [[doc:org-agenda-skip-scheduled-delay-if-deadline][org-agenda-skip-scheduled-delay-if-deadline]] for details on how to +control this globally or per agenda. + +**** Use =C-u C-u C-c C-s= will insert a delay cookie for scheduled tasks + +See the previous section for why delay cookies may be useful. + +**** Use =C-u C-u C-c C-d= will insert a warning delay for deadline tasks + +=C-u C-u C-c C-d= now inserts a warning delay to deadlines. +*** Calendar, diary and appts + +**** New variable [[doc:org-read-date-minibuffer-local-map][org-read-date-minibuffer-local-map]] + +By default, this new local map uses "." to go to today's date, like in the +normal =M-x calendar RET=. If you want to deactivate this and to reassign +the "@" key to =calendar-goto-today=, use this: + +#+BEGIN_SRC emacs-lisp + ;; Unbind "." in Org's calendar: + (define-key org-read-date-minibuffer-local-map (kbd ".") nil) + + ;; Bind "@" to `calendar-goto-today': + (define-key org-read-date-minibuffer-local-map + (kbd "@") + (lambda () (interactive) (org-eval-in-calendar '(calendar-goto-today)))) +#+END_SRC + +**** In Org's calendar, =!= displays diary entries of the date at point + +This is useful when you want to check if you don't already have an +appointment when setting new ones with =C-c .= or =C-c s=. =!= will +call =diary-view-entries= and display the diary in a separate buffer. + +**** [[doc:org-diary][org-diary]]: only keep the descriptions of links + +[[doc:org-diary][org-diary]] returns diary information from Org files, but it returns it +in a diary buffer, not in an Org mode buffer. When links are displayed, +only show their description, not the full links. +*** Agenda + +**** New agenda type =agenda*= and entry types =:scheduled* :deadline*= + +When defining agenda custom commands, you can now use =agenda*=: this will +list entries that have both a date and a time. This is useful when you +want to build a list of appointments. + +You can also set [[doc:org-agenda-entry-types][org-agenda-entry-types]] either globally or locally in +each agenda custom command and use =:timestamp*= and/or =:deadline*= there. + +Another place where this is useful is your =.diary= file: + +: %%(org-diary :scheduled*) ~/org/rdv.org + +This will list only entries from =~/org/rdv.org= that are scheduled with a +time value (i.e. appointments). + +**** New agenda sorting strategies + +[[doc:org-agenda-sorting-strategy][org-agenda-sorting-strategy]] allows these new sorting strategies: + +| Strategy | Explanations | +|----------------+------------------------------------------| +| timestamp-up | Sort by any timestamp, early first | +| timestamp-down | Sort by any timestamp, late first | +| scheduled-up | Sort by scheduled timestamp, early first | +| scheduled-down | Sort by scheduled timestamp, late first | +| deadline-up | Sort by deadline timestamp, early first | +| deadline-down | Sort by deadline timestamp, late first | +| ts-up | Sort by active timestamp, early first | +| ts-down | Sort by active timestamp, late first | +| tsia-up | Sort by inactive timestamp, early first | +| tsia-down | Sort by inactive timestamp, late first | + +**** New options to limit the number of agenda entries + +You can now limit the number of entries in an agenda view. This is +different from filters: filters only /hide/ the entries in the agenda, +while limits are set while generating the list of agenda entries. + +These new options are available: + +- [[doc:org-agenda-max-entries][org-agenda-max-entries]] :: limit by number of entries. +- [[doc:org-agenda-max-todos][org-agenda-max-todos]] :: limit by number of TODOs. +- [[doc:org-agenda-max-tags][org-agenda-max-tags]] :: limit by number of tagged entries. +- [[doc:org-agenda-max-effort][org-agenda-max-effort]] :: limit by effort (minutes). + +For example, if you locally set [[doc:org-agenda-max-todos][org-agenda-max-todos]] to 3 in an agenda +view, the agenda will be limited to the first three todos. Other entries +without a TODO keyword or beyond the third TODO headline will be ignored. + +When setting a limit (e.g. about an effort's sum), the default behavior is +to exclude entries that cannot be checked against (e.g. entries that have +no effort property.) To include other entries too, you can set the limit +to a negative number. For example =(setq org-agenda-max-tags -3)= will not +show the fourth tagged headline (and beyond), but it will also show +non-tagged headlines. + +**** =~= in agenda view sets temporary limits + +You can hit =~= in the agenda to temporarily set limits: this will +regenerate the agenda as if the limits were set. This is useful for +example when you want to only see a list of =N= tasks, or a list of tasks +that take only =N= minutes. + +**** "=" in agenda view filters by regular expressions + +You can now filter agenda entries by regular expressions using ~=~. =C-u +== will filter entries out. Regexp filters are cumulative. You can set +[[doc:org-agenda-regexp-filter-preset][org-agenda-regexp-filter-preset]] to suit your needs in each agenda view. + +**** =|= in agenda view resets all filters + +Since it's common to combine tag filters, category filters, and now regexp +filters, there is a new command =|= to reset all filters at once. + +**** Allow writing an agenda to an =.org= file + +You can now write an agenda view to an =.org= file. It copies the +headlines and their content (but not subheadings) into the new file. + +This is useful when you want to quickly share an agenda containing the full +list of notes. + +**** New commands to drag an agenda line forward (=M-=) or backard (=M-=) + +It sometimes handy to move agenda lines around, just to quickly reorganize +your tasks, or maybe before saving the agenda to a file. Now you can use +=M-= and =M-= to move the line forward or backward. + +This does not persist after a refresh of the agenda, and this does not +change the =.org= files who contribute to the agenda. + +**** Use =%b= for displaying "breadcrumbs" in the agenda view + +[[doc:org-agenda-prefix-format][org-agenda-prefix-format]] now allows to use a =%b= formatter to tell Org +to display "breadcrumbs" in the agenda view. + +This is useful when you want to display the task hierarchy in your agenda. + +**** Use =%l= for displaying the headline's level in the agenda view + +[[doc:org-agenda-prefix-format][org-agenda-prefix-format]] allows to use a =%l= formatter to tell Org to +display entries with additional spaces corresponding to their level in the +outline tree. + +**** [[doc:org-agenda-write][org-agenda-write]] will ask before overwriting an existing file + +=M-x org-agenda-write RET= (or =C-c C-w= from an agenda buffer) used to +overwrite preexisting file with the same name without confirmation. It now +asks for a confirmation. + +**** New commands =M-m= and =M-*= to toggle (all) mark(s) for bulk action + +- [[doc:org-agenda-bulk-toggle][org-agenda-bulk-toggle]] :: this command is bound to =M-m= and toggles + the mark of the entry at point. + +- [[doc:org-agenda-bulk-toggle-all][org-agenda-bulk-toggle-all]] :: this command is bound to =M-*= and + toggles all the marks in the current agenda. + +**** New option [[doc:org-agenda-search-view-max-outline-level][org-agenda-search-view-max-outline-level]] + +This option sets the maximum outline level to display in search view. +E.g. when this is set to 1, the search view will only show headlines of +level 1. + +**** New option [[doc:org-agenda-todo-ignore-time-comparison-use-seconds][org-agenda-todo-ignore-time-comparison-use-seconds]] + +This allows to compare times using seconds instead of days when honoring +options like =org-agenda-todo-ignore-*= in the agenda display. + +**** New option [[doc:org-agenda-entry-text-leaders][org-agenda-entry-text-leaders]] + +This allows you to get rid of the ">" character that gets added in front of +entries excerpts when hitting =E= in the agenda view. + +**** New formatting string for past deadlines in [[doc:org-agenda-deadline-leaders][org-agenda-deadline-leaders]] + +The default formatting for past deadlines is ="%2d d. ago: "=, which makes +it explicit that the deadline is in the past. You can configure this via +[[doc:org-agenda-deadline-leaders][org-agenda-deadline-leaders]]. Note that the width of the formatting +string is important to keep the agenda alignment clean. + +**** New allowed value =repeated-after-deadline= for [[doc:org-agenda-skip-scheduled-if-deadline-is-shown][org-agenda-skip-scheduled-if-deadline-is-shown]] + +When [[doc:org-agenda-skip-scheduled-if-deadline-is-shown][org-agenda-skip-scheduled-if-deadline-is-shown]] is set to +=repeated-after-deadline=, the agenda will skip scheduled items if they are +repeated beyond the current dealine. + +**** New option for [[doc:org-agenda-skip-deadline-prewarning-if-scheduled][org-agenda-skip-deadline-prewarning-if-scheduled]] + +This variable may be set to nil, t, the symbol `pre-scheduled', or a number +which will then give the number of days before the actual deadline when the +prewarnings should resume. The symbol `pre-scheduled' eliminates the +deadline prewarning only prior to the scheduled date. + +Read the full docstring for details. + +**** [[doc:org-class][org-class]] now supports holiday strings in the skip-weeks parameter + +For example, this task will now be skipped only on new year's day: + + : * Task + : <%%(org-class 2012 1 1 2013 12 12 2 "New Year's Day")> +*** Capture + +**** Allow =C-1= as a prefix for [[doc:org-agenda-capture][org-agenda-capture]] and [[doc:org-capture][org-capture]] + +With a =C-1= prefix, the capture mechanism will use the =HH:MM= value at +point (if any) or the current =HH:MM= time as the default time for the +capture template. + +**** Expand keywords within %(sexp) placeholder in capture templates + +If you use a =%:keyword= construct within a =%(sexp)= construct, Org will +expand the keywords before expanding the =%(sexp)=. + +**** Allow to contextualize capture (and agenda) commands by checking the name of the buffer + +[[doc:org-capture-templates-contexts][org-capture-templates-contexts]] and [[doc:org-agenda-custom-commands-contexts][org-agenda-custom-commands-contexts]] +allow you to define what capture templates and what agenda commands should +be available in various contexts. It is now possible for the context to +check against the name of the buffer. +*** Tag groups + +Using =#+TAGS: { Tag1 : Tag2 Tag3 }= will define =Tag1= as a /group tag/ +(note the colon after =Tag1=). If you search for =Tag1=, it will return +headlines containing either =Tag1=, =Tag2= or =Tag3= (or any combinaison +of those tags.) + +You can use group tags for sparse tree in an Org buffer, for creating +agenda views, and for filtering. + +See http://orgmode.org/org.html#Tag-groups for details. + +*** Links + +**** =C-u C-u M-x org-store-link RET= will ignore non-core link functions + +Org knows how to store links from Org buffers, from info files and from +other Emacs buffers. Org can be taught how to store links from any buffer +through new link protocols (see [[http://orgmode.org/org.html#Adding-hyperlink-types]["Adding hyperlink types"]] in the manual.) + +Sometimes you want Org to ignore added link protocols and store the link +as if the protocol was not known. + +You can now do this with =C-u C-u M-x org-store-link RET=. + +**** =C-u C-u C-u M-x org-store-link RET= on an active region will store links for each lines + +Imagine for example that you want to store a link for every message in a +Gnus summary buffer. In that case =C-x h C-u C-u C-u M-x org-store-link +RET= will store a link for every line (i.e. message) if the region is +active. + +**** =C-c C-M-l= will add a default description for links which don't have one + +=C-c C-M-l= inserts all stored links. If a link does not have a +description, this command now adds a default one, so that we are not mixing +with-description and without-description links when inserting them. + +**** No curly braces to bracket links within internal links + +When storing a link to a headline like + +: * See [[http://orgmode.org][Org website]] + +[[doc:org-store-link][org-store-link]] used to convert the square brackets into curly brackets. +It does not anymore, taking the link description or the link path, when +there is no description. +*** Table + +**** Switching between #+TBLFM lines + +If you have several =#+TBLFM= lines below a table, =C-c C-c= on a line will +apply the formulas from this line, and =C-c C-c= on another line will apply +those other formulas. + +**** You now use "nan" for empty fields in Calc formulas + +If empty fields are of interest, it is recommended to reread the section +[[http://orgmode.org/org.html#Formula-syntax-for-Calc][3.5.2 Formula syntax for Calc]] of the manual because the description for the +mode strings has been clarified and new examples have been added towards +the end. + +**** Handle localized time-stamps in formulas evaluation + +If your =LOCALE= is set so that Org time-stamps use another language than +english, and if you make time computations in Org's table, it now works by +internally converting the time-stamps with a temporary =LOCALE=C= before +doing computation. + +**** New lookup functions + +There are now three lookup functions: + +- [[doc:org-loopup-first][org-loopup-first]] +- [[doc:org-loopup-last][org-loopup-last]] +- [[doc:org-loopup-all][org-loopup-all]] + +See [[http://orgmode.org/org.html#Lookup-functions][the manual]] for details. +*** Startup keywords + +These new startup keywords are now available: + +| Startup keyword | Option | +|----------------------------------+---------------------------------------------| +| =#+STARTUP: logdrawer= | =(setq org-log-into-drawer t)= | +| =#+STARTUP: nologdrawer= | =(setq org-log-into-drawer nil)= | +|----------------------------------+---------------------------------------------| +| =#+STARTUP: logstatesreversed= | =(setq org-log-states-order-reversed t)= | +| =#+STARTUP: nologstatesreversed= | =(setq org-log-states-order-reversed nil)= | +|----------------------------------+---------------------------------------------| +| =#+STARTUP: latexpreview= | =(setq org-startup-with-latex-preview t)= | +| =#+STARTUP: nolatexpreview= | =(setq org-startup-with-latex-preview nil)= | + +*** Clocking + +**** New option [[doc:org-clock-rounding-minutes][org-clock-rounding-minutes]] + +E.g. if [[doc:org-clock-rounding-minutes][org-clock-rounding-minutes]] is set to 5, time is 14:47 and you +clock in: then the clock starts at 14:45. If you clock out within the next +5 minutes, the clock line will be removed; if you clock out 8 minutes after +your clocked in, the clock out time will be 14:50. + +**** New option [[doc:org-time-clocksum-use-effort-durations][org-time-clocksum-use-effort-durations]] + +When non-nil, =C-c C-x C-d= uses effort durations. E.g., by default, one +day is considered to be a 8 hours effort, so a task that has been clocked +for 16 hours will be displayed as during 2 days in the clock display or in +the clocktable. + +See [[doc:org-effort-durations][org-effort-durations]] on how to set effort durations and +[[doc:org-time-clocksum-format][org-time-clocksum-format]] for more on time clock formats. + +**** New option [[doc:org-clock-x11idle-program-name][org-clock-x11idle-program-name]] + +This allows to set the name of the program which prints X11 idle time in +milliseconds. The default is to use =x11idle=. + +**** New option [[doc:org-use-last-clock-out-time-as-effective-time][org-use-last-clock-out-time-as-effective-time]] + +When non-nil, use the last clock out time for [[doc:org-todo][org-todo]]. Note that this +option has precedence over the combined use of [[doc:org-use-effective-time][org-use-effective-time]] and +[[doc:org-extend-today-until][org-extend-today-until]]. + +**** =S-= on a clocksum column will update the sum by updating the last clock +**** =C-u 3 C-S-= will update clock timestamps synchronously by 3 units +**** New parameter =:wstart= for clocktables to define the week start day +**** New parameter =:mstart= to state the starting day of the month +**** Allow relative times in clocktable tstart and tend options +**** The clocktable summary is now a caption +**** =:tstart= and =:tend= and friends allow relative times like "<-1w>" or "" +*** Babel + +**** You can now use =C-c C-k= for [[doc:org-edit-src-abort][org-edit-src-abort]] + +This allows you to quickly cancel editing a source block. + +**** =C-u C-u M-x org-babel-tangle RET= tangles by the target file of the block at point + +This is handy if you want to tangle all source code blocks that have the +same target than the block at point. + +**** New options for auto-saving the base buffer or the source block editing buffer + +When [[doc:org-edit-src-turn-on-auto-save][org-edit-src-turn-on-auto-save]] is set to =t=, editing a source block +in a new window will turn on =auto-save-mode= and save the code in a new +file under the same directory than the base Org file. + +When [[doc:org-edit-src-auto-save-idle-delay][org-edit-src-auto-save-idle-delay]] is set to a number of minutes =N=, +the base Org buffer will be saved after this number of minutes of idle +time. + +**** New =:post= header argument post-processes results + + This header argument may be used to pass the results of the current + code block through another code block for post-processing. See the + manual for a usage example. + +**** Commented out heading are ignored when collecting blocks for tangling + +If you comment out a heading (with =C-c ;= anywhere on the heading or in +the subtree), code blocks from within this heading are now ignored when +collecting blocks for tangling. + +**** New option [[doc:org-babel-hash-show-time][org-babel-hash-show-time]] to show a time-stamp in the result hash +**** Do not ask for confirmation if cached value is current + +Do not run [[doc:org-babel-confirm-evaluate][org-babel-confirm-evaluate]] if source block has a cache and the +cache value is current as there is no evaluation involved in this case. +**** =ob-sql.el= and =ob-python.el= have been improved. +**** New Babel files only need to =(require 'ob)= + +When writing a new Babel file, you now only need to use =(require 'ob)= +instead of requiring each Babel library one by one. +*** Faces + +- Org now fontifies radio link targets by default +- In the agenda, use [[doc:org-todo-keyword-faces][org-todo-keyword-faces]] to highlight selected TODO keywords +- New face [[doc:org-priority][org-priority]], enhanced fontification of priority cookies in agenda +- New face [[doc:org-tag-group][org-tag-group]] for group tags + +** Miscellaneous + +- New speedy key =s= pour [[doc:org-narrow-to-subtree][org-narrow-to-subtree]] +- Handling of [[doc:org-html-table-row][org-html-table-row]] has been updated (incompatible change) +- [[doc:org-export-html-table-tag][org-export-html-table-tag]] is replaced by [[doc:org-html-table-default-attributes][org-html-table-default-attributes]] +- Support using =git-annex= with Org attachments +- org-protocol: Pass optional value using query in url to capture from protocol +- When the refile history is empty, use the current filename as default +- When you cannot change the TODO state of a task, Org displays the blocking task +- New option [[doc:org-mobile-allpriorities][org-mobile-allpriorities]] +- org-bibtex.el now use =visual-line-mode= instead of the deprecated =longlines-mode= +- [[doc:org-format-latex-options][org-format-latex-options]] allows to set the foreground/background colors automatically +- New option [[doc:org-archive-file-header-format][org-archive-file-header-format]] +- New "neg" entity in [[doc:org-entities][org-entities]] +- New function [[doc:org-docview-export][org-docview-export]] to export docview links +- New =:eps= header argument for ditaa code blocks +- New option [[doc:org-gnus-no-server][org-gnus-no-server]] to start Gnus with =gnus-no-server= +- Org is now distributed with =htmlize.el= version 1.43 +- ~org-drill.el~ has been updated to version 2.3.7 +- ~org-mac-iCal.el~ now supports MacOSX version up to 10.8 +- Various improvements to ~org-contacts.el~ and =orgpan.el= + +** Outside Org + +*** Spanish translation of the Org guide by David Arroyo Menéndez + +David (and others) translated the Org compact guide in spanish: + +You can read the [[http://orgmode.org/worg/orgguide/orgguide.es.pdf][PDF guide]]. + +*** ~poporg.el~ and ~outorg.el~ + +Two new libraries (~poporg.el~ by François Pinard and ~outorg.el~ by +Thorsten Jolitz) now enable editing of comment-sections from source-code +buffers in temporary Org-mode buffers, making the full editing power of +Org-mode available. ~outorg.el~ comes together with ~outshine.el~ and +~navi-mode.el~, two more libraries by Thorsten Jolitz with the goal to give +source-code buffers the /look & feel/ of Org-mode buffers while greatly +improving navigation and structure editing. A detailed description can be +found here: http://orgmode.org/worg/org-tutorials/org-outside-org.html + +Here are two screencasts demonstrating Thorsten's tools: + +- [[http://youtu.be/nqE6YxlY0rw]["Modern conventions for Emacs Lisp files"]] +- [[http://www.youtube.com/watch?v%3DII-xYw5VGFM][Exploring Bernt Hansen's Org-mode tutorial with 'navi-mode']] + +*** MobileOrg for iOS + +MobileOrg for iOS back in the App Store The 1.6.0 release was focused on +the new Dropbox API and minor bug fixes but also includes a new ability to +launch in Capture mode. Track development and contribute [[https://github.com/MobileOrg/mobileorg/issues][on github]]. + * Version 7.9.3 ** New option [[doc::org-agenda-use-tag-inheritance][org-agenda-use-tag-inheritance]] diff --git a/etc/refcards/orgcard.tex b/etc/refcards/orgcard.tex index 651d7dd08eb..0e19d32a1a7 100644 --- a/etc/refcards/orgcard.tex +++ b/etc/refcards/orgcard.tex @@ -1,5 +1,5 @@ % Reference Card for Org Mode -\def\orgversionnumber{7.9.3} +\def\orgversionnumber{8.2.3} \def\versionyear{2013} % latest update \input emacsver.tex diff --git a/lisp/org/ChangeLog b/lisp/org/ChangeLog index 019fa8a358d..743053229b9 100644 --- a/lisp/org/ChangeLog +++ b/lisp/org/ChangeLog @@ -1,3 +1,5270 @@ +2013-11-12 Aaron Ecay + + * ox-latex.el (org-latex-inline-image-rules): Add "svg" to + supported filetypes. + (org-latex--inline-image): Implement SVG files inclusion. + (org-latex-headline): Don’t insert alternate title if identical to + regular one. + + * ob-python.el: Update the arglist passed to `declare-function' + for `run-python'. + + * ob-tangle.el (org-babel-tangle): Use 'light argument to + `org-babel-get-src-block-info'. + + * ob-core.el (org-babel-execute-src-block): Return nil in case of + `:results none'. Also run `org-babel-after-execute-hook' in this + circumstance. + + * org-id.el (org-id-locations-save): Bind print-(level,length) to + nil in this function. + + * ob-R.el (org-babel-R-graphics-devices): New defvar. + (org-babel-R-construct-graphics-device-call): Use it instead of a + hard-coded list of graphics devices. + + * ob-core.el (org-babel-when-in-src-block): New macro. + (org-babel-execute-src-block-maybe) + (org-babel-expand-src-block-maybe) + (org-babel-load-in-session-maybe, org-babel-pop-to-session-maybe): + Use it. + (org-babel-execute-src-block): Use `copy-tree' to prevent setf + from modifying users variables withing let-bound `info' variable. + + * ob-exp.el (org-export-babel-evaluate): Add a 'inline-only + option. + (org-babel-exp-results): Implement 'inline-only for + `org-export-babel-evaluate'. + + * org.el (org-edit-special): Use prefix arg. + + * ob-awk.el (org-babel-expand-body:awk, ob-picolisp.el) + (org-babel-expand-body:picolisp): Remove optional arg. + + * ob-R.el (org-babel-R-initiate-session): Handle case where the + session buffer exists, but does not have a live process. + (org-babel-R-construct-graphics-device-call): Change file + extension of tikz graphics files to .tikz. + + * org-src.el (org-edit-src-exit): Don't modify the undo list when + inserting the code. + + * ox-latex.el (org-latex-plain-text): Properly escape "~" for + LaTeX export. + (org-latex-image-default-option): Change default value to "". + (org-latex-image-default-width, org-latex-image-default-height): + New variables. + (org-latex-inline-image-rules): Make .tikz files as exportable + with LaTeX. + (org-latex--inline-image): Support tikz images. Also support + separate :width and :height parameters for images. + + * org-bibtex.el (org-bibtex-ask): Use `visual-line-mode' instead + of longlines-mode. + +2013-11-12 Abdó Roig-Maranges + + * org.el (org-format-latex): Do not re-generate a LaTeX preview if + the image already exists. + + * org-agenda.el (org-agenda-search-view-max-outline-level): New + option to define the max level for the entries shown by the search + view. A value of 1 means to show the top parent of the entries. + + * org.el (org-create-formula-image-with-dvipng): Fix bug that made + this function fail with no :foreground and :background attributes + set, due to bad handling of "Transparent" color. Fix bug when + colors are not `default'. + (org-format-latex-options): Add `auto' to docstring. + (org-format-latex): Get face colors at point and put them inside + opt. + (org-create-formula-image-with-imagemagick): Fix bug when handling + "Transparent" bg color. + (org-dvipng-color-format): Same as `org-latex-color-format' for + dvipng-style color specification. + +2013-11-12 Achim Gratz + + * ob-core.el (org-babel-check-confirm-evaluate): Return result of + evaluating the function pointed to by `org-confirm-babel-evaluate' + when it is a functionp and its value as a variable otherwise. + (org-babel-get-rownames, org-table.el) + (org-table-transpose-table-at-point): Replace the inadvertent use + of mapcar* (from cl) by plain mapcar and direct cons manipulation. + (org-babel-params-from-properties): Use + `org-babel-current-src-block-location' for evaluating new-style + header-argument properties. Remove superfluous save-match-data + clauses. Comment which properties get evaluated where. + (org-babel-insert-header-arg, org-babel-parse-src-block-match): + Replace `if' with empty else part by `when' for readability. + (org-babel-params-from-properties): Inquire for language specific + and default header properties. Language specific header + properties take precedence over default header properties and + old-style header property specifications. + + * org.el (org-re-property): Re-implement using full regex for + `org-re-property'. Add optional argument LITERAL to flag when + PROPERTY should to be regex-quoted. Move before definition of + `org-re-property'. + (org-re-property-keyword): Remove, functionality is subsumed by + `org-re-property'. + (org-property-re): Define using `org-re-property'. Improve + definition so that this regex can be + (org-entry-get, org-property-values): Adjust match number for + PROPVAL. (org-entry-put): Use `org-re-property' instead of + `org-re-property-keyword'. + used in all situations. Extend docstring with explanation of + matching groups. + (org-at-property-p): Implement using `org-element-at-point'. + (org-entry-properties, org-buffer-property-keys, org-indent-line): + Use `org-property-re' and adjust match group numbers accordingly. + + * org-compat.el (define-obsolete-variable-alias) + (define-obsolete-function-alias): Actually remove the third (and + any following) argument from the argument list before calling the + advised function. Extend eval-and-compile clause and add advices + for functions that have different parameter lists in XEmacs. Add + variable definitions that XEmacs lacks . + + * ob-fortran.el (org-every): Declare. + + * org-element.el (org-element-node-property-parser): Use + `org-property-re' and adjust match group numbers accordingly. + Move `looking-at' out of the let clause to not rely on the + unspecified evaluation order inside the let. + + * ob-eval.el, ob.el, org-macro.el, org-mhe.el: Require org-macs + and org-compat as necessary. + + * ob-tangle.el (org-edit-special, org-store-link) + (org-open-link-from-string): Declare functions. + + * org-macs.el (declare-function): Define macro to use autoload + instead for XEmacs. + + * ox-html.el, ox-odt.el: XEmacs does not have table.el, so use + 'noerror on the require form. + + * ox-texinfo.el (org-texinfo-table-column-widths): Fix spliced + argument list that XEmacs complains about by adding parenthesis. + + * ob-octave.el (org-babel-octave-initiate-session): If octave-inf + can't be loaded, try octave instead before giving up. Emacs + 24.3.50 and upwards replaces octave-inf with just plain octave. + + * org-id.el (org-id-update-id-locations): Autoload interactive + function. + + * ob-core.el (org-babel-parse-inline-src-block-match): + * ob-exp.el (org-babel-exp-src-block): Give header arguments from + properties priority over default header arguments. + + * ob-sh.el (org-babel-sh-var-to-sh): When detecting a table, the + first line could be the symbol `hline' rather than a list of table + cells, so check for that as well. + + * org.el (org-table-clean-did-remove-column): + * org-table.el (org-table-clean-did-remove-column): Move defvar, + this dynamic variable is only used in org-table. + + * org-table.el (org-table-colgroup-info): Remove unused defvar for + `org-table-colgroup-info'. + (org-table-clean-before-export): Let-bind regular expression + strings and remove unused matching group. Use + `org-table-clean-did-remove-column' in cond statement rather than + branching via if to avoid code duplication. Remove the code + associated with the removed `org-table-colgroup-info'. + (orgtbl-export): Remove unused internal function. + + * org-macro.el (org-macro-expand): Do not try to interpret the + macro replacement text as a regex so that escaped backslashes and + commas in macro arguments will be interpreted correctly. + + * ob-perl.el (org-babel-perl-wrapper-method): Select output handle + only after evaluation so that output is not mixed into results + eavaluation. + (org-babel-perl-evaluate): Fix the handling of results for + ":results output" to also parse tables. Use the same lambda + construction as in ob-sh.el to avoid code duplication. + + * ob-exp.el (org-babel-exp-results, org-babel-lob-execute): + Suppress user confirmation of the emacs-lisp wrapper execution + around a lob call. + + * ob-perl.el (org-babel-perl-wrapper-method): Use TAB as separator + for table results as expected by + `org-babel-import-elisp-from-file´. + + * ob-core.el (org-babel-number-p): String match for any number + moved first so that the match data for the length check does not + become corrupted. + (org-babel-confirm-evaluate-answer-no): Dynamically scoped + variable, if bound non-nil the confirmation dialog will not be + initiated and denial of evaluation is assumed. + (org-babel-check-confirm-evaluate): New macro to establish + bindings based on INFO. + (org-babel-check-evaluate): New defsubst that checks if the + evaluation of a code block is disabled. Refactors the first part + of the original function `org-babel-confirm-evaluate´. + (org-babel-confirm-evaluate): New defsubst that checks if the user + should be queried and returns the answer. Keeps the second part + of the original function `org-babel-confirm-evaluate´. + Re-implement using bindings for common subexpressions. + (org-babel-execute-src-block): Do not ask for confirmation if the + cached result is current. + (org-babel-call-process-region-original): Change declaration into + definition with nil initial value at the beginning of the file and + drop the later definition. Add comment that the dynamic scoping + of this variable is done for tramp. + + * org-table.el (org-table-eval-formula): The condition-case to + check for must be "error", not "user-error". + + * ob-perl.el (org-babel-execute:perl): Pass `result-params´ + through to `org-babel-perl-evaluate´. + (org-babel-variable-assignments:perl): Add "my" to variable + declaration so that it becomes compatible with "use strict;". Use + new internal formatting function `org-babel-perl--var-to-perl´. + (org-babel-perl--var-to-perl): New internal function, uses Perl + non-interpolating quoting on the string that defines the variable + to suppress spurious interpretation of it as Perl syntax. + (org-babel-perl-wrapper-method): Use a block and declare all + variables as "my", also use Perl quoting throughout. Redirect + STDOUT to the temporary file so that simply "print" will put the + results there. Check the return value and output in table form if + it is an ARRAY ref, otherwise print it without a final newline. + (org-babel-perl-preface): Content of this variable is prepended to + body before invocation of perl. Rename input parameter body to + ibody and let-bind body to concatentation of + `org-babel-perl-preface' and ibody. Implement results + interpretation so that tables are easier to produce. + + * ob-eval.el (org-babel-eval): Use simplified version of + `org-babel--shell-command-on-region´, we are the only caller of + this function. + (org-babel--shell-command-on-region): Replace + `org-babel-shell-command-on-region´ with a much more simplified + internal version, remove superfluous DOCSTRING and interactive + clause, strip out all conditionals which were never used. Prevent + deletion of temporary input file to aid debugging when the symbol + `org-babel--debug-input´ is bound and has non-nil value. + + * ob-tangle.el (org-babel-tangle): Do not change signature, a nil + arg is even documented in the manual. + + * org-src.el: Change declaration of `org-babel-tangle´ to "arg" + for first argument. + + * ob-core.el (org-babel-execute-src-block): Add binding for + merged-params to avoid multiple evaluation of + `org-babel-merge-params´. Rename cache? to cache-p, add binding + for cache-current-p and use it. Do not run + `org-babel-confirm-evaluate´ if source block has a cache and the + cache value is current (there is no evaluation involved in this + case). + + * org.el (org-current-time): Replace call to obsolete function + `time-to-seconds´ with a call to compatibility function + `org-float-time´. + + * org-compat.el (user-emacs-directory): If not bound, define as an + alias to `user-init-directory´ so that XEmacs continues to be + happy with Org. + + * org-macs.el: New macro to allow the 5-argument form of load to + be used where possible without breaking compatibility with XEmacs. + + * org.el (org-version, org-reload): Use + `org-load-noerror-mustsuffix´ instead of adding a fifth argument + to load directly. Guard against undefined variable load-suffixes, + which doesn't exist in XEmacs. + + * org.el: Use + `org-define-obsolete-{function,variable}-alias´instead of + `define-obsolate{function,variable}-alias´. + + * org-compat.el (user-error): Defalias to `error´ for Emacsen that + don't have it. + + * ob-python.el (org-babel-python-hline-to) + (org-babel-python-None-to): Specify customize group as 'org-babel + and widget type as 'string. + + * ob.el (org-babel-result-cond): Macro expansion needs to unquote + formal parameter `result-params´. + + * org.el (org-reload): Major rewrite. + + * org.el (org-clock-get-last-clock-out-time): Declare function. + +2013-11-12 Alan Schmitt + + * ob-ocaml.el (org-babel-prep-session:ocaml): Use + `save-window-excursion' around the code starting the tuareg + process. + (org-babel-ocaml-command): New option to specify the name of the + toplevel to run. + (org-babel-prep-session:ocaml): Directly call + `tuareg-run-process-if-needed' with `org-babel-ocaml-command' as + argument. + (org-babel-execute:ocaml): Always append ";;" at the end of the + expression before sending it to the toplevel. Do not remove the + type information if "verbatim" is a results parameter of the code + block. + (org-babel-ocaml-parse-output): Make sure the complete type is + taken into account when matching against known types. + + * org-faces.el (org-footnote): Fix docstring. + +2013-11-12 Andreas Leha + + * ob-latex.el (org-babel-execute:latex): Add a tizk option that + copies the body of the block into a tikz file. + +2013-11-12 Arun Persaud + + * org-agenda.el (org-agenda-prefix-format): Add documentation for + the new %b option. + (org-prefix-has-breadcrumbs): Add flag, `t' when %b is set. + (org-agenda-format-item): Add breadcrumbs if requested. + (org-compile-prefix-format): Add compiled information for + breadcrumbs, add %b option. + +2013-11-12 Aurélien Aptel (tiny change) + + * ox-html.el (org-html-code, org-html-verbatim): Remove fancy + string replacements for code and verbatim text when exporting to + HTML. + +2013-11-12 Bastien Guerry + + * org.el (org-align-tags-here): Fix bug: move to the correct + position. + (org-agenda-prepare-buffers): Restore the point position. + (org-insert-link): Don't remove brackets when they belong to a + timestamp in a headline. + + * org-capture.el (org-capture-refile): Don't finalize prematurely. + (org-capture): Store :return-to-wconf earlier. + (org-capture-place-template): Don't store :return-to-wconf when + called from a capture template using `function', rely on the early + :return-to-wconf value store from `org-capture'. + + * org-compat.el (org-move-to-column): New argument + `ignore-invisible' to turn on `buffer-invisibility-spec'. + + * org-agenda.el (org-agenda-show-new-time): Ignore invisible text + when inserting the new time as a text property. + (org-agenda-filter-make-matcher): When filtering tags and hitting + space, filter out entries with tags, only keep those without tags. + (org-agenda-drag-line-forward, org-agenda-drag-line-backward): Fix + bugs: don't drag lines without text and don't drag lines + before/after hidden lines. + + * ox-odt.el (org-odt-table-style-format): Use %s for inserting the + rel-width property as a string. + (org-odt-template): Fall back on a string for :rel-width. + + * org.el (org-directory, org-default-notes-file) + (org-reverse-note-order): Don't use the `org-remember' + customization group. + (org-require-autoloaded-modules): Don't require + `org-remember'. + + * org-capture.el: Update commentary section to reflect the fact + that org-remember.el is not used anymore. + + * org.el (org-babel-load-file): Set `exported-file' correctly, in + case the file as been tangled using a buffer-local value. + + * ob-tangle.el (org-babel-tangle-file): Return the list of tangled + files. + + * ox-org.el (org-org-publish-to-org): When htmlizing an .org file, + ensure to show all headings and all blocks before fontifying. + + * ob-shen.el (org-babel-ruby-var-to-ruby): Declare. + + * ox.el: Fix comment: remove reference to the obsolete variable + `org-export-language-setup'. + + * org.el (org-set-regexps-and-options-for-tags): Fix concatenation + of the tags list. + + * ox-odt.el (org-odt-pixels-per-inch): Use 96.0 as the default. + + * org.el (org-refile): With a numeric prefix argument of `3', + emulate (setq org-refile-keep t) and copy the subtree to the + target location, don't delete it. + (org-set-regexps-and-options-for-tags): Fix the setting of tag + groups when relying on `org-tag-alist', not on tags directly set + in the buffer with the #+TAGS option. + + * org-agenda.el (org-agenda-archive-with): Save window excursion. + + * org.el (org-forward-element, org-backward-element): Throw a + message instead of an error when trying to move from a position + where there is no element. + (org-clock-is-active): Fix docstring. + + * org-list.el (org-sort-list): Use `x' instead of `c' for sorting + plain list by checked status. + + * org.el (org-structure-template-alist): Fix custom type and + default value. + (org-set-regexps-and-options-for-tags): Enhance docstring. + (org-set-regexps-and-options): Make sure not to add + `org-tag-alist' twice when setting this variable through et + #+setupfile: directive. + (org-tags-expand): Use `with-syntax-table'. + + * org-list.el (org-sort-list): Implement sorting by "checked" + status for check lists. + + * org-table.el (org-table-sum): Fix rounding error when summing + times. + + * ob-scheme.el (org-babel-scheme-execute-with-geiser): Fix code + typo. Add declarations. + + * ox-html.el (org-html-link-use-abs-url): New option. + (org-html-link): Use it to prepend relative links with the value + of HTML_LINK_HOME, when defined. + + * org.el (org-refile): Fix refiling the active region within an + list. Don't store the last refiled subtree in the kill ring. + + * org.el (org-mode-map): Remap `forward-paragraph' and + `backward-paragraph' to `org-forward-element' and + `org-backward-element'. + + * ox-html.el (org-html-begin-plain-list): New parameter + `ordered-num' to tell whether the list is ordered numerically. + (org-html-plain-list): Handle alphabetical ordered list. + + * org-agenda.el (org-batch-agenda): Let-bind `org-agenda-sticky' + to nil during batch export. + + * org.el (org-copy-subtree): Fix typo in docstring. + (org-scan-tags): Don't disable `case-fold-search' too early. + + * org-agenda.el (org-agenda-skip-eval): Fix typo in docstring. + + * org-capture.el (org-capture-set-target-location): Don't throw an + error when `org-time-was-given' is not bound. + + * org-clock.el (org-clock-modify-effort-estimate): Clarify + docstring. + + * org.el (org-set-regexps-and-options-for-tags): Return a list + with tag-related variables. + (org-set-regexps-and-options): Append tags from a setup file to + the local tags of the file. + (org-agenda-prepare-buffers): Set tags from a setup file by + calling `org-set-regexps-and-options' when necessary. + (org-set-regexps-and-options): Fix `org-deadline-time-hour-regexp' + and `org-scheduled-time-hour-regexp'. + + * org-table.el (org-table-TBLFM-begin-regexp): Rename from + `org-TBLFM-begin-regexp'. + (org-table-calc-current-TBLFM): Rename from + `org-calc-current-TBLFM'. + + * org.el (org-ctrl-c-ctrl-c): Require org-table if needed. + (org-refresh-properties): Put the text property on the whole + subtree, not just on the headline. + (org-get-outline-path): Remove statistical and checkboxes cookies. + + * org-agenda.el (org-agenda, org-search-view, org-tags-view) + (org-agenda-get-day-entries, org-agenda-set-restriction-lock): Use + (current-buffer) as the value of `org-agenda-restrict'. Fix a bug + about narrowing to wrong region boundaries when + `org-agenda-restrict' is non-nil. + + * org.el (org-agenda-text-search-extra-files): Fix typos in + docstring. + (org-insert-heading): Fix case when there the first heading starts + at the beginning of the buffer. + + * ob-core.el (org-babel-expand-src-block): Use + `org-called-interactively-p'. + + * org.el (org-agenda-prepare-buffers): Avoid duplicates in + `org-tag-alist-for-agenda' correctly. + (org-read-date-minibuffer-local-map): Check if we are at the + beginning of the prompt, not if we are after a whitespace. Bind + C-. to `calendar-goto-today'. + + * org-clock.el (org-clock-in): Don't forward by one character when + setting the marker in the clock history. + + * org.el (org-read-date-minibuffer-local-map): Call + `calendar-goto-today' only if there is a space before point in the + minibuffer prompt. + (org-insert-heading): Reveal context when called interactively. + Fix bug about wrong conversion of lines with :END: or #+end_ into + headlines. + (org-in-drawer-p): New function. + (org-meta-return): Use `org-catch-invisible-edits' and the + `org-in-drawer-p' to check whether we are within a drawer. + + * org-list.el (org-sort-list): Fix infloop. + + * org.el (org-clone-subtree-with-time-shift): Unconditionally ask + for a time shift if there is a time-stamp. Don't ask for a time + shift when called with a universal prefix argument. + + * ob-core.el (org-babel-insert-result): Fix bug when inserting + results as a list: ensure we split a string containing "\n". + + * ox-html.el: Fix copyright header. + + * org.el (org-store-link): Don't add a search string when storing + a link from a radio target. + (org-open-at-point): Jump to the radio link (<<>>), not to + the simple target (<>). + + * org-table.el (org-table-get-remote-range): Fix typo. + + * org-datetree.el (org-datetree-find-month-create) + (org-datetree-find-day-create): Add a docstring. + (org-datetree-find-year-create): Only match headlines with a + year or a year and one or more tags. + + * org-crypt.el (org-crypt-check-auto-save) + (org-crypt-use-before-save-magic): Use `org-add-hook' when the + hooks are local hooks. + + * org-agenda.el (org-agenda-mode): Use `org-add-hook' and merge + upstream change from Emacs 2013-04-18T00:12:33Z!monnier@iro.umontreal.ca. + + * ob-core.el (org-babel-pop-to-session-maybe): Fix docstring. + (org-babel-pop-to-session-maybe): Use true function's name, + not its alias. + + * org-agenda.el (org-agenda-drag-line-forward) + (org-agenda-drag-line-backward): New commands. + (org-agenda-mode-map): Bind the new commands to M- and + M- respectively. + + * org.el (org-insert-heading): Fix insertion of items. + + * org-capture.el (org-capture-use-agenda-date): Fix docstring. + + * org-agenda.el (org-agenda-bulk-toggle): Fix docstring. + (org-agenda-bulk-toggle-all): New command. + (org-agenda-mode-map): Bind `org-agenda-bulk-toggle' to `M-m' + and `org-agenda-bulk-toggle-all' to `M-*'. + (org-agenda-menu): Add `org-agenda-bulk-toggle' and + `org-agenda-bulk-toggle-all'. + (org-agenda-bulk-mark, org-agenda-bulk-unmark): Jump to the + next headline, not the next line. + + * org-capture.el (org-mks): Fix bug: let-bind `case-fold-search' + to nil while matching the first letter of a multi-letters + template. + + * org.el (org-store-link): When a bracket link is found in a + headline, use the link description or the link path. + (org-flag-drawer, org-hide-block-toggle) + (org-goto-left, org-goto-right, org-promote) + (org-paste-subtree, org-narrow-to-block, org-sort-entries) + (org-insert-link, org-offer-links-in-entry, org-open-file) + (org-refile, org-refile-get-location) + (org-refile-check-position, org-prepare-dblock, org-todo) + (org-auto-repeat-maybe, org-show-todo-tree, org-sparse-tree) + (org-occur, org-priority, org-scan-tags) + (org-get-tags-string, org-property-action, org-set-effort) + (org-entry-put, org-insert-drawer) + (org-compute-property-at-point) + (org-property-next-allowed-value, org-evaluate-time-range) + (org-closest-date, org-timestamp-change) + (org-revert-all-org-buffers, org-cycle-agenda-files) + (org-agenda-file-to-front, org-remove-file) + (org-preview-latex-fragment, org-format-latex) + (org-create-math-formula, org-create-formula-image) + (org-speed-command-help, org-check-before-invisible-edit) + (org-modifier-cursor-error, org-hidden-tree-error) + (org-mark-subtree, org-kill-line, org-first-sibling-p) + (org-up-element, org-down-element) + (org-drag-element-backward, org-drag-element-forward) + (org-unindent-buffer, org-speedbar-set-agenda-restriction): Use + `user-error' instead of `error'. + + * ox-latex.el (latex): Don't force exporting with smart quotes. + + * ox.el (org-export-with-smart-quotes): Mention the need to use + the relevant Babel package when setting this option to non-nil. + + * org-src.el (org-edit-src-turn-on-auto-save): New option. + (org-edit-src-code): Use it. + (org-edit-src-auto-save-idle-delay): Enhance docstring. + + * org-capture.el (org-mks): Make cursor invisible. + + * org.el (org-link-expand-abbrev): Save match data before before + calling the replacement function. + + * org-list.el (org-sort-list): Don't move point when matching time + values. + + * org.el (org-shifttab): Show the correct number of empty + headlines when called with a numeric prefix argument. Enhance + docstring. + (org-uniquify): Use `copy-sequence'. + (org-adaptive-fill-function, org-fill-paragraph): Throw a useful + error message when parse an element fails in the current buffer. + + * ox.el (org-export-with-planning): Enhance docstring. + + * org.el (org-closed-keep-when-no-todo): New option. + (org-todo): Use the new option. + (org-open-line): Rename from `org-ctrl-o'. + (org-mode-map): Use `remap'. + (org-cycle-emulate-tab, org-file-apps) + (org-set-font-lock-defaults) + (org-translate-link-from-planner, org-link-search) + (org-refile-get-targets, org-read-date-get-relative): Minor + code clean-up: fix dangling parentheses. + + * org-agenda.el (org-agenda-entry-text-mode): Also check against + regexp filters. + (org-timeline): Handle `org-agenda-show-log'. + + * org-clock.el (org-clock-select-task): Remove successive + duplicates in the clock history to consider. + + * org.el (org-uniquify-alist): Improve docstring. + (org-make-tags-matcher, org-change-tag-in-region): Add buffer's + tags to the tags completion table. + (org-tags-expand): Prevent circular replacement of group tags. + Tiny docstring formatting. + (org-uniquify): Make a defsubst. Use `delete-dups' instead of + `add-to-list'. + (org-todo): Also remove the CLOSED planning information when + removing the TODO keyword. + (org-forward-heading-same-level): Fix bug when forwarding + to a hidden subtree of the same level. + (org-tags-expand): Use word delimiters when building the tag + search regexp. + + * org-clock.el (org-clock-insert-selection-line): Don't display + the clockout time. + + * org.el (org-emphasis-regexp-components): Make a defvar. + (org-emphasis-alist): New default value: don't set HTML tags. + (org-emphasize, org-set-emph-re): Use the new value of + `org-emphasis-alist'. + + * org-mobile.el (org-mobile-edit): Insert new headings at the end + of the parent subtree. Use `org-at-heading-p' instead of the + obsolete `org-on-heading-p'. + + * org.el (org-insert-heading): When called from a list item and + `org-insert-heading-respect-content' is non-nil, insert a heading, + not an item. + (org-insert-heading-respect-content): Fix docstring. + (org-insert-heading): When in a non-empty non-headline line, + convert the current line into a headline. + + * org-table.el (org-table-copy-down): Don't move cursor when + getting the field. + + * ox-icalendar.el (org-icalendar-export-current-agenda): Do not + evaluate babel code blocks. + + * ox-html.el (html): Add more options. + + * ox-publish.el (org-publish-project-alist): Add :with-planning in + docstring. + + * ob-exp.el (org-babel-exp-src-block): Tiny docstring fix. + + * ox-icalendar.el (org-icalendar--combine-files): Fix typo. + + * org-mouse.el (org-mouse-agenda-context-menu): Fix a function's + name. + + * ox.el (org-export-options-alist, org-export--skip-p): Use + `:with-planning' instead of `:with-plannings', to keep in sync + with the corresponding option's name. + + * ob-core.el (org-babel-confirm-evaluate): Fix typo in docstring. + + * org-agenda.el (org-agenda-undo, org-agenda) + (org-agenda-append-agenda) + (org-agenda-get-restriction-and-command, org-agenda-write) + (org-agenda-clock-cancel) + (org-agenda-diary-entry-in-org-file, org-agenda-diary-entry) + (org-agenda-execute-calendar-command) + (org-agenda-goto-calendar, org-agenda-convert-date) + (org-agenda-bulk-mark, org-agenda-bulk-action) + (org-agenda-show-the-flagging-note): Use `user-error' instead of + `error'. + + * org-macs.el (org-with-remote-undo): Normalize argument names. + + * org.el (org-store-log-note): Fix `buffer-undo-list' when called + after `org-agenda-todo'. + (org-add-log-note): Minor formatting fix. + + * org-agenda.el (org-agenda-append-agenda): Set buffer read only. + + * org-clock.el (org-clock-select-task): Throw a user error when + the clock history is empty. + + * org-table.el (org-table-get-remote-range): Fix docstring: use + #+NAME instead of #+TBLNAME. + + * ob-ref.el: Use #+NAME instead of #+TBLNAME in comment. + + * ox-html.el (org-html-table-row-tags): Better example. + + * org-clock.el (org-clock-select-task): Fix window to buffer. + Hide the cursor. + (org-clock-insert-selection-line): Add the clock-out time. + + * ox-html.el (org-html-table-row-tags): Allow new dynamically + bound value `row-number'. + (org-html-table-row): Bind `row-number' to the number of the + row (first row is 0). + + * org.el (org-minutes-to-clocksum-string): Round fractions of + minutes. + + * ox-html.el (org-html-table-row-tags): Fix example in docstring. + + * org-agenda.el (org-agenda-span-to-ndays): Enhance docstring. + (org-agenda-goto-date): Fix bug when going to a date in month + view. + (org-agenda-goto-date): Put the cursor on the agenda line with the + selected date. + (scheduled/deadline items with hour spec) then redo an agenda*. + + * org-clock.el (org-clock-resolve): Enhance the content of the + help window. + + * org-footnote.el (org-footnote-auto-label): Minor docstring fix. + + * ox-odt.el (org-odt-link): Fix bug: convert & to & in + links. + + * ox-html.el (org-html-table-row): Dynamically bind + `rowgroup-number', `start-rowgroup-p', `end-rowgroup-p', + `top-row-p', `bottom-row-p'. + (org-html-table-row-tags): Update docstring: tell what variables + are dynamically bound. + + * org-src.el (org-edit-src-code): Don't set + `buffer-auto-save-file-name' unless `auto-save-default' is + non-nil. + + * ox.el (org-export-table-row-group): Fix typo in docstring. + + * org-table.el (orgtbl-apply-fmt): Enhance docstring. + + * org.el (org-file-contents): Make the message more prominent. + + * ox.el (org-export-replace-region-by): New function. + + * ox-texinfo.el (org-texinfo-convert-region-to-texinfo), + * ox-md.el (org-md-convert-region-to-md), + * ox-latex.el (org-latex-convert-region-to-latex), + * ox-html.el (org-html-convert-region-to-html): New functions to + replace the active region by its export into various backends. + + * org-faces.el (org-agenda-restriction-lock): Use less flashy + colors. + + * org-agenda.el + (org-agenda-restriction-lock-highlight-subtree): New option. + (org-agenda-top-headline-filter): Rename from + `org-agenda-top-headline-filter'. + (org-find-top-headline): Rename from `org-find-top-category'. + Add a docstring. + (org-agenda-filtered-by-top-headline): Rename from + `org-agenda-filtered-by-top-category'. + (org-agenda-filter-by-top-headline): Rename from + `org-agenda-filter-by-top-category'. Fix docstring. + (org-agenda-filter-top-headline-apply): Rename from + `org-agenda-filter-top-category-apply'. Fix docstring. + (org-agenda-mode-map): Update binding. + (org-agenda-get-todos): Set `todo-state' earlier so that we can + skip false-positives in time. + + * org.el (org-get-todo-state): Add a docstring. + (org-ctrl-o): New command to insert a new row in tables + (like `M-S-' does) and open a line elsewhere. + (org-mode-map): Bind the new command to `C-o'. + (org-set-regexps-and-options): Process tags from an external setup + file. + + * org-agenda.el (org-agenda-dim-blocked-tasks): Enhance docstring. + (org-agenda-finalize-entries): Conditionally apply limits so + that we don't manipulate big lists uselessly. + (org-agenda-limit-entries): Limit exclusively. E.g., when + limiting to a maximum of "2 tags", don't limit among tagged + entries only, but limit among all entries. + (org-agenda-limit-interactively): New command. + (org-agenda-mode-map): Bind the new command to "~". + (org-agenda-redo): Small fix: don't use `eval'. + + * org.el (org-ctrl-c-ctrl-c): Fix bug wrt updating checkboxes: the + list beginning should be stored using a marker so that updating + [%0] to [%50] will not throw an error. + (org-babel-load-file): Move `org-babel-load-file' from + ob-tangle.el to here so that it is correctly autoloaded by Emacs + before Org is required. + + * org-mac-message.el: Delete. + + * org.el (org-modules): org-mac-message.el is not a core package + anymore. + + * org-table.el (orgtbl-to-generic): Fix bug when exporting the + cells of radio tables with 'hline. + + * org.el (org-speed-commands-default): Use ?s for + `org-narrow-to-subtree'. + + * org-agenda.el (org-agenda-start-on-weekday): Fix typo. + (org-agenda-start-day): Enhance docstring. + + * org-src.el (org-src-native-tab-command-maybe): Check that we are + in a source code block. + + * org-mobile.el: Remove useless defvar. + + * org.el (org-indent-line): A line just below a line with a list + item is now indented depending on the indentation of this list + item. + + * org.el (org-options-keywords): Add #+TARGET. + + * org-clock.el (org-resolve-clocks-if-idle): Only try to resolve + last clock if the clock buffer still exists. + (org-clock-out, org-clock-cancel): Set markers to nil. + + * ox-org.el (org-org-publish-to-org): + * ox-html.el (org-html-publish-to-html): Use the custom extension. + + * org.el (org-cycle-internal-local): Fix invalid search bound when + `org-cycle-include-plain-lists' is set to 'integrate. + + * org.el (org-sparse-tree-default-date-type): Add an option for + closed time-stamps. + (org-sparse-tree): Allow to check against closed time-stamps. + (org-re-timestamp): Handle closed time-stamps. + (org-closed-in-range): Delete. + + * org-capture.el (org-capture-import-remember-templates): Take + care of adding :jump-to-captured option if needed. + + * org.el (org-toggle-pretty-entities): Enhance messages. + (org-raise-scripts): Handle scripts like "a_b^c". + + * org-capture.el (org-capture-templates): Document new option + :jump-to-captured in the docstring. Offer the complete list of + options when customizing. + (org-capture-finalize): Handle :jump-to-captured. + + * org.el (org-agenda-prepare-buffers): Fix bugs: don't let-bind + `org-tag-alist' to nil and don't append duplicate tags to + `org-tag-alist-for-agenda'. + (org-store-link): Storing multiple links in the active region now + requires a triple prefix argument. + (org-store-link, org-link-search): Fix handling of links to #+NAME + and #+TARGET keywords. + + * org-compat.el (org-ignore-region): Tiny docstring fix. + + * org-capture.el (org-capture): Don't store multiple links over + lines in the active region. + + * ox-odt.el (org-odt-special-block): Don't wrap annotations into + ... at all. + (org-odt--fix-annotations): New function. + (org-odt--export-wrap): Use the new function to fix annotations + insertion in content.xml. + + * org.el (org-mode-flyspell-verify): Require 'org-element so that + `org-element-affiliated-keywords' is defined. + + * ox-odt.el (org-odt-special-block): Don't insert annotations + using style "Text_20_body". + + * org.el (org-toggle-tags-groups): Correctly highlight group tags. + (org-tags-expand): Expand tags as words, with characters ?@ + and ?_ being considered words constituents. + (org-set-regexps-and-options): Don't read setup files from + read-only buffers. + (org-file-contents): When no-error is non-nil, throw a less + intrusive message. + + * org-agenda.el (org-agenda-scheduled-leaders) + (org-agenda-deadline-leaders): Re-align leaders to the left, + back to a 11 characters width. + + * org.el (org-refile-cache-check-set): More informative message. + + * org-agenda.el (org-tags-view): Set the matcher after preparing + the agenda, as `org-tag-groups-alist-for-agenda' might be needed. + (org-agenda-filter-make-matcher): New parameter `filter' and + `type'. Handle group tags. + (org-agenda-filter-expand-tags): New function. + (org-agenda-filter-apply): Handle group tags. + + * org.el (org-blank-before-new-entry): Tiny docstring fix. + (org-tag-alist-for-agenda): Add docstring. + (org-tag-groups-alist-for-agenda): New global variable. + (org-tag-groups-alist): New buffer-local variable. + (org-tag-alist, org-tag-persistent-alist): Handle :grouptags. + (org-group-tags): New option. + (org-toggle-group-tags): New command. + (org-mode-map): Bind `org-toggle-group-tags' to `C-c C-x q'. + (org-set-regexps-and-options-for-tags): New function, factored + out from `org-set-regexps-and-options'. + (org-set-regexps-and-options): Don't handle tags, they are now + handled separately by `org-set-regexps-and-options-for-tags'. + (org-assign-fast-keys): Handle :grouptags. + (org-mode): Use `org-set-regexps-and-options-for-tags' on top + of `org-set-regexps-and-options'. + (org-fontify-meta-lines-and-blocks-1): Fontify group tags. + (org-make-tags-matcher): Expand group tags in the matcher. + (org-tags-expand): New function. + (org-tags-completion-function): Tiny code clean up. + (org-set-current-tags-overlay): Add a docstring. + (org-fast-tag-selection): Highlight group tags. + (org-agenda-prepare-buffers): Set `org-tag-alist-for-agenda' + and `org-tag-groups-alist-for-agenda'. Don't uniquify + `org-tag-alist-for-agenda' as we may need the grouping + information for filtering in the agenda buffer. + (org-uniquify-alist): New function. + + * org-pcomplete.el (pcomplete/org-mode/file-option/tags): Handle + :grouptags. + + * org-faces.el (mode-line): New face for group tags. + + * ob-core.el (org-babel-hash-show-time): Tiny docstring + enhancement. + + * org-element.el (org-element-paragraph-separate): Use new name + `org-list-allow-alphabetical'. + + * org-list.el (org-list-allow-alphabetical): Rename from + `org-alphabetical-lists'. + (org-list-empty-line-terminates-plain-lists): Rename from + `org-empty-line-terminates-plain-lists'. + (org-checkbox-hierarchical-statistics): Rename from + `org-hierarchical-checkbox-statistics'. + + * org.el (org-image-actual-width): Update docstring. + (org-display-inline-images): Use the #+attr_html: :width syntax. + (org-modules): Remove deleted libraries, add new ones. + + * ox-html.el (org-html-indent): Default to nil, as non-nil can + break indentation of source code blocks. + (org-html-link): Don't insert nil if there is no attributes. + (org-html-link--inline-image): Use the correct syntax for image + attributes. Allow :width :height and :alt as predefined + attributes for inline images. + (org-html-link, org-html-table): Use the standard syntax--- + e.g. "#+attr_html: :options ..."--- to get attributes. + + * ox.el (org-export-table-cell-alignment): Treat an empty cell as + a number if it follows a number. + + * ox.el (org-export-as): Allow user functions in + `org-export-before-parsing-hook' to modify the point. + + * org.el (org-entry-add-to-multivalued-property): Add the new + value by appending it at the end of the line. + + * org-table.el (orgtbl-to-generic): New parameter `backend' to + export cells content using a specific backend. + (orgtbl-to-latex, orgtbl-to-texinfo): Export cells to LaTeX + and Texinfo before sending the table. + + * ox.el (org-export-define-backend) + (org-export-define-derived-backend): Make defuns and update + docstrings. + + * ox-texinfo.el (texinfo): + * ox-org.el (org): + * ox-odt.el (odt): + * ox-md.el (md): + * ox-man.el (man): + * ox-latex.el (latex): + * ox-icalendar.el (icalendar): + * ox-html.el (html): + * ox-beamer.el (beamer): + * ox-ascii.el (ascii): Use `org-export-define-backend' and + `org-export-define-derived-backend' as defuns, not macros. + + * org.el (org-set-regexps-and-options): Use + `org-table-set-constants'. + + * org-table.el (org-table-set-constants): New function. + (orgtbl-ctrl-c-ctrl-c): Use it. + + * org-pcomplete.el + (pcomplete/org-mode/block-option/clocktable): Add parameters. + + * org.el (org-options-keywords): Remove "INFOJS_OPT": it is added + through ox-html.el now. + + * org-agenda.el (org-agenda-redo): Set filters after agenda has + been redone. + + * org.el (org-store-link): When there is an active region, store + each line as a separate link. + (org-insert-all-links): Use a default description when links + do not have one already. + + * org-agenda.el (org-agenda-redo): Fix code typo. + + * org.el (org-link-display-format): Fix docstring. + + * ox-publish.el (org-publish-org-to) + (org-publish-org-sitemap, org-publish-find-title) + (org-publish-find-date) + (org-publish-cache-file-needs-publishing): Set + `org-inhibit-startup' to t when visiting files for + publication. + + * ox-org.el (org-org-publish-to-org): Kill buffers not visited at + publication time. + + * org.el (org-set-font-lock-defaults): Set font-lock keywords + correctly for plain links. + + * ox-texinfo.el (org-texinfo-logfiles-extensions) + (org-texinfo-remove-logfiles): New options. + (org-texinfo-compile): Use the new options to remove files + after compiling a Texinfo file. + + * ox-texinfo.el (org-texinfo-coding-system): New option. + (org-texinfo-template): Add @documentlanguage and + @documentencoding. + (org-texinfo-headline): Add a space before tags. + (org-texinfo-export-to-texinfo, org-texinfo-export-to-info): + Use `org-texinfo-coding-system' as the coding system for + exported buffers. + (org-texinfo-publish-to-texinfo): New function. + + * ox-texinfo.el (org-texinfo-filename) + (org-texinfo-info-process, org-texinfo-max-toc-depth) + (org-texinfo--sanitize-menu): Docstrings tiny fixes. + + * org-agenda.el (org-agenda-dim-blocked-tasks): Only throw a + message when called interactively. Fix docstring position in the + defun. + + * ox-html.el (org-html--build-meta-info): Fix setting of + http-equiv="Content-Type". + + * org-agenda.el (org-agenda-mode-map): Use ?= for filtering by + regexp and ?| for removing all filters. + (org-agenda-filter-remove-all): New command. + (org-agenda-filter-show-all-re): Rename from + `org-agenda-filter-show-all-regexp'. + (org-agenda-filter-by-regexp): Call + `org-agenda-filter-show-all-re'. + + * org-list.el (org-insert-item): Don't ask for a definition term + when insert an item in a description list. + + * org-agenda.el (org-agenda-Quit): Set `org-agenda-buffer' to nil. + This prevents bugs when calling e.g., `org-diary' after quitting + an agenda window. + (org-agenda-entry-types): Move earlier in the file. + (org-agenda-custom-commands-local-options, org-diary) + (org-agenda-get-day-entries): Don't hardcode the default agenda + entry types, use `org-agenda-entry-types'. + (org-agenda-custom-commands): Fix default setting so that the + customize interface does not complain about a mismatch. + + * org.el (org-export-backends): Add new backends. + + * ox-html.el (org-html-indent): New option. + (org-html-use-unicode-chars): New option. + (org-html-pretty-output): Delete. + (org-html-final-function): Use the new options. + + * ox-html.el (org-html-link): Fix handling of abbreviated links + which include a file: protocol. + (org-html--build-postamble): Default to today's date. + (org-html--build-meta-info): When #+DATE contains a time stamp, + parse it as a RFC 822 time string, otherwise simply insert the + date as a string. + + * ox.el (org-export--copy-to-kill-ring-p): New function. + (org-export-copy-to-kill-ring): Use 'if-interactive as the + default. + (org-export-to-buffer, org-export-to-file): Use + `org-export--copy-to-kill-ring-p' and fix docstrings. + + * ox-odt.el (org-odt-export-as-odf): Use + `org-export--copy-to-kill-ring-p'. + + * org.el (org-set-font-lock-defaults): Fontify macros. + + * org-faces.el (org-macro): New face. + + * org.el (org-clone-subtree-with-time-shift): Only prompt for a + time shift when the entry at point has a time stamp and when the + command is called with a universal prefix argument. + (org-execute-file-search-functions): Docstring fix. + + * org-compat.el (org-defvaralias): Fix declare form. + + * org-clock.el (org-clocktable-defaults): Add :mstart parameter. + (org-clock-special-range): New argument mstart. + (org-dblock-write:clocktable, org-dblock-write:clocktable) + (org-clocktable-write-default, org-clocktable-steps) + (org-clock-get-table-data): Handle the :mstart parameter. + + * org.el (org-map-entries): Use `save-window-excursion'. + + * org-compat.el (org-defvaralias): New compatibility function. + + * org-list.el (org-cycle-include-plain-lists): Also add to the + 'org-cycle customization group. + (org-list-allow-alphabetical) + (org-checkbox-hierarchical-statistics) + (org-list-empty-line-terminates-plain-lists) + (org-list-description-max-indent): Rename and add aliases to old + names. + + * org-element.el (org-element-context): Prevent an error when + getting the context of a table rule. + + * org.el (org-deadline-time-hour-regexp) + (org-scheduled-time-hour-regexp): New buffer local variables. + (org-set-regexps-and-options): Set the new variables. + + * org-agenda.el (org-agenda-custom-commands-local-options): Add + :deadline* and :scheduled* to the list of possible agenda entry + types. + (org-agenda): Implement a new agenda type agenda* with :scheduled* + and :deadline* replacing :scheduled and :deadline respectively in + agenda entry types. In such agenda, only scheduled and deadline + items with a time specification [h]h:mm will be considered. + (org-agenda-entry-types): Document the new agenda entry types + :scheduled* and :deadline*. + (org-agenda-list): New parameter `with-hour'. Use :scheduled* and + :deadline*. + (org-agenda-get-day-entries): Handle :scheduled* and :deadline*. + (org-agenda-get-deadlines, org-agenda-get-scheduled): New + parameter `with-hour'. Use `org-deadline-time-hour-regexp' or + `org-scheduled-time-hour-regexp' as the search string if needed. + (org-agenda-to-appt): Use :scheduled* and :deadline* by default, + as other scheduled and deadline items don't have a time spec and + cannot be turned into appointments. Trim bracket links and use + only the description as the appointment text. + (org-agenda-get-restriction-and-command): Add + default description for the agenda* view. + (org-agenda-run-series): Handle agenda* views. + + * org-faces.el (org-agenda-filter-tags) + (org-agenda-diary, org-agenda-calendar-event) + (org-agenda-calendar-sexp): Minor code clean up. + (org-agenda-filter-category): Docstring fix. + (org-agenda-filter-category): New face. + + * org-agenda.el (org-agenda-local-vars): Add + `org-agenda-re-filter-overlays' and `org-agenda-regexp-filter'. + (org-agenda-mode-map): Use "|" for + `org-agenda-filtered-by-regexp'. + (org-agenda-re-filter-overlays): New variable. + (org-agenda-mark-filtered-text): Use + `org-agenda-re-filter-overlays'. + (org-agenda-finalize, org-agenda-redo): Allow regexp filtering. + (org-agenda-filter-by-category): Set `org-agenda-category-filter' + here instead of within `org-agenda-apply-filter'. + (org-agenda-regexp-filter): New variable. + (org-agenda-filter-by-regexp): New function to filter agenda + buffers by regexp. + (org-agenda-filter-make-matcher): Make matcher for regexp filters. + (org-agenda-filter-apply): Don't set `org-agenda-tag-filter' and + `org-agenda-category-filter'. Maybe apply regexp filter. + (org-agenda-filter-hide-line): Add docstring. Hide + regexp-filtered lines. + (org-agenda-filter-show-all-tag, org-agenda-filter-show-all-cat): + Add docstring. + (org-agenda-filter-show-all-regexp): New function. + (org-agenda-set-mode-name): Add regexp-filter information. + (org-agenda-custom-commands-local-options): Add regexp filter. + (org-agenda-regexp-filter-preset): New variable. + (org-agenda-prepare): Use the new variable. + + * ox-odt.el (org-odt-code, org-odt-verbatim): Use + `org-odt--encode-plain-text'. + + * ox-html.el (org-html-link): Minor code clean-up. + + * org.el (org-insert-heading): DTRT when in a narrowed region. + + * org-compat.el (org-buffer-narrowed-p): New compatibility + function. + + * ox-html.el (org-html-format-inline-image): Fix missing string in + formatting string. + + * org-agenda.el (org-agenda-skip-scheduled-if-deadline-is-shown): + New allowed value `repeated-after-deadline' which will prevent the + display of scheduled items when repeated after the current + deadline. + (org-agenda-get-scheduled): Handle the new value. + + * org.el (org-time-string-to-absolute): Tiny docstring fix. + + * ox-html.el (org-html-style-default): New classes `footpara' and + `footdef' for the footnotes paragraphs and definitions. + (org-html-format-footnote-definition): Wrap the footnote + defintions into their own div. + (org-html-paragraph): Don't add extra
after a paragraph in a + footnote. + (org-html-container-element, org-html-divs): Mention that + org-info.js will not work when changing the defaults. + + * ox-md.el (md): Export underlined text as verbatim. + + * ox-html.el (org-html-style-default): New CSS .underline and + #org-div-home-and-up. + (org-html-text-markup-alist): Don't hardcode the style, use the + new class .underline. + (org-html-home/up-format): Don't hardcode the style, use + #org-div-home-and-up. + (org-html-center-block): Use the .center class. + + * ox-md.el (org-md-underline): New function. + + * org-agenda.el (org-sorting-choice): Fix default value. + + * ox-html.el (org-html-format-footnote-definition) + (org-html-footnote-section): Don't wrap footnote definitions into + tables. + (org-html-paragraph): Add HTML style and class parameter when the + paragraph is in a footnote definition. Also allow to add an extra + string after the paragraph. Further parameters can be added for + paragraphs in other environments. + (org-html-template): Always include the title as

, even when there is no title, as org-info.js + needs it. + + * org-element.el (org-element-map): Fix tiny typo in docstring. + + * org-agenda.el (org-agenda-day-view): Fix parameter's name. + + * ox-html.el (org-html-format-inline-image): Don't add superfluous +

when there is an empty caption. + + * org-agenda.el (org-agenda-refile): Enhance docstring. Allow to + clear the refile cache with C-0 or C-u C-u C-u. + + * ox-md.el (org-md-export-as-markdown): Tiny docstring fix. Fix a + library keyword in the comment section. + + * org.el (org-toggle-item): Convert all normal lines as items when + there is a region, and only convert the first line when called + with a universal prefix argument. This is consistent with the + behavior of `org-toggle-heading'. + (org-toggle-heading): When the region contains only normal lines, + a universal prefix arg will only convert the first line. This is + more consistent with `org-toggle-item'. + (orgstruct-setup): Add `org-ctrl-c-minus' and `org-ctrl-c-star'. + (customize-package-emacs-version-alist): Update + `customize-package-emacs-version-alist'. + + * ox-texinfo.el (org-export-texinfo) + (org-texinfo-filename, org-texinfo-classes) + (org-texinfo-format-headline-function) + (org-texinfo-node-description-column) + (org-texinfo-active-timestamp-format) + (org-texinfo-link-with-unknown-path-format) + (org-texinfo-tables-verbatim) + (org-texinfo-table-scientific-notation) + (org-texinfo-text-markup-alist) + (org-texinfo-format-drawer-function) + (org-texinfo-format-inlinetask-function) + (org-texinfo-info-process): + * ox-odt.el (org-odt-format-drawer-function) + (org-odt-format-headline-function) + (org-odt-format-inlinetask-function): + * ox-md.el (org-export-md, org-md-headline-style): Fix :version + and :package-version keywords. + + * org.el (org-time-clocksum-use-effort-durations): Don't set to t + by default as it will change many clocktables out there. Let the + user decides whether she wants to turn this on. + + * org.el (org-agenda-inhibit-startup): Revert to nil as the default. + + * org-agenda.el (org-agenda-dim-blocked-tasks): Revert to t as the + default. + + * ox-html.el (org-html-style-default): More cosmetic tweaks. + (org-html-head-include-default-style): Minor docstring update. + + * ox.el (org-export-snippet-translation-alist) + (org-export-coding-system, org-export-in-background) + (org-export-async-init-file, org-export-invisible-backends) + (org-export-dispatch-use-expert-ui): + * ox-texinfo.el (org-texinfo-filename, org-texinfo-classes) + (org-texinfo-format-headline-function) + (org-texinfo-node-description-column) + (org-texinfo-active-timestamp-format) + (org-texinfo-link-with-unknown-path-format) + (org-texinfo-tables-verbatim) + (org-texinfo-table-scientific-notation) + (org-texinfo-text-markup-alist) + (org-texinfo-format-drawer-function) + (org-texinfo-format-inlinetask-function) + (org-texinfo-info-process): + * ox-man.el (org-man-tables-centered) + (org-man-table-scientific-notation) + (org-man-source-highlight, org-man-source-highlight-langs) + (org-man-pdf-process, org-man-logfiles-extensions): + * ox-html.el (org-html-allow-name-attribute-in-anchors) + (org-html-coding-system, org-html-divs): + * ox-ascii.el (org-ascii-text-width) + (org-ascii-headline-spacing, org-ascii-indented-line-width) + (org-ascii-paragraph-spacing, org-ascii-charset) + (org-ascii-underline, org-ascii-bullets) + (org-ascii-links-to-notes) + (org-ascii-table-keep-all-vertical-lines) + (org-ascii-table-widen-columns) + (org-ascii-table-use-ascii-art) + (org-ascii-format-drawer-function) + (org-ascii-format-inlinetask-function): + * org.el (org-modules, org-export-backends) + (org-highlight-latex-and-related, orgstruct-setup-hook): + * org-attach.el (org-attach-git-annex-cutoff): + * org-archive.el (org-archive-file-header-format): + * org-agenda.el (org-agenda-todo-ignore-time-comparison-use-seconds): + * ob-python.el (org-babel-python-hline-to) + (org-babel-python-None-to): + * ob-ditaa.el (org-ditaa-eps-jar-path): + * ob-core.el (org-babel-results-keyword): Add :version and + :package-version. + + * ox-ascii.el: Use utf-8-emacs as the file coding system. + + * org-capture.el (org-capture-templates, org-capture-string) + (org-capture-steal-local-variables) + (org-capture-empty-lines-before) + (org-capture-empty-lines-after) + (org-capture-insert-template-here) + (org-capture-import-remember-templates): Fix or add docstring. + + * ox-html.el (org-html-style-default): Cosmetic changes. + (org-html-postamble, org-html-preamble) + (org-html-preamble-format): Update docstring. + + * org-agenda.el (org-agenda-format-date-aligned) + (org-agenda-time-of-day-to-ampm-maybe) + (org-scheduled-past-days) + (org-agenda-normalize-custom-commands) + (org-agenda-run-series, org-store-agenda-views): Fix or add + docstring. + + * ox-latex.el: + (org-latex-table-scientific-notation, org-latex-verse-block): Fix + typos in docstrings. + + * ox-html.el (org-html-text-markup-alist) + (org-html-pretty-output, org-html-link-org-files-as-html) + (org-html-postamble, org-html-preamble) + (org-html-format-inline-image, org-html-splice-attributes) + (org-export-splice-style, org-html-htmlize-region-for-paste) + (org-html-fix-class-name) + (org-html-format-footnote-reference) + (org-html-format-footnotes-section) + (org-html-footnote-section, org-html--anchor) + (org-html--todo, org-html--tags, org-html-format-headline) + (org-html-toc, org-html-format-section, org-html-checkbox) + (org-html-format-list-item, org-html-format-latex) + (org-html-encode-plain-text) + (org-html-table-first-row-data-cells) + (org-html-table--table.el-table, org-html-final-function): Fix + or add docstring. + + * org.el (org-insert-heading): If the current item has a checkbox, + insert the new item with a checkbox. + + * org.el (org-insert-heading): Don't delete spaces in empty + headlines. + + * ox-odt.el (org-odt-keyword): Fix typo. + + * ox-latex.el (org-latex-toc-command): Cosmetic docstring change. + + * ox-html.el (org-html-encode-plain-text): Fix typo in docstring. + + * org-faces.el (org-column): Update docstring. + + * org-colview.el: Update error message. + + * org.el (org-modules): Do not include org-mew.el, org-vm.el, + org-w3m.el, org-wl.el as these files are now part of contrib/. + + * org-w3m.el: + * org-vm.el: + * org-w3m.el: + * org-wl.el: Delete (moved to Org's contrib/ directory.) + + * org-capture.el (org-mks): Move from org-mks.el. + + * org-mks.el: Delete. + + * ox-html.el (html): Update HTML options names. + + * org.el (org-show-context): Don't try to fix ellipsis when + showing a subtree in agenda. + + * ox-html.el (html): Reintroduce #+HTML_HEAD_EXTRA, previously + known as HTML_STYLE_EXTRA. + (org-html-head): Enhance docstring. + (org-html-head-extra): Reintroduce. Was `org-html-style-extra'. + (org-html--build-head): Rename from `org-html--build-head'. Add + information from `org-html-head-extra'. + (org-html-template): Use `org-html--build-head'. + + * ox-html.el (org-html-display-buffer-mode): Delete. + (org-html-export-as-html): Use `set-auto-mode' instead of + `org-html-display-buffer-mode'. + + * org-agenda.el (org-agenda-write): Overwrite file when called + non-interactively. + + * org-mobile.el (org-mobile-edit): Workaround a + `org-insert-heading-respect-content' bug which prevents correct + insertion when point is invisible + + * org.el (org-previous-line-empty-p): New parameter to allow + checking next line. Add a docstring. + (org-insert-heading): Handle two universal prefix arguments as + advertized in the docstring. Don't insert new lines when + creating a heading after the first heading in the current + subtree. + (org-insert-heading-respect-content): New optional argument + arg, passed to `org-insert-heading'. + + * org.el (org-mode): Remove syntax entries. Use + `org-backward-element' and `org-forward-element' for + `beginning-of-defun-function' and `end-of-defun-function': this + allows using C-M-a and C-M-e before the first headline. + + * ox-html.el (html): Remove :html-htmlized-css-url :options-alist. + + * ox-org.el (org-org-htmlized-css-url): Rename from + `org-html-htmlized-org-css-url' and moved here from ox-html.el. + (org-org-publish-to-org): Handle :htmlized-source in + publishing projects. + + * ox-html.el (org-html-style-default): Update docstring. + (org-html-infojs-install-script, org-html--build-style): Update + property names. + (org-html-head-include-scripts) + (org-html-head-include-default-style, org-html-head): + Respectively rename from `org-html-style-include-scripts', + `org-html-style-include-default' and `org-html-style', now + obsolete. + (org-html-style-extra): Delete. + + * org-clock.el (org-clock-out): Fix bug: if a closing note needs + to be stored in the drawer where clocks are stored, let's + temporarily remove `org-clock-remove-empty-clock-drawer' from + `org-clock-out-hook'. + + * ob-tangle.el (org-babel-tangle): Remove unused attempt of + prompting the user of the tangle file name since :tangle is always + set. Don't prompt for a tangle file name when called with two + universal prefix arg outside of a src block. Use + `org-babel-tangle-single-block'. + (org-babel-tangle-single-block): New function. + (org-babel-tangle-collect-blocks): Use the new function. + + * org-table.el (org-table-convert-region, org-table-export) + (org-table-align, org-table-beginning-of-field) + (org-table-copy-down, org-table-check-inside-data-field) + (org-table-insert-column, org-table-find-dataline) + (org-table-delete-column, org-table-move-column) + (org-table-insert-row, org-table-insert-hline) + (org-table-kill-row, org-table-paste-rectangle) + (org-table-wrap-region, org-table-sum, org-table-get-formula) + (org-table-get-formula, org-table-get-stored-formulas) + (org-table-fix-formulas, org-table-maybe-eval-formula) + (org-table-rotate-recalc-marks, org-table-eval-formula) + (org-table-get-range, org-table-get-descriptor-line) + (org-table-find-row-type, org-table-recalculate) + (org-table-iterate, org-table-iterate-buffer-tables) + (org-table-formula-handle-first/last-rc) + (org-table-edit-formulas, org-table-fedit-shift-reference) + (org-rematch-and-replace, org-table-shift-refpart) + (org-table-fedit-finish, org-table-fedit-lisp-indent) + (org-table-show-reference, org-table-show-reference) + (org-table-show-reference, org-table-show-reference) + (org-table-force-dataline, orgtbl-error, orgtbl-export) + (orgtbl-send-replace-tbl, org-table-to-lisp) + (orgtbl-send-table, orgtbl-send-table, orgtbl-send-table) + (orgtbl-toggle-comment, orgtbl-insert-radio-table) + (orgtbl-to-unicode, org-table-get-remote-range) + (org-table-get-remote-range, org-table-copy-dow) + (org-table-check-inside-data-field, org-table-insert-colum) + (org-table-find-dataline, org-table-delete-colum) + (org-table-move-column, org-table-insert-ro) + (org-table-insert-hline, org-table-kill-ro) + (org-table-paste-rectangle, org-table-wrap-regio) + (org-table-sum, org-table-get-formul) + (org-table-get-stored-formulas, org-table-fix-formula) + (org-table-maybe-eval-formul, org-table-rotate-recalc-marks) + (org-table-eval-formul, org-table-get-range) + (org-table-get-descriptor-lin, org-table-find-row-type) + (org-table-recalculat, org-table-iterate) + (org-table-iterate-buffer-table) + (org-table-formula-handle-first/last-r) + (org-table-edit-formulas, org-table-fedit-shift-referenc) + (org-rematch-and-replace, org-table-shift-refpar) + (org-table-fedit-finish, org-table-fedit-lisp-inden) + (org-table-show-reference, org-table-force-datalin) + (orgtbl-error, orgtbl-export, orgtbl-send-replace-tb) + (org-table-to-lisp, orgtbl-send-tabl, orgtbl-toggle-comment) + (orgtbl-insert-radio-tabl, orgtbl-to-unicode) + (org-table-get-remote-range): Use `user-error' instead of + `error' for user errors. + + * ob-core.el (org-babel-load-in-session): Throw a useful error + when there is no code block at point. + + * ob-tangle.el (org-babel-tangle): Rename the ONLY-THIS-BLOCK + parameter to ARG. Allow two universal prefix arguments to tangle + by the target file of the block at point. + (org-babel-tangle-collect-blocks): New parameter TANGLE-FILE + to restrict the collection of blocks to those who will be + tangled in TARGET-FILE. + + * org-src.el (org-edit-src-auto-save-idle-delay): Use a delay of 0 + by default (i.e., deactivate auto-saving.) + (org-edit-src-code): Set `buffer-auto-save-file-name' for + auto-saving with `auto-save-mode'. + + * org.el (org-deadline, org-schedule): When called with two + universal prefix arguments, set the warning time or the delay + relatively to the current timestamp, not to today's date. + + * org-agenda.el (org-agenda-filter-apply): Deactive + `org-agenda-entry-text-mode' when filtering. + (org-agenda-entry-text-mode): Don't allow in filtered views. + Don't show the maximum number of lines when turning off. + + * ox-html.el (org-html-headline): Add comment. + + * org.el (org-mode): Set `paragraph-start'. + + * org-agenda.el (org-agenda-entry-text-leaders): New option. + (org-agenda-entry-text-show-here): Use it. + + * ox-html.el (org-html-link--inline-image): Always retrieve + attributes for inline images. + (org-html-link): Fix trailing whitespace at the end of the opening + HTML tag. + (org-html-headline): For headlines whose first element is a + headline and not a section, pretend there is an empty section (as + "") for the correct HTML div to be inserted. + + * org-agenda.el (org-agenda-collect-markers) + (org-create-marker-find-array): Move to ox-icalendar.el. + (org-agenda-marker-table, org-check-agenda-marker-table): + Delete. + + * ox-icalendar.el (org-icalendar-create-uid): New parameter + H-MARKERS to only update some headlines, not the whole file. + (org-icalendar--combine-files): When exporting to an .ics file + only add UID to the headlines shown in the agenda buffer. + (org-agenda-collect-markers, org-create-marker-find-array): + Move here. + + * org-agenda.el (org-agenda-write): Ask before overwriting an + existing file. + + * org-pcomplete.el (pcomplete/org-mode/file-option/infojs_opt): + Use `org-html-infojs-opts-table'. + + * ox-html.el (org-html-infojs-opts-table): + (org-html-use-infojs, org-html-infojs-options) + (org-html-infojs-template): Move from ox-jsinfo.el. Rename using + the org-html- prefix. + (org-html-infojs-install-script): Move from ox-infojs.el. + + * ox-infojs.el: Delete. + + * ox-html.el (org-html-section): Fix indentation. + (org-html-inner-template): Add the document title here, within the + "content" class, as the org-info.js needs it. + (org-html-template): Don't include the document's title here. + (org-html-format-inlinetask-function): Remove wrong example. + + * ob-tangle.el (org-babel-tangle-collect-blocks): Don't collect + blocks in commented out headings. + + * ox-latex.el (org-latex-logfiles-extensions) + (org-latex-remove-logfiles): Improve docstrings. + + * org-capture.el (org-capture): Cosmetic fix. + + * org-protocol.el (org-protocol-create-for-org) + (org-protocol-create): Small docstrings enhancements. + + * org-protocol.el (org-protocol-capture): Small docstring fix. + + * org.el (org-speed-command-activate): Only forbid in src code + blocks. + + * org-indent.el + (org-indent-add-properties): Bugfix: prevent negative value for + `added-ind-per-lvl'. + + * org.el (org-mode): Add `org-fix-ellipsis-at-bol' to + `isearch-mode-end-hook' so that any isearch fixes the problem with + ellipsis on the first line. + (org-fix-ellipsis-at-bol): New defsubst. + (org-show-context, org-isearch-end): Use it. + + * org-agenda.el (org-agenda-deadline-leaders): New formatting + string for past deadlines. + (org-agenda-scheduled-leaders): Small change. + (org-agenda-get-deadlines): Use the new formatting string. + + * ob-lob.el (org-babel-lob-execute): Rename cache? to cache-p. + + * org.el (org-speed-command-activate): Don't activate speed + commands within blocks. + + * org.el (org-show-context): Remove useless catch. Make sure the + top of the window is a visible headline. + (org-activate-plain-links): Remove unused catch. + + * org-macs.el (org-get-alist-option): Return nil, not (nil), so + that `org-show-context' DTRT. + + * org.el (org-imenu-get-tree): Fix bug when matching against empty + headlines. + (org-overview): Stay on current line. + (org-map-entries): Fix docstring. + + * org-macs.el (org-unmodified): Update comment. Don't define + `with-silent-modifications' for emacsen that don't have it. + + * org-compat.el (org-with-silent-modifications): New + compatibility macro. + + * org.el (org-refresh-category-properties) + (org-refresh-properties, org-entry-blocked-p) + (org-agenda-prepare-buffers): + + * org-indent.el (org-indent-remove-properties) + (org-indent-add-properties): + + * org-colview.el (org-columns-display-here) + (org-columns-remove-overlays, org-columns-quit) + (org-columns-edit-value, org-columns-compute-all) + (org-columns-compute, org-agenda-colview-compute): + + * org-clock.el (org-clock-sum): Use the compatibility macro + `org-with-silent-modifications' instead of + `with-silent-modifications'. + + * org.el (org-sort-remove-invisible): Remove emphasis markers. + + * org.el (org-sort-remove-invisible): Use defsust. Do not only + check against invisible links, truly returns the visible part of + the string. + (org-sort-remove-invisible): Add a docstring. + (org-sort-entries): Remove hidden links when comparing entries. + + * org-list.el (org-sort-list): Remove hidden links when comparing + list items. + + * ox-html.el (org-html-headline): Fix typo. + (org-html-format-headline--wrap): Cosmetic change. + + * org.el (org-at-clock-log-p): Delete. + + * org-clock.el (org-at-clock-log-p): Move here. + + * ox-html.el (org-html-format-headline-function): Fix docstring. + + * ob-sql.el (org-babel-execute:sql): Add header row delimiter for + both mysql and postgresql. + + * org.el (org-agenda-prepare-buffers): Don't use + `with-silent-modifications' too early. + + * org-macs.el: Add a comment on when to use `org-unmodified' and + when to use `with-silent-modifications'. + + * org-colview.el (org-columns-display-here) + (org-columns-remove-overlays, org-columns-quit) + (org-columns-edit-value, org-columns-compute-all) + (org-columns-compute, org-agenda-colview-compute): + * org-clock.el (org-clock-sum): + * org.el (org-refresh-category-properties) + (org-refresh-properties, org-entry-blocked-p) + (org-agenda-prepare-buffers): Use `with-silent-modifications' + instead of `org-unmodified'. + + * ox-publish.el (org-publish-sitemap-date-format): Small docstring + enhancement. + + * ox-latex.el (org-latex-format-headline-default-function): New + option. + (org-latex-format-headline-function): Use the new option as + the default value. + (org-latex-toc-command): Don't add vertical space after the table + of contents. + + * org.el (org-entry-blocked-p): Use `org-unmodified' instead of + `org-with-buffer-modified-unmodified'. + (org-agenda-prepare-buffers): Fix indentation. + + * org-macs.el (org-unmodified): Rename from + `org-with-buffer-modified-unmodified'. + (org-with-buffer-modified-unmodified): Delete. + + * ob-python.el (org-babel-python-command): Use a defcustom. + (org-babel-python-mode): Use a defcustom and default to + 'python-mode when featured. + + * org-agenda.el (org-agenda-start-day): Refer to `org-read-date' + in the docstring. + + * ox-org.el (org-org-publish-to-org): Autoload. + + * org-protocol.el: + * org-bibtex.el: Remove remember support. + + * org-clock.el (org-clock-heading-for-remember): Delete. + (org-clock-in): Do not set the heading for remember. + + * org.el (org-move-subtree-down, org-forward-element) + (org-backward-element): + + * org-table.el (org-table-previous-field) + (org-table-move-column, org-table-move-row): + + * org-list.el (org-move-item-down, org-move-item-up) + (org-cycle-item-indentation): Use `user-error' when moving or + modifying the element at point is not possible. + + * ox-html.el (org-html-table-header-tags) + (org-html-table-data-tags, org-html-table-row-tags) + (org-html-table-align-individual-fields): Use the + org-export-html group. + (org-html-inline-src-block, org-html-link): Fix error messages. + (org-html-begin-plain-list): Fix formatting, better FIXME + comment. + + * org.el (org-fill-paragraph): Fill using + `org-mode-transpose-word-syntax-table'. + + * ox-org.el (org-org-publish-to-org): New defun. + + * ox-html.el (org-export-htmlize): Delete group. + (org-html-htmlize-output-type) + (org-html-htmlized-org-css-url) + (org-html-htmlize-region-for-paste): Rename from + org-export-htmlize-*. + (org-html-htmlize-generate-css, org-html-fontify-code): Use + the correct names. + + * org-compat.el (org-file-equal-p): New compatibility function. + + * ox.el (org-export-output-file-name): Use the new function. + + * org-clock.el (org-clock-set-current) + (org-clock-delete-current): Delete. + (org-clock-in, org-clock-out): Set and delete + `org-clock-current-task'. Minor code clean-up. + + * org-clock.el (org-clock-in, org-clock-in-last): Tell + `org-current-time' to always return a past time. + + * org.el (org-current-time): New argument `past' to force + returning a past time when rounding. + + * org-agenda.el (org-agenda-unmark-clocking-task): New function. + (org-agenda-mark-clocking-task): Use it. + (org-agenda-clock-in): Let the cursor where it is. + (org-agenda-clock-out): Ditto. Also remove the + `org-agenda-clocking' overlay. + + * org-agenda.el (org-agenda-set-restriction-lock): Fix restriction + so that it ends at the beginning of the next headline at the same + level. + + * org.el (org-set-effort, org-property-next-allowed-value): + When needed, update the current clock effort time. + (org-next-link): New parameter `search-backward'. Fix bug when at + a link with no 'org-link face, e.g., in a DONE headline. Throw a + message instead of an error. + (org-previous-link): Use `org-next-link'. + + * org-agenda.el (org-agenda-format-item): Only set the breadcrumbs + when `org-prefix-has-breadcrumbs' is non-nil. + + * org.el (org-mode): Don't make characters from + `org-emphasis-alist' word constituants. + (org-mode-transpose-word-syntax-table): Rename from + `org-syntax-table'. + (org-transpose-words): Use + `org-mode-transpose-word-syntax-table'. + + * ox.el (org-export--dispatch-ui) + (org-export--dispatch-action): Use integers for control chars. + + * org-agenda.el (org-agenda-set-restriction-lock): Put the + overlay until the end of the subtree, not the end of the + headline. + + * org.el (org-entry-delete, org-delete-property): New optional + arg delete-empty-drawer, a string, to delete any empty drawer + with that name. + (org-toggle-ordered-property): Delete the drawer "PROPERTIES" + if empty. + + * org-src.el (org-src-mode-map, org-edit-src-code) + (org-edit-fixed-width-region, org-edit-src-save): Use C-c C-k + for `org-edit-src-abort'. + + * org.el (org-mode): Use org-unmodified during startup + initialization for functions that may be inhibited. + + * org-table.el (org-table-align): Only set the window start + when table alignment is performed in the selected window. + + * org-src.el (org-edit-src-auto-save-idle-delay): New option. + (org-src-ask-before-returning-to-edit-buffer): Make a defcustom. + (org-edit-src-code-timer): New timer variable. + (org-edit-src-code): Run the timer. + (org-edit-fixed-width-region): Enhance message. + (org-edit-src-exit): Cancel the timer. + (org-edit-src-save): Prevent saving when editing fixed-width + buffer, exiting will save already. + (org-edit-src-exit): Inconditionally kill the src/example + editing buffer. + + * org-pcomplete.el (pcomplete/org-mode/file-option): Require + 'org-element. This fixes a bug about unbound variable + `org-element-affiliated-keywords' when trying to complete a + keyword before 'org-element was required. + + * org-list.el (org-list-bullet-string): Replace match when there + is a match, otherwise just return the bullet. + + * org-src.el (org-src-mode-map): New binding C-c k to abort + editing. + (org-edit-src-code): Mention the keybinding to abort editing + and go back to the correct position. + (org-edit-src-abort): New command to abort editing. + + * ox-html.el (org-html--build-meta-info): Add a newline before + the title meta information. + + * org.el (org-return-follows-link): Mention that this does not + affect the behavior of RET in tables. + + * ox-html.el (org-html--build-mathjax-config): Only include + MathJax configuration if the resulting HTML contains LaTeX + fragments. + + * org.el (org-syntax-table, org-transpose-words): Delete. + (org-mode): Syntactically Define {} and <> as parentheses. + (org-drag-line-forward, org-drag-line-backward): New + functions. + (org-shiftmetaup, org-shiftmetadown): Fall back on the new + functions instead of throwing an error. + (org-make-org-heading-search-string): Don't use statistic or [x/y] + cookies when creating a link. + + * ox-html.el (org-html-table): Append #+attr_html attributes. + + * org.el (org-emphasis-alist, org-protecting-blocks): + * org-src.el (org-edit-src-find-region-and-lang): + * org-list.el (org-list-forbidden-blocks): + * org-footnote.el (org-footnote-forbidden-blocks): Remove + references to the deleted DocBook exporter. + + * org.el (org-end-of-line): Don't throw an error outside elements. + + * ox-html.el (org-html-link): Don't throw an error if the value + of the :ID: property has not been generated by uuidgen. + + * org-pcomplete.el (pcomplete/org-mode/file-option/x): + Resurrect. Use `org-default-options' to initialize completion + fonctions for the most important keywords. + + * org-macs.el (org-default-options): Rename and adapt from + `org-get-current-options'. + + * org.el (org-options-keywords): Add keywords. + + * ox-odt.el (org-odt-convert-read-params): Fix typo in prompt. + + * ox-latex.el (org-latex-horizontal-rule): Fix typo in docstring. + + * ox-html.el (org-html-display-buffer-mode): New option. + (org-html-export-as-html): Use it. + + * ob-core.el (org-babel-insert-result): Fix bug when inserting + an empty string as the result. + + * org.el (org-timestamp-change): New optional parameter + `suppress-tmp-delay' to suppress temporary delay like "--2d". + (org-auto-repeat-maybe): Suppress temporary delays. + + * org-agenda.el (org-agenda-get-scheduled): When the delay is + of the form "--2d" and there is a repeater, ignore the delay + for further repeated occurrences. + + * org-agenda.el (org-agenda-get-deadlines) + (org-agenda-get-scheduled): Minor refactoring. + + * org.el (org-time-string-to-absolute): Tiny docstring enhancement. + (org-edit-special): Don't allow to edit when buffer is read only. + + * ox-html.el (org-html-format-latex): Don't set `cache-relpath' + and `cache-dir' when `processing-type' is 'mathjax. + (org-html-format-latex): Fix conversion in non-file buffers. + + * org.el (org-speed-commands-default): Bind `B' and `F' to + `org-previous-block' and `org-next-block'. + (org-read-date-minibuffer-local-map): Use "!" instead of "?" to + see today's diary as "?" is already bounded by Calendar. + (org-read-date-minibuffer-local-map): Use "." to go to today's + date. + + * ob-core.el (org-babel-next-src-block) + (org-babel-previous-src-block): Rewrite using + `org-next-block'. + + * org.el (org-next-block, org-previous-block): New navigation + commands. + (org-mode-map): Bind the new commands to C-c C-F and C-c C-B + respectively. + + * org-agenda.el (org-agenda-write): Don't copy headlines' subtrees + when writing to an .org file. + + * org.el (org-copy-subtree): New parameter `nosubtrees'. + + * org-agenda.el (org-agenda-write): Allow writing to an .org file. + + * org.el (org-paste-subtree): Fix typo in docstring. + + * org-agenda.el (org-agenda-get-todos) + (org-agenda-get-timestamps): Use nil as `ts-date' for diary + sexpressions. + (org-agenda-get-todos): Skip diary sexps when trying to sort by + timestamp. + (org-agenda-max-entries, org-agenda-max-todos) + (org-agenda-max-tags, org-agenda-max-effort): New options. + (org-timeline, org-agenda-list, org-search-view) + (org-todo-list, org-tags-view): Tell `org-agenda-finalize-entries' + what agenda type we are currently finalizing for. + (org-agenda-finalize-entries): Limit the number of entries + depending on the new options. + (org-agenda-limit-entries): New function. + + * org.el (org-deadline): Allow a double universal prefix argument + to insert/update a warning cookie. + (org-deadline): Allow a double universal prefix argument to + insert/update a delay cookie. + + * org-agenda.el (org-agenda-skip-scheduled-delay-if-deadline): + New option. The structure of the possible values is copied + from `org-agenda-skip-deadline-prewarning-if-scheduled'. + (org-agenda-get-scheduled): Honor the two new option, + `org-scheduled-delay-days' and + `org-agenda-skip-deadline-prewarning-if-scheduled'. I.e. if a + scheduled entry has a delay cookie like "-2d" (similar to the + prewarning cookie for deadline), don't show the entry until + needed. + + * org.el (org-deadline-warning-days): Small docstring fix. + (org-scheduled-delay-days): New option (see + `org-deadline-warning-days'.) + (org-get-wdays): Use the new option. + + * org-agenda.el (org-agenda-sorting-strategy): Document the + new sorting strategies. + (org-agenda-get-todos, org-agenda-get-timestamps) + (org-agenda-get-deadlines, org-agenda-get-scheduled): Add a + `ts-date' text property with scheduled, deadline or timetamp + date. + (org-cmp-ts): New function to compare timestamps. + (org-em): Add a docstring. + (org-entries-lessp): Use `org-cmp-ts' to compare timestamps. + Implement the following sorting strategies: timestamp-up/down, + scheduled-up/down, deadline-up/down, ts-up/down (for active + timestamps) and tsia-up/down (for inactive timestamps.) + + * ob-lilypond.el (ly-process-basic): Bugfix, don't use `pcase'. + + * org.el (org-contextualize-validate-key): Check against two new + context predicates [not-]in-buffer. + + * org-agenda.el (org-agenda-custom-commands-contexts): + Document the new [not-]in-buffer context predicates. + + * ob-core.el (org-ts-regexp): Remove duplicate defconst'ing. + (org-babel-result-regexp): Don't use `org-ts-regexp', use a regexp + string directly. + + * ob-lilypond.el (ly-process-basic): Don't use `ly-gen-png' and + friends, rely on the extension of the output file. + + * org-archive.el (org-archive-file-header-format): New option. + (org-archive-subtree): Use it. + + * ob-lilypond.el (ly-process-basic): Rely on ly-gen-png/pdf/eps to + set the output type. + + * org.el (org-read-date-minibuffer-local-map): New variable. + (org-read-date): Use it. + (org-read-date-minibuffer-setup-hook): Mark as obsolete. + (org-read-date): Bind `!' to `diary-view-entries' in order to + check diary entries while setting an Org date. + + * org-agenda.el (org-diary): Only keep the descriptions of the + links since Org links are not active in the diary buffer. + + * org-faces.el (org-priority): New face. + + * org.el (org-font-lock-add-priority-faces): Use the new face. + + * org-agenda.el (org-agenda-fontify-priorities): Use the + org-priority face and add specific agenda face on top of it. + + * org-agenda.el (org-agenda-show-clocking-issues) + (org-agenda-format-item): Let-bind + `org-time-clocksum-use-effort-durations' to nil. + + * org.el (org-ctrl-c-ctrl-c): Only throw a message when using two + universal prefix arguments on a list where all items are already + in a transitory state. Refine the error when the checkbox cannot + be toggled. + + * org.el ("org-loaddefs.el"): Load org-loaddefs.el before + requiring any org library. Also use `load', not + `org-load-noerror-mustsuffix'. + (org-effort-durations): Move up to fix a compiler warning. + (org-edit-special): Fix typo in docstring. + (org-time-clocksum-format): Add a version tag and add to the + 'org-clock group. + (org-time-clocksum-use-fractional): Ditto. + (org-time-clocksum-use-effort-durations): New option to allow + using `org-effort-durations' when computing clocksum durations. + (org-minutes-to-clocksum-string): Use the new option. + + * org-clock.el (org-clocktable-write-default): Let-bind + `org-time-clocksum-use-effort-durations' to a new clocktable + parameter ":effort-durations". + + * org-entities.el (org-entities): "neg" should be used in LaTeX + math mode. Add the "neg" entity. + + * org-mobile.el (org-mobile-allpriorities): New option. + (org-mobile-create-index-file): Use the new option. + + * org-latex.el (org-export-latex-inline-images): New option. + + * org.el (org-forward-heading-same-level): Before the first + headline, go to the first headline. + (org-backward-heading-same-level): Before the first headline, + go to the beginning of the buffer, like + `outline-previous-visible-heading' does. + + * org-exp.el (org-export-plist-vars): Don't use + `org-export-html-inline-images' to set the :inline-images + property, use distinct properties for the various backends. + + * org-publish.el (org-publish-project-alist): Ditto. + + * org-latex.el (org-export-latex-links): Use :latex-inline-images + instead of :inline-images. + + * org-odt.el (org-compat): Require. + + * org.el (org-parse-time-string): Allow strings supported by + tags/properties matcher (eg , , <-7d>). + + * org-clock.el (org-clock-rounding-minutes): New option to round + the time by N minutes in the past when clocking in or out. + (org-clock-in, org-clock-in-last, org-clock-out): Use the new + option. + + * org.el (org-current-time): New optional parameter + `rounding-minutes' to override the use of + `org-time-stamp-rounding-minutes' for rounding. + + * org-clock.el (org-clock-special-range): Small docstring fix. + New parameter 'weekstart to define the week start day. + (org-clock-special-range, org-dblock-write:clocktable) + (org-dblock-write:clocktable, org-clocktable-write-default) + (org-clocktable-steps, org-clock-get-table-data): Use the new + parameter. + (org-clocktable-defaults): Set monday as the starting day of the + week by setting :wstart to 1. + + * org.el (org-store-link): Fix the naming of internal links to + lines starting with a keyword. + + * org-agenda.el (org-agenda-Quit, org-agenda-quit) + (org-agenda-exit, org-agenda-kill-all-agenda-buffers): + Docstring fixes. + + * org.el (org-last-set-property-value): New variable. + (org-read-property-name): Fix dangling parentheses. + (org-set-property-and-value): New command to manually set + both the property and the value. A prefix arg will use the + last property-value pair set without prompting the user. + (org-set-property): Set `org-last-set-property-value'. + (org-mode-map): Bind the new command to `C-c C-x P'. + (org-find-invisible-foreground): Delete. + (org-mode): Use `face-background' instead of + `org-find-invisible-foreground'. + (org-startup-options): New startup keywords. + (org-log-into-drawer): Update docstring to explain how to set this + variable through the startup keyword "logdrawer" and "nologdrawer". + (org-log-states-order-reversed): Document the new startup keywords + "logstatesreversed" and "nologstatesreversed". + (org-mode-map): Use `org-remap' instead of binding `M-t' to + `org-transpose-words' directly. + (org-syntax-table): New variable. + (org-transpose-words): New command, simply wrapping the new + syntax table around `transpose-words'. + (org-mode-map): Bind `org-transpose-words' to `M-t'. + (org-store-link): Use keyword at point as the search string. Use + `delq nil' instead of `delete nil'. + (org-make-org-heading-search-string): Rewrite using + org-element.el. Not an interactive function anymore. + + * org-pcomplete.el (pcomplete/org-mode/drawer): Ditto. + + * org-mobile.el (org-mobile-files-alist): Ditto. + + * org.el (org-store-link): When creating a link to a heading with + a bracket link, don't escape this link with curly braces as the + escaped link is not active anyway; use the description instead. + If the headline only consists of a bracket link, add a star to the + description so that the user knows this is an internal link. + + * org-w3m.el (org-w3m-store-link): New function. + + * org.el (org-store-link): Update the error message when no method + is available for storing a link. Use `user-error' for this. + Remove handling w3m links from this function. + (org-insert-heading, org-insert-todo-heading): A double prefix arg + force the insertion of the subtree at the end of the parent + subtree. + (org-store-link): A double prefix argument now skips module + store-link functions to only use Org's core functions. Also, when + several modular store-link functions match, ask for which one to + use. + (org-cycle, org-cycle-internal-global) + (org-cycle-internal-local, org-display-outline-path): Let-bind + `message-log-max' to nil so that messages don't populate the + *Messages* buffer. + + * org-table.el (org-table-eval-formula): Handle localized + time-stamps by internally converting them to english during + formulas evaluation. + + * org.el (org-clock-timestamps-up): Fix declarations. + + * ob-core.el (org-split-string): Declare function. + + * org-html.el (org-html-export-list-line): Add CSS classes to + these list HTML tags:
") + ;; ID. + (if (not (org-string-nw-p label)) "" + (format " id=\"%s\"" (org-export-solidify-link-text label))) + ;; Contents. + (format "\n

%s

" contents) + ;; Caption. + (if (not (org-string-nw-p caption)) "" + (format (if html5-fancy "\n
%s
" + "\n

%s

") + caption))))) + +(defun org-html--format-image (source attributes info) + "Return \"img\" tag with given SOURCE and ATTRIBUTES. +SOURCE is a string specifying the location of the image. +ATTRIBUTES is a plist, as returned by +`org-export-read-attribute'. INFO is a plist used as +a communication channel." + (org-html-close-tag + "img" + (org-html--make-attribute-string + (org-combine-plists + (list :src source + :alt (if (string-match-p "^ltxpng/" source) + (org-html-encode-plain-text + (org-find-text-property-in-string 'org-latex-src source)) + (file-name-nondirectory source))) + attributes)) + info)) + +(defun org-html--textarea-block (element) + "Transcode ELEMENT into a textarea block. +ELEMENT is either a src block or an example block." + (let* ((code (car (org-export-unravel-code element))) + (attr (org-export-read-attribute :attr_html element))) + (format "

\n\n

" + (or (plist-get attr :width) 80) + (or (plist-get attr :height) (org-count-lines code)) + code))) + +(defun org-html--has-caption-p (element &optional info) + "Non-nil when ELEMENT has a caption affiliated keyword. +INFO is a plist used as a communication channel. This function +is meant to be used as a predicate for `org-export-get-ordinal' or +a value to `org-html-standalone-image-predicate'." + (org-element-property :caption element)) + +;;;; Table + +(defun org-html-htmlize-region-for-paste (beg end) + "Convert the region between BEG and END to HTML, using htmlize.el. +This is much like `htmlize-region-for-paste', only that it uses +the settings define in the org-... variables." + (let* ((htmlize-output-type org-html-htmlize-output-type) + (htmlize-css-name-prefix org-html-htmlize-font-prefix) + (htmlbuf (htmlize-region beg end))) + (unwind-protect + (with-current-buffer htmlbuf + (buffer-substring (plist-get htmlize-buffer-places 'content-start) + (plist-get htmlize-buffer-places 'content-end))) + (kill-buffer htmlbuf)))) + +;;;###autoload +(defun org-html-htmlize-generate-css () + "Create the CSS for all font definitions in the current Emacs session. +Use this to create face definitions in your CSS style file that can then +be used by code snippets transformed by htmlize. +This command just produces a buffer that contains class definitions for all +faces used in the current Emacs session. You can copy and paste the ones you +need into your CSS file. + +If you then set `org-html-htmlize-output-type' to `css', calls +to the function `org-html-htmlize-region-for-paste' will +produce code that uses these same face definitions." + (interactive) + (require 'htmlize) + (and (get-buffer "*html*") (kill-buffer "*html*")) + (with-temp-buffer + (let ((fl (face-list)) + (htmlize-css-name-prefix "org-") + (htmlize-output-type 'css) + f i) + (while (setq f (pop fl) + i (and f (face-attribute f :inherit))) + (when (and (symbolp f) (or (not i) (not (listp i)))) + (insert (org-add-props (copy-sequence "1") nil 'face f)))) + (htmlize-region (point-min) (point-max)))) + (org-pop-to-buffer-same-window "*html*") + (goto-char (point-min)) + (if (re-search-forward "" nil t) + (delete-region (1+ (match-end 0)) (point-max))) + (beginning-of-line 1) + (if (looking-at " +") (replace-match "")) + (goto-char (point-min))) + +(defun org-html--make-string (n string) + "Build a string by concatenating N times STRING." + (let (out) (dotimes (i n out) (setq out (concat string out))))) + +(defun org-html-fix-class-name (kwd) ; audit callers of this function + "Turn todo keyword KWD into a valid class name. +Replaces invalid characters with \"_\"." + (save-match-data + (while (string-match "[^a-zA-Z0-9_]" kwd) + (setq kwd (replace-match "_" t t kwd)))) + kwd) + +(defun org-html-format-footnote-reference (n def refcnt) + "Format footnote reference N with definition DEF into HTML." + (let ((extra (if (= refcnt 1) "" (format ".%d" refcnt)))) + (format org-html-footnote-format + (let* ((id (format "fnr.%s%s" n extra)) + (href (format " href=\"#fn.%s\"" n)) + (attributes (concat " class=\"footref\"" href))) + (org-html--anchor id n attributes))))) + +(defun org-html-format-footnotes-section (section-name definitions) + "Format footnotes section SECTION-NAME." + (if (not definitions) "" + (format org-html-footnotes-section section-name definitions))) + +(defun org-html-format-footnote-definition (fn) + "Format the footnote definition FN." + (let ((n (car fn)) (def (cdr fn))) + (format + "
%s %s
\n" + (format org-html-footnote-format + (let* ((id (format "fn.%s" n)) + (href (format " href=\"#fnr.%s\"" n)) + (attributes (concat " class=\"footnum\"" href))) + (org-html--anchor id n attributes))) + def))) + +(defun org-html-footnote-section (info) + "Format the footnote section. +INFO is a plist used as a communication channel." + (let* ((fn-alist (org-export-collect-footnote-definitions + (plist-get info :parse-tree) info)) + (fn-alist + (loop for (n type raw) in fn-alist collect + (cons n (if (eq (org-element-type raw) 'org-data) + (org-trim (org-export-data raw info)) + (format "

%s

" + (org-trim (org-export-data raw info)))))))) + (when fn-alist + (org-html-format-footnotes-section + (org-html--translate "Footnotes" info) + (format + "\n%s\n" + (mapconcat 'org-html-format-footnote-definition fn-alist "\n")))))) + + +;;; Template + +(defun org-html--build-meta-info (info) + "Return meta tags for exported document. +INFO is a plist used as a communication channel." + (let ((protect-string + (lambda (str) + (replace-regexp-in-string + "\"" """ (org-html-encode-plain-text str)))) + (title (org-export-data (plist-get info :title) info)) + (author (and (plist-get info :with-author) + (let ((auth (plist-get info :author))) + (and auth + ;; Return raw Org syntax, skipping non + ;; exportable objects. + (org-element-interpret-data + (org-element-map auth + (cons 'plain-text org-element-all-objects) + 'identity info)))))) + (description (plist-get info :description)) + (keywords (plist-get info :keywords)) + (charset (or (and org-html-coding-system + (fboundp 'coding-system-get) + (coding-system-get org-html-coding-system + 'mime-charset)) + "iso-8859-1"))) + (concat + (format "%s\n" title) + (when (plist-get info :time-stamp-file) + (format-time-string + (concat "\n"))) + (format + (if (org-html-html5-p info) + (org-html-close-tag "meta" " charset=\"%s\"" info) + (org-html-close-tag + "meta" " http-equiv=\"Content-Type\" content=\"text/html;charset=%s\"" + info)) + charset) "\n" + (org-html-close-tag "meta" " name=\"generator\" content=\"Org-mode\"" info) + "\n" + (and (org-string-nw-p author) + (concat + (org-html-close-tag "meta" + (format " name=\"author\" content=\"%s\"" + (funcall protect-string author)) + info) + "\n")) + (and (org-string-nw-p description) + (concat + (org-html-close-tag "meta" + (format " name=\"description\" content=\"%s\"\n" + (funcall protect-string description)) + info) + "\n")) + (and (org-string-nw-p keywords) + (concat + (org-html-close-tag "meta" + (format " name=\"keywords\" content=\"%s\"" + (funcall protect-string keywords)) + info) + "\n"))))) + +(defun org-html--build-head (info) + "Return information for the .. of the HTML output. +INFO is a plist used as a communication channel." + (org-element-normalize-string + (concat + (when (plist-get info :html-head-include-default-style) + (org-element-normalize-string org-html-style-default)) + (org-element-normalize-string (plist-get info :html-head)) + (org-element-normalize-string (plist-get info :html-head-extra)) + (when (and (plist-get info :html-htmlized-css-url) + (eq org-html-htmlize-output-type 'css)) + (org-html-close-tag "link" + (format " rel=\"stylesheet\" href=\"%s\" type=\"text/css\"" + (plist-get info :html-htmlized-css-url)) + info)) + (when (plist-get info :html-head-include-scripts) org-html-scripts)))) + +(defun org-html--build-mathjax-config (info) + "Insert the user setup into the mathjax template. +INFO is a plist used as a communication channel." + (when (and (memq (plist-get info :with-latex) '(mathjax t)) + (org-element-map (plist-get info :parse-tree) + '(latex-fragment latex-environment) 'identity info t)) + (let ((template org-html-mathjax-template) + (options org-html-mathjax-options) + (in-buffer (or (plist-get info :html-mathjax) "")) + name val (yes " ") (no "// ") x) + (mapc + (lambda (e) + (setq name (car e) val (nth 1 e)) + (if (string-match (concat "\\<" (symbol-name name) ":") in-buffer) + (setq val (car (read-from-string + (substring in-buffer (match-end 0)))))) + (if (not (stringp val)) (setq val (format "%s" val))) + (if (string-match (concat "%" (upcase (symbol-name name))) template) + (setq template (replace-match val t t template)))) + options) + (setq val (nth 1 (assq 'mathml options))) + (if (string-match (concat "\\%s" e e)) + (split-string (plist-get info :email) ",+ *") + ", ")) + (?c . ,(plist-get info :creator)) + (?C . ,(let ((file (plist-get info :input-file))) + (format-time-string org-html-metadata-timestamp-format + (if file (nth 5 (file-attributes file)) + (current-time))))) + (?v . ,(or org-html-validation-link "")))) + +(defun org-html--build-pre/postamble (type info) + "Return document preamble or postamble as a string, or nil. +TYPE is either 'preamble or 'postamble, INFO is a plist used as a +communication channel." + (let ((section (plist-get info (intern (format ":html-%s" type)))) + (spec (org-html-format-spec info))) + (when section + (let ((section-contents + (if (functionp section) (funcall section info) + (cond + ((stringp section) (format-spec section spec)) + ((eq section 'auto) + (let ((date (cdr (assq ?d spec))) + (author (cdr (assq ?a spec))) + (email (cdr (assq ?e spec))) + (creator (cdr (assq ?c spec))) + (timestamp (cdr (assq ?T spec))) + (validation-link (cdr (assq ?v spec)))) + (concat + (when (and (plist-get info :with-date) + (org-string-nw-p date)) + (format "

%s: %s

\n" + (org-html--translate "Date" info) + date)) + (when (and (plist-get info :with-author) + (org-string-nw-p author)) + (format "

%s: %s

\n" + (org-html--translate "Author" info) + author)) + (when (and (plist-get info :with-email) + (org-string-nw-p email)) + (format "

%s: %s

\n" + (org-html--translate "Email" info) + email)) + (when (plist-get info :time-stamp-file) + (format + "

%s: %s

\n" + (org-html--translate "Created" info) + (format-time-string org-html-metadata-timestamp-format))) + (when (plist-get info :with-creator) + (format "

%s

\n" creator)) + (format "

%s

\n" + validation-link)))) + (t (format-spec + (or (cadr (assoc + (plist-get info :language) + (eval (intern + (format "org-html-%s-format" type))))) + (cadr + (assoc + "en" + (eval + (intern (format "org-html-%s-format" type)))))) + spec)))))) + (when (org-string-nw-p section-contents) + (concat + (format "<%s id=\"%s\" class=\"%s\">\n" + (nth 1 (assq type org-html-divs)) + (nth 2 (assq type org-html-divs)) + org-html--pre/postamble-class) + (org-element-normalize-string section-contents) + (format "\n" (nth 1 (assq type org-html-divs))))))))) + +(defun org-html-inner-template (contents info) + "Return body of document string after HTML conversion. +CONTENTS is the transcoded contents string. INFO is a plist +holding export options." + (concat + ;; Table of contents. + (let ((depth (plist-get info :with-toc))) + (when depth (org-html-toc depth info))) + ;; Document contents. + contents + ;; Footnotes section. + (org-html-footnote-section info))) + +(defun org-html-template (contents info) + "Return complete document string after HTML conversion. +CONTENTS is the transcoded contents string. INFO is a plist +holding export options." + (concat + (when (and (not (org-html-html5-p info)) (org-html-xhtml-p info)) + (let ((decl (or (and (stringp org-html-xml-declaration) + org-html-xml-declaration) + (cdr (assoc (plist-get info :html-extension) + org-html-xml-declaration)) + (cdr (assoc "html" org-html-xml-declaration)) + + ""))) + (when (not (or (eq nil decl) (string= "" decl))) + (format "%s\n" + (format decl + (or (and org-html-coding-system + (fboundp 'coding-system-get) + (coding-system-get org-html-coding-system 'mime-charset)) + "iso-8859-1")))))) + (org-html-doctype info) + "\n" + (concat "\n") + "\n" + (org-html--build-meta-info info) + (org-html--build-head info) + (org-html--build-mathjax-config info) + "\n" + "\n" + (let ((link-up (org-trim (plist-get info :html-link-up))) + (link-home (org-trim (plist-get info :html-link-home)))) + (unless (and (string= link-up "") (string= link-home "")) + (format org-html-home/up-format + (or link-up link-home) + (or link-home link-up)))) + ;; Preamble. + (org-html--build-pre/postamble 'preamble info) + ;; Document contents. + (format "<%s id=\"%s\">\n" + (nth 1 (assq 'content org-html-divs)) + (nth 2 (assq 'content org-html-divs))) + ;; Document title. + (let ((title (plist-get info :title))) + (format "

%s

\n" (org-export-data (or title "") info))) + contents + (format "\n" + (nth 1 (assq 'content org-html-divs))) + ;; Postamble. + (org-html--build-pre/postamble 'postamble info) + ;; Closing document. + "\n")) + +(defun org-html--translate (s info) + "Translate string S according to specified language. +INFO is a plist used as a communication channel." + (org-export-translate s :html info)) + +;;;; Anchor + +(defun org-html--anchor (&optional id desc attributes) + "Format a HTML anchor." + (let* ((name (and org-html-allow-name-attribute-in-anchors id)) + (attributes (concat (and id (format " id=\"%s\"" id)) + (and name (format " name=\"%s\"" name)) + attributes))) + (format "%s" attributes (or desc "")))) + +;;;; Todo + +(defun org-html--todo (todo) + "Format TODO keywords into HTML." + (when todo + (format "%s" + (if (member todo org-done-keywords) "done" "todo") + org-html-todo-kwd-class-prefix (org-html-fix-class-name todo) + todo))) + +;;;; Tags + +(defun org-html--tags (tags) + "Format TAGS into HTML." + (when tags + (format "%s" + (mapconcat + (lambda (tag) + (format "%s" + (concat org-html-tag-class-prefix + (org-html-fix-class-name tag)) + tag)) + tags " ")))) + +;;;; Headline + +(defun* org-html-format-headline + (todo todo-type priority text tags + &key level section-number headline-label &allow-other-keys) + "Format a headline in HTML." + (let ((section-number + (when section-number + (format "%s " + level section-number))) + (todo (org-html--todo todo)) + (tags (org-html--tags tags))) + (concat section-number todo (and todo " ") text + (and tags "   ") tags))) + +;;;; Src Code + +(defun org-html-fontify-code (code lang) + "Color CODE with htmlize library. +CODE is a string representing the source code to colorize. LANG +is the language used for CODE, as a string, or nil." + (when code + (cond + ;; Case 1: No lang. Possibly an example block. + ((not lang) + ;; Simple transcoding. + (org-html-encode-plain-text code)) + ;; Case 2: No htmlize or an inferior version of htmlize + ((not (and (require 'htmlize nil t) (fboundp 'htmlize-region-for-paste))) + ;; Emit a warning. + (message "Cannot fontify src block (htmlize.el >= 1.34 required)") + ;; Simple transcoding. + (org-html-encode-plain-text code)) + (t + ;; Map language + (setq lang (or (assoc-default lang org-src-lang-modes) lang)) + (let* ((lang-mode (and lang (intern (format "%s-mode" lang))))) + (cond + ;; Case 1: Language is not associated with any Emacs mode + ((not (functionp lang-mode)) + ;; Simple transcoding. + (org-html-encode-plain-text code)) + ;; Case 2: Default. Fontify code. + (t + ;; htmlize + (setq code (with-temp-buffer + ;; Switch to language-specific mode. + (funcall lang-mode) + (insert code) + ;; Fontify buffer. + (font-lock-fontify-buffer) + ;; Remove formatting on newline characters. + (save-excursion + (let ((beg (point-min)) + (end (point-max))) + (goto-char beg) + (while (progn (end-of-line) (< (point) end)) + (put-text-property (point) (1+ (point)) 'face nil) + (forward-char 1)))) + (org-src-mode) + (set-buffer-modified-p nil) + ;; Htmlize region. + (org-html-htmlize-region-for-paste + (point-min) (point-max)))) + ;; Strip any enclosing
 tags.
+	  (let* ((beg (and (string-match "\\`]*>\n*" code) (match-end 0)))
+		 (end (and beg (string-match "\\'" code))))
+	    (if (and beg end) (substring code beg end) code)))))))))
+
+(defun org-html-do-format-code
+  (code &optional lang refs retain-labels num-start)
+  "Format CODE string as source code.
+Optional arguments LANG, REFS, RETAIN-LABELS and NUM-START are,
+respectively, the language of the source code, as a string, an
+alist between line numbers and references (as returned by
+`org-export-unravel-code'), a boolean specifying if labels should
+appear in the source code, and the number associated to the first
+line of code."
+  (let* ((code-lines (org-split-string code "\n"))
+	 (code-length (length code-lines))
+	 (num-fmt
+	  (and num-start
+	       (format "%%%ds: "
+		       (length (number-to-string (+ code-length num-start))))))
+	 (code (org-html-fontify-code code lang)))
+    (org-export-format-code
+     code
+     (lambda (loc line-num ref)
+       (setq loc
+	     (concat
+	      ;; Add line number, if needed.
+	      (when num-start
+		(format "%s"
+			(format num-fmt line-num)))
+	      ;; Transcoded src line.
+	      loc
+	      ;; Add label, if needed.
+	      (when (and ref retain-labels) (format " (%s)" ref))))
+       ;; Mark transcoded line as an anchor, if needed.
+       (if (not ref) loc
+	 (format "%s"
+		 ref loc)))
+     num-start refs)))
+
+(defun org-html-format-code (element info)
+  "Format contents of ELEMENT as source code.
+ELEMENT is either an example block or a src block.  INFO is
+a plist used as a communication channel."
+  (let* ((lang (org-element-property :language element))
+	 ;; Extract code and references.
+	 (code-info (org-export-unravel-code element))
+	 (code (car code-info))
+	 (refs (cdr code-info))
+	 ;; Does the src block contain labels?
+	 (retain-labels (org-element-property :retain-labels element))
+	 ;; Does it have line numbers?
+	 (num-start (case (org-element-property :number-lines element)
+		      (continued (org-export-get-loc element info))
+		      (new 0))))
+    (org-html-do-format-code code lang refs retain-labels num-start)))
+
+
+;;; Tables of Contents
+
+(defun org-html-toc (depth info)
+  "Build a table of contents.
+DEPTH is an integer specifying the depth of the table.  INFO is a
+plist used as a communication channel.  Return the table of
+contents as a string, or nil if it is empty."
+  (let ((toc-entries
+	 (mapcar (lambda (headline)
+		   (cons (org-html--format-toc-headline headline info)
+			 (org-export-get-relative-level headline info)))
+		 (org-export-collect-headlines info depth)))
+	(outer-tag (if (and (org-html-html5-p info)
+			    (plist-get info :html-html5-fancy))
+		       "nav"
+		     "div")))
+    (when toc-entries
+      (concat (format "<%s id=\"table-of-contents\">\n" outer-tag)
+	      (format "%s\n"
+		      org-html-toplevel-hlevel
+		      (org-html--translate "Table of Contents" info)
+		      org-html-toplevel-hlevel)
+	      "
" + (org-html--toc-text toc-entries) + "
\n" + (format "\n" outer-tag))))) + +(defun org-html--toc-text (toc-entries) + "Return innards of a table of contents, as a string. +TOC-ENTRIES is an alist where key is an entry title, as a string, +and value is its relative level, as an integer." + (let* ((prev-level (1- (cdar toc-entries))) + (start-level prev-level)) + (concat + (mapconcat + (lambda (entry) + (let ((headline (car entry)) + (level (cdr entry))) + (concat + (let* ((cnt (- level prev-level)) + (times (if (> cnt 0) (1- cnt) (- cnt))) + rtn) + (setq prev-level level) + (concat + (org-html--make-string + times (cond ((> cnt 0) "\n
    \n
  • ") + ((< cnt 0) "
  • \n
\n"))) + (if (> cnt 0) "\n
    \n
  • " "
  • \n
  • "))) + headline))) + toc-entries "") + (org-html--make-string (- prev-level start-level) "
  • \n
\n")))) + +(defun org-html--format-toc-headline (headline info) + "Return an appropriate table of contents entry for HEADLINE. +INFO is a plist used as a communication channel." + (let* ((todo (and (plist-get info :with-todo-keywords) + (let ((todo (org-element-property :todo-keyword headline))) + (and todo (org-export-data todo info))))) + (todo-type (and todo (org-element-property :todo-type headline))) + (priority (and (plist-get info :with-priority) + (org-element-property :priority headline))) + (text (org-export-data-with-backend + (org-export-get-alt-title headline info) + ;; Create an anonymous back-end that will ignore any + ;; footnote-reference, link, radio-target and target + ;; in table of contents. + (org-export-create-backend + :parent 'html + :transcoders '((footnote-reference . ignore) + (link . (lambda (object c i) c)) + (radio-target . (lambda (object c i) c)) + (target . ignore))) + info)) + (tags (and (eq (plist-get info :with-tags) t) + (org-export-get-tags headline info)))) + (format "%s" + (org-export-solidify-link-text + (or (org-element-property :CUSTOM_ID headline) + (concat "sec-" + (mapconcat + #'number-to-string + (org-export-get-headline-number headline info) + "-")))) + (apply (if (functionp org-html-format-headline-function) + (lambda (todo todo-type priority text tags &rest ignore) + (funcall org-html-format-headline-function + todo todo-type priority text tags)) + #'org-html-format-headline) + todo todo-type priority text tags :section-number nil)))) + +(defun org-html-list-of-listings (info) + "Build a list of listings. +INFO is a plist used as a communication channel. Return the list +of listings as a string, or nil if it is empty." + (let ((lol-entries (org-export-collect-listings info))) + (when lol-entries + (concat "
\n" + (format "%s\n" + org-html-toplevel-hlevel + (org-html--translate "List of Listings" info) + org-html-toplevel-hlevel) + "
\n
    \n" + (let ((count 0) + (initial-fmt (format "%s" + (org-html--translate "Listing %d:" info)))) + (mapconcat + (lambda (entry) + (let ((label (org-element-property :name entry)) + (title (org-trim + (org-export-data + (or (org-export-get-caption entry t) + (org-export-get-caption entry)) + info)))) + (concat + "
  • " + (if (not label) + (concat (format initial-fmt (incf count)) " " title) + (format "%s %s" + (org-export-solidify-link-text label) + (format initial-fmt (incf count)) + title)) + "
  • "))) + lol-entries "\n")) + "\n
\n
\n
")))) + +(defun org-html-list-of-tables (info) + "Build a list of tables. +INFO is a plist used as a communication channel. Return the list +of tables as a string, or nil if it is empty." + (let ((lol-entries (org-export-collect-tables info))) + (when lol-entries + (concat "
\n" + (format "%s\n" + org-html-toplevel-hlevel + (org-html--translate "List of Tables" info) + org-html-toplevel-hlevel) + "
\n
    \n" + (let ((count 0) + (initial-fmt (format "%s" + (org-html--translate "Table %d:" info)))) + (mapconcat + (lambda (entry) + (let ((label (org-element-property :name entry)) + (title (org-trim + (org-export-data + (or (org-export-get-caption entry t) + (org-export-get-caption entry)) + info)))) + (concat + "
  • " + (if (not label) + (concat (format initial-fmt (incf count)) " " title) + (format "%s %s" + (org-export-solidify-link-text label) + (format initial-fmt (incf count)) + title)) + "
  • "))) + lol-entries "\n")) + "\n
\n
\n
")))) + + +;;; Transcode Functions + +;;;; Bold + +(defun org-html-bold (bold contents info) + "Transcode BOLD from Org to HTML. +CONTENTS is the text with bold markup. INFO is a plist holding +contextual information." + (format (or (cdr (assq 'bold org-html-text-markup-alist)) "%s") + contents)) + +;;;; Center Block + +(defun org-html-center-block (center-block contents info) + "Transcode a CENTER-BLOCK element from Org to HTML. +CONTENTS holds the contents of the block. INFO is a plist +holding contextual information." + (format "
\n%s
" contents)) + +;;;; Clock + +(defun org-html-clock (clock contents info) + "Transcode a CLOCK element from Org to HTML. +CONTENTS is nil. INFO is a plist used as a communication +channel." + (format "

+ +%s %s%s + +

" + org-clock-string + (org-translate-time + (org-element-property :raw-value + (org-element-property :value clock))) + (let ((time (org-element-property :duration clock))) + (and time (format " (%s)" time))))) + +;;;; Code + +(defun org-html-code (code contents info) + "Transcode CODE from Org to HTML. +CONTENTS is nil. INFO is a plist holding contextual +information." + (format (or (cdr (assq 'code org-html-text-markup-alist)) "%s") + (org-html-encode-plain-text (org-element-property :value code)))) + +;;;; Drawer + +(defun org-html-drawer (drawer contents info) + "Transcode a DRAWER element from Org to HTML. +CONTENTS holds the contents of the block. INFO is a plist +holding contextual information." + (if (functionp org-html-format-drawer-function) + (funcall org-html-format-drawer-function + (org-element-property :drawer-name drawer) + contents) + ;; If there's no user defined function: simply + ;; display contents of the drawer. + contents)) + +;;;; Dynamic Block + +(defun org-html-dynamic-block (dynamic-block contents info) + "Transcode a DYNAMIC-BLOCK element from Org to HTML. +CONTENTS holds the contents of the block. INFO is a plist +holding contextual information. See `org-export-data'." + contents) + +;;;; Entity + +(defun org-html-entity (entity contents info) + "Transcode an ENTITY object from Org to HTML. +CONTENTS are the definition itself. INFO is a plist holding +contextual information." + (org-element-property :html entity)) + +;;;; Example Block + +(defun org-html-example-block (example-block contents info) + "Transcode a EXAMPLE-BLOCK element from Org to HTML. +CONTENTS is nil. INFO is a plist holding contextual +information." + (if (org-export-read-attribute :attr_html example-block :textarea) + (org-html--textarea-block example-block) + (format "
\n%s
" + (org-html-format-code example-block info)))) + +;;;; Export Snippet + +(defun org-html-export-snippet (export-snippet contents info) + "Transcode a EXPORT-SNIPPET object from Org to HTML. +CONTENTS is nil. INFO is a plist holding contextual +information." + (when (eq (org-export-snippet-backend export-snippet) 'html) + (org-element-property :value export-snippet))) + +;;;; Export Block + +(defun org-html-export-block (export-block contents info) + "Transcode a EXPORT-BLOCK element from Org to HTML. +CONTENTS is nil. INFO is a plist holding contextual information." + (when (string= (org-element-property :type export-block) "HTML") + (org-remove-indentation (org-element-property :value export-block)))) + +;;;; Fixed Width + +(defun org-html-fixed-width (fixed-width contents info) + "Transcode a FIXED-WIDTH element from Org to HTML. +CONTENTS is nil. INFO is a plist holding contextual information." + (format "
\n%s
" + (org-html-do-format-code + (org-remove-indentation + (org-element-property :value fixed-width))))) + +;;;; Footnote Reference + +(defun org-html-footnote-reference (footnote-reference contents info) + "Transcode a FOOTNOTE-REFERENCE element from Org to HTML. +CONTENTS is nil. INFO is a plist holding contextual information." + (concat + ;; Insert separator between two footnotes in a row. + (let ((prev (org-export-get-previous-element footnote-reference info))) + (when (eq (org-element-type prev) 'footnote-reference) + org-html-footnote-separator)) + (cond + ((not (org-export-footnote-first-reference-p footnote-reference info)) + (org-html-format-footnote-reference + (org-export-get-footnote-number footnote-reference info) + "IGNORED" 100)) + ;; Inline definitions are secondary strings. + ((eq (org-element-property :type footnote-reference) 'inline) + (org-html-format-footnote-reference + (org-export-get-footnote-number footnote-reference info) + "IGNORED" 1)) + ;; Non-inline footnotes definitions are full Org data. + (t (org-html-format-footnote-reference + (org-export-get-footnote-number footnote-reference info) + "IGNORED" 1))))) + +;;;; Headline + +(defun org-html-format-headline--wrap + (headline info &optional format-function &rest extra-keys) + "Transcode a HEADLINE element from Org to HTML. +CONTENTS holds the contents of the headline. INFO is a plist +holding contextual information." + (let* ((level (+ (org-export-get-relative-level headline info) + (1- org-html-toplevel-hlevel))) + (headline-number (org-export-get-headline-number headline info)) + (section-number (and (not (org-export-low-level-p headline info)) + (org-export-numbered-headline-p headline info) + (mapconcat 'number-to-string + headline-number "."))) + (todo (and (plist-get info :with-todo-keywords) + (let ((todo (org-element-property :todo-keyword headline))) + (and todo (org-export-data todo info))))) + (todo-type (and todo (org-element-property :todo-type headline))) + (priority (and (plist-get info :with-priority) + (org-element-property :priority headline))) + (text (org-export-data (org-element-property :title headline) info)) + (tags (and (plist-get info :with-tags) + (org-export-get-tags headline info))) + (headline-label (or (org-element-property :CUSTOM_ID headline) + (concat "sec-" (mapconcat 'number-to-string + headline-number "-")))) + (format-function + (cond ((functionp format-function) format-function) + ((functionp org-html-format-headline-function) + (lambda (todo todo-type priority text tags &rest ignore) + (funcall org-html-format-headline-function + todo todo-type priority text tags))) + (t 'org-html-format-headline)))) + (apply format-function + todo todo-type priority text tags + :headline-label headline-label :level level + :section-number section-number extra-keys))) + +(defun org-html-headline (headline contents info) + "Transcode a HEADLINE element from Org to HTML. +CONTENTS holds the contents of the headline. INFO is a plist +holding contextual information." + ;; Empty contents? + (setq contents (or contents "")) + (let* ((numberedp (org-export-numbered-headline-p headline info)) + (level (org-export-get-relative-level headline info)) + (text (org-export-data (org-element-property :title headline) info)) + (todo (and (plist-get info :with-todo-keywords) + (let ((todo (org-element-property :todo-keyword headline))) + (and todo (org-export-data todo info))))) + (todo-type (and todo (org-element-property :todo-type headline))) + (tags (and (plist-get info :with-tags) + (org-export-get-tags headline info))) + (priority (and (plist-get info :with-priority) + (org-element-property :priority headline))) + (section-number (and (org-export-numbered-headline-p headline info) + (mapconcat 'number-to-string + (org-export-get-headline-number + headline info) "."))) + ;; Create the headline text. + (full-text (org-html-format-headline--wrap headline info))) + (cond + ;; Case 1: This is a footnote section: ignore it. + ((org-element-property :footnote-section-p headline) nil) + ;; Case 2. This is a deep sub-tree: export it as a list item. + ;; Also export as items headlines for which no section + ;; format has been found. + ((org-export-low-level-p headline info) + ;; Build the real contents of the sub-tree. + (let* ((type (if numberedp 'ordered 'unordered)) + (itemized-body (org-html-format-list-item + contents type nil info nil full-text))) + (concat + (and (org-export-first-sibling-p headline info) + (org-html-begin-plain-list type)) + itemized-body + (and (org-export-last-sibling-p headline info) + (org-html-end-plain-list type))))) + ;; Case 3. Standard headline. Export it as a section. + (t + (let* ((section-number (mapconcat 'number-to-string + (org-export-get-headline-number + headline info) "-")) + (ids (remove 'nil + (list (org-element-property :CUSTOM_ID headline) + (concat "sec-" section-number) + (org-element-property :ID headline)))) + (preferred-id (car ids)) + (extra-ids (cdr ids)) + (extra-class (org-element-property :HTML_CONTAINER_CLASS headline)) + (level1 (+ level (1- org-html-toplevel-hlevel))) + (first-content (car (org-element-contents headline)))) + (format "<%s id=\"%s\" class=\"%s\">%s%s\n" + (org-html--container headline info) + (format "outline-container-%s" + (or (org-element-property :CUSTOM_ID headline) + (concat "sec-" section-number))) + (concat (format "outline-%d" level1) (and extra-class " ") + extra-class) + (format "\n%s%s\n" + level1 + preferred-id + (mapconcat + (lambda (x) + (let ((id (org-export-solidify-link-text + (if (org-uuidgen-p x) (concat "ID-" x) + x)))) + (org-html--anchor id))) + extra-ids "") + full-text + level1) + ;; When there is no section, pretend there is an empty + ;; one to get the correct
\n" class extra) text "
\n"))) + +(defun org-html-inlinetask (inlinetask contents info) + "Transcode an INLINETASK element from Org to HTML. +CONTENTS holds the contents of the block. INFO is a plist +holding contextual information." + (cond + ;; If `org-html-format-inlinetask-function' is provided, call it + ;; with appropriate arguments. + ((functionp org-html-format-inlinetask-function) + (let ((format-function + (function* + (lambda (todo todo-type priority text tags + &key contents &allow-other-keys) + (funcall org-html-format-inlinetask-function + todo todo-type priority text tags contents))))) + (org-html-format-headline--wrap + inlinetask info format-function :contents contents))) + ;; Otherwise, use a default template. + (t (format "
\n%s%s\n%s
" + (org-html-format-headline--wrap inlinetask info) + (org-html-close-tag "br" nil info) + contents)))) + +;;;; Italic + +(defun org-html-italic (italic contents info) + "Transcode ITALIC from Org to HTML. +CONTENTS is the text with italic markup. INFO is a plist holding +contextual information." + (format (or (cdr (assq 'italic org-html-text-markup-alist)) "%s") contents)) + +;;;; Item + +(defun org-html-checkbox (checkbox) + "Format CHECKBOX into HTML." + (case checkbox (on "[X]") + (off "[ ]") + (trans "[-]") + (t ""))) + +(defun org-html-format-list-item (contents type checkbox info + &optional term-counter-id + headline) + "Format a list item into HTML." + (let ((checkbox (concat (org-html-checkbox checkbox) (and checkbox " "))) + (br (org-html-close-tag "br" nil info))) + (concat + (case type + (ordered + (let* ((counter term-counter-id) + (extra (if counter (format " value=\"%s\"" counter) ""))) + (concat + (format "" extra) + (when headline (concat headline br))))) + (unordered + (let* ((id term-counter-id) + (extra (if id (format " id=\"%s\"" id) ""))) + (concat + (format "" extra) + (when headline (concat headline br))))) + (descriptive + (let* ((term term-counter-id)) + (setq term (or term "(no term)")) + ;; Check-boxes in descriptive lists are associated to tag. + (concat (format "
%s
" + (concat checkbox term)) + "
")))) + (unless (eq type 'descriptive) checkbox) + contents + (case type + (ordered "") + (unordered "") + (descriptive "
"))))) + +(defun org-html-item (item contents info) + "Transcode an ITEM element from Org to HTML. +CONTENTS holds the contents of the item. INFO is a plist holding +contextual information." + (let* ((plain-list (org-export-get-parent item)) + (type (org-element-property :type plain-list)) + (counter (org-element-property :counter item)) + (checkbox (org-element-property :checkbox item)) + (tag (let ((tag (org-element-property :tag item))) + (and tag (org-export-data tag info))))) + (org-html-format-list-item + contents type checkbox info (or tag counter)))) + +;;;; Keyword + +(defun org-html-keyword (keyword contents info) + "Transcode a KEYWORD element from Org to HTML. +CONTENTS is nil. INFO is a plist holding contextual information." + (let ((key (org-element-property :key keyword)) + (value (org-element-property :value keyword))) + (cond + ((string= key "HTML") value) + ((string= key "TOC") + (let ((value (downcase value))) + (cond + ((string-match "\\" value) + (let ((depth (or (and (string-match "[0-9]+" value) + (string-to-number (match-string 0 value))) + (plist-get info :with-toc)))) + (org-html-toc depth info))) + ((string= "listings" value) (org-html-list-of-listings info)) + ((string= "tables" value) (org-html-list-of-tables info)))))))) + +;;;; Latex Environment + +(defun org-html-format-latex (latex-frag processing-type) + "Format a LaTeX fragment LATEX-FRAG into HTML." + (let ((cache-relpath "") (cache-dir "")) + (unless (eq processing-type 'mathjax) + (let ((bfn (or (buffer-file-name) + (make-temp-name + (expand-file-name "latex" temporary-file-directory))))) + (setq cache-relpath + (concat "ltxpng/" + (file-name-sans-extension + (file-name-nondirectory bfn))) + cache-dir (file-name-directory bfn)))) + (with-temp-buffer + (insert latex-frag) + (org-format-latex cache-relpath cache-dir nil "Creating LaTeX Image..." + nil nil processing-type) + (buffer-string)))) + +(defun org-html-latex-environment (latex-environment contents info) + "Transcode a LATEX-ENVIRONMENT element from Org to HTML. +CONTENTS is nil. INFO is a plist holding contextual information." + (let ((processing-type (plist-get info :with-latex)) + (latex-frag (org-remove-indentation + (org-element-property :value latex-environment))) + (attributes (org-export-read-attribute :attr_html latex-environment))) + (case processing-type + ((t mathjax) + (org-html-format-latex latex-frag 'mathjax)) + ((dvipng imagemagick) + (let ((formula-link (org-html-format-latex latex-frag processing-type))) + (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link)) + ;; Do not provide a caption or a name to be consistent with + ;; `mathjax' handling. + (org-html--wrap-image + (org-html--format-image + (match-string 1 formula-link) attributes info) info)))) + (t latex-frag)))) + +;;;; Latex Fragment + +(defun org-html-latex-fragment (latex-fragment contents info) + "Transcode a LATEX-FRAGMENT object from Org to HTML. +CONTENTS is nil. INFO is a plist holding contextual information." + (let ((latex-frag (org-element-property :value latex-fragment)) + (processing-type (plist-get info :with-latex))) + (case processing-type + ((t mathjax) + (org-html-format-latex latex-frag 'mathjax)) + ((dvipng imagemagick) + (let ((formula-link (org-html-format-latex latex-frag processing-type))) + (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link)) + (org-html--format-image (match-string 1 formula-link) nil info)))) + (t latex-frag)))) + +;;;; Line Break + +(defun org-html-line-break (line-break contents info) + "Transcode a LINE-BREAK object from Org to HTML. +CONTENTS is nil. INFO is a plist holding contextual information." + (concat (org-html-close-tag "br" nil info) "\n")) + +;;;; Link + +(defun org-html-inline-image-p (link info) + "Non-nil when LINK is meant to appear as an image. +INFO is a plist used as a communication channel. LINK is an +inline image when it has no description and targets an image +file (see `org-html-inline-image-rules' for more information), or +if its description is a single link targeting an image file." + (if (not (org-element-contents link)) + (org-export-inline-image-p link org-html-inline-image-rules) + (not + (let ((link-count 0)) + (org-element-map (org-element-contents link) + (cons 'plain-text org-element-all-objects) + (lambda (obj) + (case (org-element-type obj) + (plain-text (org-string-nw-p obj)) + (link (if (= link-count 1) t + (incf link-count) + (not (org-export-inline-image-p + obj org-html-inline-image-rules)))) + (otherwise t))) + info t))))) + +(defvar org-html-standalone-image-predicate) +(defun org-html-standalone-image-p (element info) + "Test if ELEMENT is a standalone image. + +INFO is a plist holding contextual information. + +Return non-nil, if ELEMENT is of type paragraph and its sole +content, save for white spaces, is a link that qualifies as an +inline image. + +Return non-nil, if ELEMENT is of type link and its containing +paragraph has no other content save white spaces. + +Return nil, otherwise. + +Bind `org-html-standalone-image-predicate' to constrain paragraph +further. For example, to check for only captioned standalone +images, set it to: + + \(lambda (paragraph) (org-element-property :caption paragraph))" + (let ((paragraph (case (org-element-type element) + (paragraph element) + (link (org-export-get-parent element))))) + (and (eq (org-element-type paragraph) 'paragraph) + (or (not (and (boundp 'org-html-standalone-image-predicate) + (functionp org-html-standalone-image-predicate))) + (funcall org-html-standalone-image-predicate paragraph)) + (not (let ((link-count 0)) + (org-element-map (org-element-contents paragraph) + (cons 'plain-text org-element-all-objects) + (lambda (obj) (case (org-element-type obj) + (plain-text (org-string-nw-p obj)) + (link + (or (> (incf link-count) 1) + (not (org-html-inline-image-p obj info)))) + (otherwise t))) + info 'first-match 'link)))))) + +(defun org-html-link (link desc info) + "Transcode a LINK object from Org to HTML. + +DESC is the description part of the link, or the empty string. +INFO is a plist holding contextual information. See +`org-export-data'." + (let* ((home (when (plist-get info :html-link-home) + (org-trim (plist-get info :html-link-home)))) + (use-abs-url (plist-get info :html-link-use-abs-url)) + (link-org-files-as-html-maybe + (function + (lambda (raw-path info) + "Treat links to `file.org' as links to `file.html', if needed. + See `org-html-link-org-files-as-html'." + (cond + ((and org-html-link-org-files-as-html + (string= ".org" + (downcase (file-name-extension raw-path ".")))) + (concat (file-name-sans-extension raw-path) "." + (plist-get info :html-extension))) + (t raw-path))))) + (type (org-element-property :type link)) + (raw-path (org-element-property :path link)) + ;; Ensure DESC really exists, or set it to nil. + (desc (org-string-nw-p desc)) + (path + (cond + ((member type '("http" "https" "ftp" "mailto")) + (concat type ":" raw-path)) + ((string= type "file") + ;; Treat links to ".org" files as ".html", if needed. + (setq raw-path + (funcall link-org-files-as-html-maybe raw-path info)) + ;; If file path is absolute, prepend it with protocol + ;; component - "file://". + (cond ((file-name-absolute-p raw-path) + (setq raw-path + (concat "file://" (expand-file-name + raw-path)))) + ((and home use-abs-url) + (setq raw-path (concat (file-name-as-directory home) raw-path)))) + ;; Add search option, if any. A search option can be + ;; relative to a custom-id or a headline title. Any other + ;; option is ignored. + (let ((option (org-element-property :search-option link))) + (cond ((not option) raw-path) + ((eq (aref option 0) ?#) (concat raw-path option)) + ;; External fuzzy link: try to resolve it if path + ;; belongs to current project, if any. + ((eq (aref option 0) ?*) + (concat + raw-path + (let ((numbers + (org-publish-resolve-external-fuzzy-link + (org-element-property :path link) option))) + (and numbers (concat "#sec-" + (mapconcat 'number-to-string + numbers "-")))))) + (t raw-path)))) + (t raw-path))) + ;; Extract attributes from parent's paragraph. HACK: Only do + ;; this for the first link in parent (inner image link for + ;; inline images). This is needed as long as attributes + ;; cannot be set on a per link basis. + (attributes-plist + (let* ((parent (org-export-get-parent-element link)) + (link (let ((container (org-export-get-parent link))) + (if (and (eq (org-element-type container) 'link) + (org-html-inline-image-p link info)) + container + link)))) + (and (eq (org-element-map parent 'link 'identity info t) link) + (org-export-read-attribute :attr_html parent)))) + (attributes + (let ((attr (org-html--make-attribute-string attributes-plist))) + (if (org-string-nw-p attr) (concat " " attr) ""))) + protocol) + (cond + ;; Image file. + ((and org-html-inline-images + (org-export-inline-image-p link org-html-inline-image-rules)) + (org-html--format-image path attributes-plist info)) + ;; Radio target: Transcode target's contents and use them as + ;; link's description. + ((string= type "radio") + (let ((destination (org-export-resolve-radio-link link info))) + (when destination + (format "%s" + (org-export-solidify-link-text path) + attributes + (org-export-data (org-element-contents destination) info))))) + ;; Links pointing to a headline: Find destination and build + ;; appropriate referencing command. + ((member type '("custom-id" "fuzzy" "id")) + (let ((destination (if (string= type "fuzzy") + (org-export-resolve-fuzzy-link link info) + (org-export-resolve-id-link link info)))) + (case (org-element-type destination) + ;; ID link points to an external file. + (plain-text + (let ((fragment (concat "ID-" path)) + ;; Treat links to ".org" files as ".html", if needed. + (path (funcall link-org-files-as-html-maybe + destination info))) + (format "%s" + path fragment attributes (or desc destination)))) + ;; Fuzzy link points nowhere. + ((nil) + (format "%s" + (or desc + (org-export-data + (org-element-property :raw-link link) info)))) + ;; Link points to a headline. + (headline + (let ((href + ;; What href to use? + (cond + ;; Case 1: Headline is linked via it's CUSTOM_ID + ;; property. Use CUSTOM_ID. + ((string= type "custom-id") + (org-element-property :CUSTOM_ID destination)) + ;; Case 2: Headline is linked via it's ID property + ;; or through other means. Use the default href. + ((member type '("id" "fuzzy")) + (format "sec-%s" + (mapconcat 'number-to-string + (org-export-get-headline-number + destination info) "-"))) + (t (error "Shouldn't reach here")))) + ;; What description to use? + (desc + ;; Case 1: Headline is numbered and LINK has no + ;; description. Display section number. + (if (and (org-export-numbered-headline-p destination info) + (not desc)) + (mapconcat 'number-to-string + (org-export-get-headline-number + destination info) ".") + ;; Case 2: Either the headline is un-numbered or + ;; LINK has a custom description. Display LINK's + ;; description or headline's title. + (or desc (org-export-data (org-element-property + :title destination) info))))) + (format "%s" + (org-export-solidify-link-text href) attributes desc))) + ;; Fuzzy link points to a target or an element. + (t + (let* ((path (org-export-solidify-link-text path)) + (org-html-standalone-image-predicate 'org-html--has-caption-p) + (number (cond + (desc nil) + ((org-html-standalone-image-p destination info) + (org-export-get-ordinal + (org-element-map destination 'link + 'identity info t) + info 'link 'org-html-standalone-image-p)) + (t (org-export-get-ordinal + destination info nil 'org-html--has-caption-p)))) + (desc (cond (desc) + ((not number) "No description for this link") + ((numberp number) (number-to-string number)) + (t (mapconcat 'number-to-string number "."))))) + (format "%s" path attributes desc)))))) + ;; Coderef: replace link with the reference name or the + ;; equivalent line number. + ((string= type "coderef") + (let ((fragment (concat "coderef-" path))) + (format "%s" + fragment + (org-trim + (format (concat "class=\"coderef\"" + " onmouseover=\"CodeHighlightOn(this, '%s');\"" + " onmouseout=\"CodeHighlightOff(this, '%s');\"") + fragment fragment)) + attributes + (format (org-export-get-coderef-format path desc) + (org-export-resolve-coderef path info))))) + ;; Link type is handled by a special function. + ((functionp (setq protocol (nth 2 (assoc type org-link-protocols)))) + (funcall protocol (org-link-unescape path) desc 'html)) + ;; External link with a description part. + ((and path desc) (format "%s" path attributes desc)) + ;; External link without a description part. + (path (format "%s" path attributes path)) + ;; No path, only description. Try to do something useful. + (t (format "%s" desc))))) + +;;;; Paragraph + +(defun org-html-paragraph (paragraph contents info) + "Transcode a PARAGRAPH element from Org to HTML. +CONTENTS is the contents of the paragraph, as a string. INFO is +the plist used as a communication channel." + (let* ((parent (org-export-get-parent paragraph)) + (parent-type (org-element-type parent)) + (style '((footnote-definition " class=\"footpara\""))) + (extra (or (cadr (assoc parent-type style)) ""))) + (cond + ((and (eq (org-element-type parent) 'item) + (= (org-element-property :begin paragraph) + (org-element-property :contents-begin parent))) + ;; Leading paragraph in a list item have no tags. + contents) + ((org-html-standalone-image-p paragraph info) + ;; Standalone image. + (let ((caption + (let ((raw (org-export-data + (org-export-get-caption paragraph) info)) + (org-html-standalone-image-predicate + 'org-html--has-caption-p)) + (if (not (org-string-nw-p raw)) raw + (concat + "" + (format (org-html--translate "Figure %d:" info) + (org-export-get-ordinal + (org-element-map paragraph 'link + 'identity info t) + info nil 'org-html-standalone-image-p)) + " " raw)))) + (label (org-element-property :name paragraph))) + (org-html--wrap-image contents info caption label))) + ;; Regular paragraph. + (t (format "\n%s

" extra contents))))) + +;;;; Plain List + +;; FIXME Maybe arg1 is not needed because
  • already sets +;; the correct value for the item counter +(defun org-html-begin-plain-list (type &optional arg1) + "Insert the beginning of the HTML list depending on TYPE. +When ARG1 is a string, use it as the start parameter for ordered +lists." + (case type + (ordered + (format "
      " + (if arg1 (format " start=\"%d\"" arg1) ""))) + (unordered "
        ") + (descriptive "
        "))) + +(defun org-html-end-plain-list (type) + "Insert the end of the HTML list depending on TYPE." + (case type + (ordered "
    ") + (unordered "") + (descriptive ""))) + +(defun org-html-plain-list (plain-list contents info) + "Transcode a PLAIN-LIST element from Org to HTML. +CONTENTS is the contents of the list. INFO is a plist holding +contextual information." + (let* (arg1 ;; (assoc :counter (org-element-map plain-list 'item + (type (org-element-property :type plain-list))) + (format "%s\n%s%s" + (org-html-begin-plain-list type) + contents (org-html-end-plain-list type)))) + +;;;; Plain Text + +(defun org-html-convert-special-strings (string) + "Convert special characters in STRING to HTML." + (let ((all org-html-special-string-regexps) + e a re rpl start) + (while (setq a (pop all)) + (setq re (car a) rpl (cdr a) start 0) + (while (string-match re string start) + (setq string (replace-match rpl t nil string)))) + string)) + +(defun org-html-encode-plain-text (text) + "Convert plain text characters from TEXT to HTML equivalent. +Possible conversions are set in `org-html-protect-char-alist'." + (mapc + (lambda (pair) + (setq text (replace-regexp-in-string (car pair) (cdr pair) text t t))) + org-html-protect-char-alist) + text) + +(defun org-html-plain-text (text info) + "Transcode a TEXT string from Org to HTML. +TEXT is the string to transcode. INFO is a plist holding +contextual information." + (let ((output text)) + ;; Protect following characters: <, >, &. + (setq output (org-html-encode-plain-text output)) + ;; Handle smart quotes. Be sure to provide original string since + ;; OUTPUT may have been modified. + (when (plist-get info :with-smart-quotes) + (setq output (org-export-activate-smart-quotes output :html info text))) + ;; Handle special strings. + (when (plist-get info :with-special-strings) + (setq output (org-html-convert-special-strings output))) + ;; Handle break preservation if required. + (when (plist-get info :preserve-breaks) + (setq output + (replace-regexp-in-string + "\\(\\\\\\\\\\)?[ \t]*\n" + (concat (org-html-close-tag "br" nil info) "\n") output))) + ;; Return value. + output)) + + +;; Planning + +(defun org-html-planning (planning contents info) + "Transcode a PLANNING element from Org to HTML. +CONTENTS is nil. INFO is a plist used as a communication +channel." + (let ((span-fmt "%s %s")) + (format + "

    %s

    " + (mapconcat + 'identity + (delq nil + (list + (let ((closed (org-element-property :closed planning))) + (when closed + (format span-fmt org-closed-string + (org-translate-time + (org-element-property :raw-value closed))))) + (let ((deadline (org-element-property :deadline planning))) + (when deadline + (format span-fmt org-deadline-string + (org-translate-time + (org-element-property :raw-value deadline))))) + (let ((scheduled (org-element-property :scheduled planning))) + (when scheduled + (format span-fmt org-scheduled-string + (org-translate-time + (org-element-property :raw-value scheduled))))))) + " ")))) + +;;;; Property Drawer + +(defun org-html-property-drawer (property-drawer contents info) + "Transcode a PROPERTY-DRAWER element from Org to HTML. +CONTENTS is nil. INFO is a plist holding contextual +information." + ;; The property drawer isn't exported but we want separating blank + ;; lines nonetheless. + "") + +;;;; Quote Block + +(defun org-html-quote-block (quote-block contents info) + "Transcode a QUOTE-BLOCK element from Org to HTML. +CONTENTS holds the contents of the block. INFO is a plist +holding contextual information." + (format "
    \n%s
    " contents)) + +;;;; Quote Section + +(defun org-html-quote-section (quote-section contents info) + "Transcode a QUOTE-SECTION element from Org to HTML. +CONTENTS is nil. INFO is a plist holding contextual information." + (let ((value (org-remove-indentation + (org-element-property :value quote-section)))) + (when value (format "
    \n%s
    " value)))) + +;;;; Section + +(defun org-html-section (section contents info) + "Transcode a SECTION element from Org to HTML. +CONTENTS holds the contents of the section. INFO is a plist +holding contextual information." + (let ((parent (org-export-get-parent-headline section))) + ;; Before first headline: no container, just return CONTENTS. + (if (not parent) contents + ;; Get div's class and id references. + (let* ((class-num (+ (org-export-get-relative-level parent info) + (1- org-html-toplevel-hlevel))) + (section-number + (mapconcat + 'number-to-string + (org-export-get-headline-number parent info) "-"))) + ;; Build return value. + (format "
    \n%s
    " + class-num + (or (org-element-property :CUSTOM_ID parent) section-number) + contents))))) + +;;;; Radio Target + +(defun org-html-radio-target (radio-target text info) + "Transcode a RADIO-TARGET object from Org to HTML. +TEXT is the text of the target. INFO is a plist holding +contextual information." + (let ((id (org-export-solidify-link-text + (org-element-property :value radio-target)))) + (org-html--anchor id text))) + +;;;; Special Block + +(defun org-html-special-block (special-block contents info) + "Transcode a SPECIAL-BLOCK element from Org to HTML. +CONTENTS holds the contents of the block. INFO is a plist +holding contextual information." + (let* ((block-type (downcase + (org-element-property :type special-block))) + (contents (or contents "")) + (html5-fancy (and (org-html-html5-p info) + (plist-get info :html-html5-fancy) + (member block-type org-html-html5-elements))) + (attributes (org-export-read-attribute :attr_html special-block))) + (unless html5-fancy + (let ((class (plist-get attributes :class))) + (setq attributes (plist-put attributes :class + (if class (concat class " " block-type) + block-type))))) + (setq attributes (org-html--make-attribute-string attributes)) + (when (not (equal attributes "")) + (setq attributes (concat " " attributes))) + (if html5-fancy + (format "<%s%s>\n%s" block-type attributes + contents block-type) + (format "\n%s\n
  • " attributes contents)))) + +;;;; Src Block + +(defun org-html-src-block (src-block contents info) + "Transcode a SRC-BLOCK element from Org to HTML. +CONTENTS holds the contents of the item. INFO is a plist holding +contextual information." + (if (org-export-read-attribute :attr_html src-block :textarea) + (org-html--textarea-block src-block) + (let ((lang (org-element-property :language src-block)) + (caption (org-export-get-caption src-block)) + (code (org-html-format-code src-block info)) + (label (let ((lbl (org-element-property :name src-block))) + (if (not lbl) "" + (format " id=\"%s\"" + (org-export-solidify-link-text lbl)))))) + (if (not lang) (format "
    \n%s
    " label code) + (format + "
    \n%s%s\n
    " + (if (not caption) "" + (format "" + (org-export-data caption info))) + (format "\n
    %s
    " lang label code)))))) + +;;;; Statistics Cookie + +(defun org-html-statistics-cookie (statistics-cookie contents info) + "Transcode a STATISTICS-COOKIE object from Org to HTML. +CONTENTS is nil. INFO is a plist holding contextual information." + (let ((cookie-value (org-element-property :value statistics-cookie))) + (format "%s" cookie-value))) + +;;;; Strike-Through + +(defun org-html-strike-through (strike-through contents info) + "Transcode STRIKE-THROUGH from Org to HTML. +CONTENTS is the text with strike-through markup. INFO is a plist +holding contextual information." + (format (or (cdr (assq 'strike-through org-html-text-markup-alist)) "%s") + contents)) + +;;;; Subscript + +(defun org-html-subscript (subscript contents info) + "Transcode a SUBSCRIPT object from Org to HTML. +CONTENTS is the contents of the object. INFO is a plist holding +contextual information." + (format "%s" contents)) + +;;;; Superscript + +(defun org-html-superscript (superscript contents info) + "Transcode a SUPERSCRIPT object from Org to HTML. +CONTENTS is the contents of the object. INFO is a plist holding +contextual information." + (format "%s" contents)) + +;;;; Tabel Cell + +(defun org-html-table-cell (table-cell contents info) + "Transcode a TABLE-CELL element from Org to HTML. +CONTENTS is nil. INFO is a plist used as a communication +channel." + (let* ((table-row (org-export-get-parent table-cell)) + (table (org-export-get-parent-table table-cell)) + (cell-attrs + (if (not org-html-table-align-individual-fields) "" + (format (if (and (boundp 'org-html-format-table-no-css) + org-html-format-table-no-css) + " align=\"%s\"" " class=\"%s\"") + (org-export-table-cell-alignment table-cell info))))) + (when (or (not contents) (string= "" (org-trim contents))) + (setq contents " ")) + (cond + ((and (org-export-table-has-header-p table info) + (= 1 (org-export-table-row-group table-row info))) + (concat "\n" (format (car org-html-table-header-tags) "col" cell-attrs) + contents (cdr org-html-table-header-tags))) + ((and org-html-table-use-header-tags-for-first-column + (zerop (cdr (org-export-table-cell-address table-cell info)))) + (concat "\n" (format (car org-html-table-header-tags) "row" cell-attrs) + contents (cdr org-html-table-header-tags))) + (t (concat "\n" (format (car org-html-table-data-tags) cell-attrs) + contents (cdr org-html-table-data-tags)))))) + +;;;; Table Row + +(defun org-html-table-row (table-row contents info) + "Transcode a TABLE-ROW element from Org to HTML. +CONTENTS is the contents of the row. INFO is a plist used as a +communication channel." + ;; Rules are ignored since table separators are deduced from + ;; borders of the current row. + (when (eq (org-element-property :type table-row) 'standard) + (let* ((rowgroup-number (org-export-table-row-group table-row info)) + (row-number (org-export-table-row-number table-row info)) + (start-rowgroup-p + (org-export-table-row-starts-rowgroup-p table-row info)) + (end-rowgroup-p + (org-export-table-row-ends-rowgroup-p table-row info)) + ;; `top-row-p' and `end-rowgroup-p' are not used directly + ;; but should be set so that `org-html-table-row-tags' can + ;; use them (see the docstring of this variable.) + (top-row-p (and (equal start-rowgroup-p '(top)) + (equal end-rowgroup-p '(below top)))) + (bottom-row-p (and (equal start-rowgroup-p '(above)) + (equal end-rowgroup-p '(bottom above)))) + (rowgroup-tags + (cond + ;; Case 1: Row belongs to second or subsequent rowgroups. + ((not (= 1 rowgroup-number)) + '("" . "\n")) + ;; Case 2: Row is from first rowgroup. Table has >=1 rowgroups. + ((org-export-table-has-header-p + (org-export-get-parent-table table-row) info) + '("" . "\n")) + ;; Case 2: Row is from first and only row group. + (t '("" . "\n"))))) + (concat + ;; Begin a rowgroup? + (when start-rowgroup-p (car rowgroup-tags)) + ;; Actual table row + (concat "\n" (eval (car org-html-table-row-tags)) + contents + "\n" + (eval (cdr org-html-table-row-tags))) + ;; End a rowgroup? + (when end-rowgroup-p (cdr rowgroup-tags)))))) + +;;;; Table + +(defun org-html-table-first-row-data-cells (table info) + "Transcode the first row of TABLE. +INFO is a plist used as a communication channel." + (let ((table-row + (org-element-map table 'table-row + (lambda (row) + (unless (eq (org-element-property :type row) 'rule) row)) + info 'first-match)) + (special-column-p (org-export-table-has-special-column-p table))) + (if (not special-column-p) (org-element-contents table-row) + (cdr (org-element-contents table-row))))) + +(defun org-html-table--table.el-table (table info) + "Format table.el tables into HTML. +INFO is a plist used as a communication channel." + (when (eq (org-element-property :type table) 'table.el) + (require 'table) + (let ((outbuf (with-current-buffer + (get-buffer-create "*org-export-table*") + (erase-buffer) (current-buffer)))) + (with-temp-buffer + (insert (org-element-property :value table)) + (goto-char 1) + (re-search-forward "^[ \t]*|[^|]" nil t) + (table-generate-source 'html outbuf)) + (with-current-buffer outbuf + (prog1 (org-trim (buffer-string)) + (kill-buffer) ))))) + +(defun org-html-table (table contents info) + "Transcode a TABLE element from Org to HTML. +CONTENTS is the contents of the table. INFO is a plist holding +contextual information." + (case (org-element-property :type table) + ;; Case 1: table.el table. Convert it using appropriate tools. + (table.el (org-html-table--table.el-table table info)) + ;; Case 2: Standard table. + (t + (let* ((label (org-element-property :name table)) + (caption (org-export-get-caption table)) + (number (org-export-get-ordinal + table info nil 'org-html--has-caption-p)) + (attributes + (org-html--make-attribute-string + (org-combine-plists + (and label (list :id (org-export-solidify-link-text label))) + (and (not (org-html-html5-p info)) + (plist-get info :html-table-attributes)) + (org-export-read-attribute :attr_html table)))) + (alignspec + (if (and (boundp 'org-html-format-table-no-css) + org-html-format-table-no-css) + "align=\"%s\"" "class=\"%s\"")) + (table-column-specs + (function + (lambda (table info) + (mapconcat + (lambda (table-cell) + (let ((alignment (org-export-table-cell-alignment + table-cell info))) + (concat + ;; Begin a colgroup? + (when (org-export-table-cell-starts-colgroup-p + table-cell info) + "\n") + ;; Add a column. Also specify it's alignment. + (format "\n%s" + (org-html-close-tag + "col" (concat " " (format alignspec alignment)) info)) + ;; End a colgroup? + (when (org-export-table-cell-ends-colgroup-p + table-cell info) + "\n")))) + (org-html-table-first-row-data-cells table info) "\n"))))) + (format "\n%s\n%s\n%s" + (if (equal attributes "") "" (concat " " attributes)) + (if (not caption) "" + (format (if org-html-table-caption-above + "%s" + "%s") + (concat + "" + (format (org-html--translate "Table %d:" info) number) + " " (org-export-data caption info)))) + (funcall table-column-specs table info) + contents))))) + +;;;; Target + +(defun org-html-target (target contents info) + "Transcode a TARGET object from Org to HTML. +CONTENTS is nil. INFO is a plist holding contextual +information." + (let ((id (org-export-solidify-link-text + (org-element-property :value target)))) + (org-html--anchor id))) + +;;;; Timestamp + +(defun org-html-timestamp (timestamp contents info) + "Transcode a TIMESTAMP object from Org to HTML. +CONTENTS is nil. INFO is a plist holding contextual +information." + (let ((value (org-html-plain-text + (org-timestamp-translate timestamp) info))) + (format "%s" + (replace-regexp-in-string "--" "–" value)))) + +;;;; Underline + +(defun org-html-underline (underline contents info) + "Transcode UNDERLINE from Org to HTML. +CONTENTS is the text with underline markup. INFO is a plist +holding contextual information." + (format (or (cdr (assq 'underline org-html-text-markup-alist)) "%s") + contents)) + +;;;; Verbatim + +(defun org-html-verbatim (verbatim contents info) + "Transcode VERBATIM from Org to HTML. +CONTENTS is nil. INFO is a plist holding contextual +information." + (format (or (cdr (assq 'verbatim org-html-text-markup-alist)) "%s") + (org-html-encode-plain-text (org-element-property :value verbatim)))) + +;;;; Verse Block + +(defun org-html-verse-block (verse-block contents info) + "Transcode a VERSE-BLOCK element from Org to HTML. +CONTENTS is verse block contents. INFO is a plist holding +contextual information." + ;; Replace each newline character with line break. Also replace + ;; each blank line with a line break. + (setq contents (replace-regexp-in-string + "^ *\\\\\\\\$" (format "%s\n" (org-html-close-tag "br" nil info)) + (replace-regexp-in-string + "\\(\\\\\\\\\\)?[ \t]*\n" + (format "%s\n" (org-html-close-tag "br" nil info)) contents))) + ;; Replace each white space at beginning of a line with a + ;; non-breaking space. + (while (string-match "^[ \t]+" contents) + (let* ((num-ws (length (match-string 0 contents))) + (ws (let (out) (dotimes (i num-ws out) + (setq out (concat out " ")))))) + (setq contents (replace-match ws nil t contents)))) + (format "

    \n%s

    " contents)) + + +;;; Filter Functions + +(defun org-html-final-function (contents backend info) + "Filter to indent the HTML and convert HTML entities." + (with-temp-buffer + (insert contents) + (set-auto-mode t) + (if org-html-indent + (indent-region (point-min) (point-max))) + (when org-html-use-unicode-chars + (require 'mm-url) + (mm-url-decode-entities)) + (buffer-substring-no-properties (point-min) (point-max)))) + + +;;; End-user functions + +;;;###autoload +(defun org-html-export-as-html + (&optional async subtreep visible-only body-only ext-plist) + "Export current buffer to an HTML buffer. + +If narrowing is active in the current buffer, only export its +narrowed part. + +If a region is active, export that region. + +A non-nil optional argument ASYNC means the process should happen +asynchronously. The resulting buffer should be accessible +through the `org-export-stack' interface. + +When optional argument SUBTREEP is non-nil, export the sub-tree +at point, extracting information from the headline properties +first. + +When optional argument VISIBLE-ONLY is non-nil, don't export +contents of hidden elements. + +When optional argument BODY-ONLY is non-nil, only write code +between \"\" and \"\" tags. + +EXT-PLIST, when provided, is a property list with external +parameters overriding Org default settings, but still inferior to +file-local settings. + +Export is done in a buffer named \"*Org HTML Export*\", which +will be displayed when `org-export-show-temporary-export-buffer' +is non-nil." + (interactive) + (org-export-to-buffer 'html "*Org HTML Export*" + async subtreep visible-only body-only ext-plist + (lambda () (set-auto-mode t)))) + +;;;###autoload +(defun org-html-convert-region-to-html () + "Assume the current region has org-mode syntax, and convert it to HTML. +This can be used in any buffer. For example, you can write an +itemized list in org-mode syntax in an HTML buffer and use this +command to convert it." + (interactive) + (org-export-replace-region-by 'html)) + +;;;###autoload +(defun org-html-export-to-html + (&optional async subtreep visible-only body-only ext-plist) + "Export current buffer to a HTML file. + +If narrowing is active in the current buffer, only export its +narrowed part. + +If a region is active, export that region. + +A non-nil optional argument ASYNC means the process should happen +asynchronously. The resulting file should be accessible through +the `org-export-stack' interface. + +When optional argument SUBTREEP is non-nil, export the sub-tree +at point, extracting information from the headline properties +first. + +When optional argument VISIBLE-ONLY is non-nil, don't export +contents of hidden elements. + +When optional argument BODY-ONLY is non-nil, only write code +between \"\" and \"\" tags. + +EXT-PLIST, when provided, is a property list with external +parameters overriding Org default settings, but still inferior to +file-local settings. + +Return output file's name." + (interactive) + (let* ((extension (concat "." org-html-extension)) + (file (org-export-output-file-name extension subtreep)) + (org-export-coding-system org-html-coding-system)) + (org-export-to-file 'html file + async subtreep visible-only body-only ext-plist))) + +;;;###autoload +(defun org-html-publish-to-html (plist filename pub-dir) + "Publish an org file to HTML. + +FILENAME is the filename of the Org file to be published. PLIST +is the property list for the given project. PUB-DIR is the +publishing directory. + +Return output file name." + (org-publish-org-to 'html filename + (concat "." (or (plist-get plist :html-extension) + org-html-extension "html")) + plist pub-dir)) + + +;;; FIXME + +;;;; org-format-table-html +;;;; org-format-org-table-html +;;;; org-format-table-table-html +;;;; org-table-number-fraction +;;;; org-table-number-regexp +;;;; org-html-inline-image-extensions +;;;; org-export-preferred-target-alist +;;;; class for anchors +;;;; org-export-mark-todo-in-toc +;;;; org-html-format-org-link +;;;; (caption (and caption (org-xml-encode-org-text caption))) +;;;; alt = (file-name-nondirectory path) + +(provide 'ox-html) + +;; Local variables: +;; generated-autoload-file: "org-loaddefs.el" +;; End: + +;;; ox-html.el ends here diff --git a/lisp/org/ox-icalendar.el b/lisp/org/ox-icalendar.el new file mode 100644 index 00000000000..8dfe836c9f5 --- /dev/null +++ b/lisp/org/ox-icalendar.el @@ -0,0 +1,979 @@ +;;; ox-icalendar.el --- iCalendar Back-End for Org Export Engine + +;; Copyright (C) 2004-2012 Free Software Foundation, Inc. + +;; Author: Carsten Dominik +;; Nicolas Goaziou +;; Keywords: outlines, hypermedia, calendar, wp +;; Homepage: http://orgmode.org + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: +;; +;; This library implements an iCalendar back-end for Org generic +;; exporter. See Org manual for more information. +;; +;; It is expected to conform to RFC 5545. + +;;; Code: + +(eval-when-compile (require 'cl)) +(require 'ox-ascii) +(declare-function org-bbdb-anniv-export-ical "org-bbdb" nil) + + + +;;; User-Configurable Variables + +(defgroup org-export-icalendar nil + "Options specific for iCalendar export back-end." + :tag "Org Export iCalendar" + :group 'org-export) + +(defcustom org-icalendar-combined-agenda-file "~/org.ics" + "The file name for the iCalendar file covering all agenda files. +This file is created with the command \\[org-icalendar-combine-agenda-files]. +The file name should be absolute. It will be overwritten without warning." + :group 'org-export-icalendar + :type 'file) + +(defcustom org-icalendar-alarm-time 0 + "Number of minutes for triggering an alarm for exported timed events. + +A zero value (the default) turns off the definition of an alarm trigger +for timed events. If non-zero, alarms are created. + +- a single alarm per entry is defined +- The alarm will go off N minutes before the event +- only a DISPLAY action is defined." + :group 'org-export-icalendar + :version "24.1" + :type 'integer) + +(defcustom org-icalendar-combined-name "OrgMode" + "Calendar name for the combined iCalendar representing all agenda files." + :group 'org-export-icalendar + :type 'string) + +(defcustom org-icalendar-combined-description "" + "Calendar description for the combined iCalendar (all agenda files)." + :group 'org-export-icalendar + :type 'string) + +(defcustom org-icalendar-exclude-tags nil + "Tags that exclude a tree from export. +This variable allows to specify different exclude tags from other +back-ends. It can also be set with the ICAL_EXCLUDE_TAGS +keyword." + :group 'org-export-icalendar + :type '(repeat (string :tag "Tag"))) + +(defcustom org-icalendar-use-deadline '(event-if-not-todo todo-due) + "Contexts where iCalendar export should use a deadline time stamp. + +This is a list with several symbols in it. Valid symbol are: +`event-if-todo' Deadlines in TODO entries become calendar events. +`event-if-not-todo' Deadlines in non-TODO entries become calendar events. +`todo-due' Use deadlines in TODO entries as due-dates" + :group 'org-export-icalendar + :type '(set :greedy t + (const :tag "Deadlines in non-TODO entries become events" + event-if-not-todo) + (const :tag "Deadline in TODO entries become events" + event-if-todo) + (const :tag "Deadlines in TODO entries become due-dates" + todo-due))) + +(defcustom org-icalendar-use-scheduled '(todo-start) + "Contexts where iCalendar export should use a scheduling time stamp. + +This is a list with several symbols in it. Valid symbol are: +`event-if-todo' Scheduling time stamps in TODO entries become an event. +`event-if-not-todo' Scheduling time stamps in non-TODO entries become an event. +`todo-start' Scheduling time stamps in TODO entries become start date. + Some calendar applications show TODO entries only after + that date." + :group 'org-export-icalendar + :type '(set :greedy t + (const :tag + "SCHEDULED timestamps in non-TODO entries become events" + event-if-not-todo) + (const :tag "SCHEDULED timestamps in TODO entries become events" + event-if-todo) + (const :tag "SCHEDULED in TODO entries become start date" + todo-start))) + +(defcustom org-icalendar-categories '(local-tags category) + "Items that should be entered into the \"categories\" field. + +This is a list of symbols, the following are valid: +`category' The Org mode category of the current file or tree +`todo-state' The todo state, if any +`local-tags' The tags, defined in the current line +`all-tags' All tags, including inherited ones." + :group 'org-export-icalendar + :type '(repeat + (choice + (const :tag "The file or tree category" category) + (const :tag "The TODO state" todo-state) + (const :tag "Tags defined in current line" local-tags) + (const :tag "All tags, including inherited ones" all-tags)))) + +(defcustom org-icalendar-with-timestamps 'active + "Non-nil means make an event from plain time stamps. + +It can be set to `active', `inactive', t or nil, in order to make +an event from, respectively, only active timestamps, only +inactive ones, all of them or none. + +This variable has precedence over `org-export-with-timestamps'. +It can also be set with the #+OPTIONS line, e.g. \"<:t\"." + :group 'org-export-icalendar + :type '(choice + (const :tag "All timestamps" t) + (const :tag "Only active timestamps" active) + (const :tag "Only inactive timestamps" inactive) + (const :tag "No timestamp" nil))) + +(defcustom org-icalendar-include-todo nil + "Non-nil means create VTODO components from TODO items. + +Valid values are: +nil don't include any task. +t include tasks that are not in DONE state. +`unblocked' include all TODO items that are not blocked. +`all' include both done and not done items." + :group 'org-export-icalendar + :type '(choice + (const :tag "None" nil) + (const :tag "Unfinished" t) + (const :tag "Unblocked" unblocked) + (const :tag "All" all) + (repeat :tag "Specific TODO keywords" + (string :tag "Keyword")))) + +(defcustom org-icalendar-include-bbdb-anniversaries nil + "Non-nil means a combined iCalendar file should include anniversaries. +The anniversaries are defined in the BBDB database." + :group 'org-export-icalendar + :type 'boolean) + +(defcustom org-icalendar-include-sexps t + "Non-nil means export to iCalendar files should also cover sexp entries. +These are entries like in the diary, but directly in an Org mode +file." + :group 'org-export-icalendar + :type 'boolean) + +(defcustom org-icalendar-include-body t + "Amount of text below headline to be included in iCalendar export. +This is a number of characters that should maximally be included. +Properties, scheduling and clocking lines will always be removed. +The text will be inserted into the DESCRIPTION field." + :group 'org-export-icalendar + :type '(choice + (const :tag "Nothing" nil) + (const :tag "Everything" t) + (integer :tag "Max characters"))) + +(defcustom org-icalendar-store-UID nil + "Non-nil means store any created UIDs in properties. + +The iCalendar standard requires that all entries have a unique identifier. +Org will create these identifiers as needed. When this variable is non-nil, +the created UIDs will be stored in the ID property of the entry. Then the +next time this entry is exported, it will be exported with the same UID, +superseding the previous form of it. This is essential for +synchronization services. + +This variable is not turned on by default because we want to avoid creating +a property drawer in every entry if people are only playing with this feature, +or if they are only using it locally." + :group 'org-export-icalendar + :type 'boolean) + +(defcustom org-icalendar-timezone (getenv "TZ") + "The time zone string for iCalendar export. +When nil or the empty string, use output +from (current-time-zone)." + :group 'org-export-icalendar + :type '(choice + (const :tag "Unspecified" nil) + (string :tag "Time zone"))) + +(defcustom org-icalendar-date-time-format ":%Y%m%dT%H%M%S" + "Format-string for exporting icalendar DATE-TIME. + +See `format-time-string' for a full documentation. The only +difference is that `org-icalendar-timezone' is used for %Z. + +Interesting value are: + - \":%Y%m%dT%H%M%S\" for local time + - \";TZID=%Z:%Y%m%dT%H%M%S\" for local time with explicit timezone + - \":%Y%m%dT%H%M%SZ\" for time expressed in Universal Time" + :group 'org-export-icalendar + :version "24.1" + :type '(choice + (const :tag "Local time" ":%Y%m%dT%H%M%S") + (const :tag "Explicit local time" ";TZID=%Z:%Y%m%dT%H%M%S") + (const :tag "Universal time" ":%Y%m%dT%H%M%SZ") + (string :tag "Explicit format"))) + +(defvar org-icalendar-after-save-hook nil + "Hook run after an iCalendar file has been saved. +This hook is run with the name of the file as argument. A good +way to use this is to tell a desktop calendar application to +re-read the iCalendar file.") + + + +;;; Define Back-End + +(org-export-define-derived-backend 'icalendar 'ascii + :translate-alist '((clock . ignore) + (footnote-definition . ignore) + (footnote-reference . ignore) + (headline . org-icalendar-entry) + (inlinetask . ignore) + (planning . ignore) + (section . ignore) + (inner-template . (lambda (c i) c)) + (template . org-icalendar-template)) + :options-alist + '((:exclude-tags + "ICALENDAR_EXCLUDE_TAGS" nil org-icalendar-exclude-tags split) + (:with-timestamps nil "<" org-icalendar-with-timestamps) + (:with-vtodo nil nil org-icalendar-include-todo) + ;; The following property will be non-nil when export has been + ;; started from org-agenda-mode. In this case, any entry without + ;; a non-nil "ICALENDAR_MARK" property will be ignored. + (:icalendar-agenda-view nil nil nil)) + :filters-alist + '((:filter-headline . org-icalendar-clear-blank-lines)) + :menu-entry + '(?c "Export to iCalendar" + ((?f "Current file" org-icalendar-export-to-ics) + (?a "All agenda files" + (lambda (a s v b) (org-icalendar-export-agenda-files a))) + (?c "Combine all agenda files" + (lambda (a s v b) (org-icalendar-combine-agenda-files a)))))) + + + +;;; Internal Functions + +(defun org-icalendar-create-uid (file &optional bell h-markers) + "Set ID property on headlines missing it in FILE. +When optional argument BELL is non-nil, inform the user with +a message if the file was modified. With optional argument +H-MARKERS non-nil, it is a list of markers for the headlines +which will be updated." + (let ((pt (if h-markers (goto-char (car h-markers)) (point-min))) + modified-flag) + (org-map-entries + (lambda () + (let ((entry (org-element-at-point))) + (unless (or (< (point) pt) (org-element-property :ID entry)) + (org-id-get-create) + (setq modified-flag t) + (forward-line)) + (when h-markers (setq org-map-continue-from (pop h-markers))))) + nil nil 'comment) + (when (and bell modified-flag) + (message "ID properties created in file \"%s\"" file) + (sit-for 2)))) + +(defun org-icalendar-blocked-headline-p (headline info) + "Non-nil when HEADLINE is considered to be blocked. + +INFO is a plist used as a communication channel. + +a headline is blocked when either: + + - It has children which are not all in a completed state. + + - It has a parent with the property :ORDERED:, and there are + siblings prior to it with incomplete status. + + - Its parent is blocked because it has siblings that should be + done first or is a child of a blocked grandparent entry." + (or + ;; Check if any child is not done. + (org-element-map headline 'headline + (lambda (hl) (eq (org-element-property :todo-type hl) 'todo)) + info 'first-match) + ;; Check :ORDERED: node property. + (catch 'blockedp + (let ((current headline)) + (mapc (lambda (parent) + (cond + ((not (org-element-property :todo-keyword parent)) + (throw 'blockedp nil)) + ((org-not-nil (org-element-property :ORDERED parent)) + (let ((sibling current)) + (while (setq sibling (org-export-get-previous-element + sibling info)) + (when (eq (org-element-property :todo-type sibling) 'todo) + (throw 'blockedp t))))) + (t (setq current parent)))) + (org-export-get-genealogy headline)) + nil)))) + +(defun org-icalendar-use-UTC-date-time-p () + "Non-nil when `org-icalendar-date-time-format' requires UTC time." + (char-equal (elt org-icalendar-date-time-format + (1- (length org-icalendar-date-time-format))) ?Z)) + +(defvar org-agenda-default-appointment-duration) ; From org-agenda.el. +(defun org-icalendar-convert-timestamp (timestamp keyword &optional end utc) + "Convert TIMESTAMP to iCalendar format. + +TIMESTAMP is a timestamp object. KEYWORD is added in front of +it, in order to make a complete line (e.g. \"DTSTART\"). + +When optional argument END is non-nil, use end of time range. +Also increase the hour by two (if time string contains a time), +or the day by one (if it does not contain a time) when no +explicit ending time is specified. + +When optional argument UTC is non-nil, time will be expressed in +Universal Time, ignoring `org-icalendar-date-time-format'." + (let* ((year-start (org-element-property :year-start timestamp)) + (year-end (org-element-property :year-end timestamp)) + (month-start (org-element-property :month-start timestamp)) + (month-end (org-element-property :month-end timestamp)) + (day-start (org-element-property :day-start timestamp)) + (day-end (org-element-property :day-end timestamp)) + (hour-start (org-element-property :hour-start timestamp)) + (hour-end (org-element-property :hour-end timestamp)) + (minute-start (org-element-property :minute-start timestamp)) + (minute-end (org-element-property :minute-end timestamp)) + (with-time-p minute-start) + (equal-bounds-p + (equal (list year-start month-start day-start hour-start minute-start) + (list year-end month-end day-end hour-end minute-end))) + (mi (cond ((not with-time-p) 0) + ((not end) minute-start) + ((and org-agenda-default-appointment-duration equal-bounds-p) + (+ minute-end org-agenda-default-appointment-duration)) + (t minute-end))) + (h (cond ((not with-time-p) 0) + ((not end) hour-start) + ((or (not equal-bounds-p) + org-agenda-default-appointment-duration) + hour-end) + (t (+ hour-end 2)))) + (d (cond ((not end) day-start) + ((not with-time-p) (1+ day-end)) + (t day-end))) + (m (if end month-end month-start)) + (y (if end year-end year-start))) + (concat + keyword + (format-time-string + (cond (utc ":%Y%m%dT%H%M%SZ") + ((not with-time-p) ";VALUE=DATE:%Y%m%d") + (t (replace-regexp-in-string "%Z" + org-icalendar-timezone + org-icalendar-date-time-format + t))) + ;; Convert timestamp into internal time in order to use + ;; `format-time-string' and fix any mistake (i.e. MI >= 60). + (encode-time 0 mi h d m y) + (or utc (and with-time-p (org-icalendar-use-UTC-date-time-p))))))) + +(defun org-icalendar-dtstamp () + "Return DTSTAMP property, as a string." + (format-time-string "DTSTAMP:%Y%m%dT%H%M%SZ" nil t)) + +(defun org-icalendar-get-categories (entry info) + "Return categories according to `org-icalendar-categories'. +ENTRY is a headline or an inlinetask element. INFO is a plist +used as a communication channel." + (mapconcat + 'identity + (org-uniquify + (let (categories) + (mapc (lambda (type) + (case type + (category + (push (org-export-get-category entry info) categories)) + (todo-state + (let ((todo (org-element-property :todo-keyword entry))) + (and todo (push todo categories)))) + (local-tags + (setq categories + (append (nreverse (org-export-get-tags entry info)) + categories))) + (all-tags + (setq categories + (append (nreverse (org-export-get-tags entry info nil t)) + categories))))) + org-icalendar-categories) + ;; Return list of categories, following specified order. + (nreverse categories))) ",")) + +(defun org-icalendar-transcode-diary-sexp (sexp uid summary) + "Transcode a diary sexp into iCalendar format. +SEXP is the diary sexp being transcoded, as a string. UID is the +unique identifier for the entry. SUMMARY defines a short summary +or subject for the event." + (when (require 'icalendar nil t) + (org-element-normalize-string + (with-temp-buffer + (let ((sexp (if (not (string-match "\\`<%%" sexp)) sexp + (concat (substring sexp 1 -1) " " summary)))) + (put-text-property 0 1 'uid uid sexp) + (insert sexp "\n")) + (org-diary-to-ical-string (current-buffer)))))) + +(defun org-icalendar-cleanup-string (s) + "Cleanup string S according to RFC 5545." + (when s + ;; Protect "\", "," and ";" characters. and replace newline + ;; characters with literal \n. + (replace-regexp-in-string + "[ \t]*\n" "\\n" + (replace-regexp-in-string "[\\,;]" "\\\&" s) + nil t))) + +(defun org-icalendar-fold-string (s) + "Fold string S according to RFC 5545." + (org-element-normalize-string + (mapconcat + (lambda (line) + ;; Limit each line to a maximum of 75 characters. If it is + ;; longer, fold it by using "\n " as a continuation marker. + (let ((len (length line))) + (if (<= len 75) line + (let ((folded-line (substring line 0 75)) + (chunk-start 75) + chunk-end) + ;; Since continuation marker takes up one character on the + ;; line, real contents must be split at 74 chars. + (while (< (setq chunk-end (+ chunk-start 74)) len) + (setq folded-line + (concat folded-line "\n " + (substring line chunk-start chunk-end)) + chunk-start chunk-end)) + (concat folded-line "\n " (substring line chunk-start)))))) + (org-split-string s "\n") "\n"))) + + + +;;; Filters + +(defun org-icalendar-clear-blank-lines (headline back-end info) + "Remove trailing blank lines in HEADLINE export. +HEADLINE is a string representing a transcoded headline. +BACK-END and INFO are ignored." + (replace-regexp-in-string "^\\(?:[ \t]*\n\\)*" "" headline)) + + + +;;; Transcode Functions + +;;;; Headline and Inlinetasks + +;; The main function is `org-icalendar-entry', which extracts +;; information from a headline or an inlinetask (summary, +;; description...) and then delegates code generation to +;; `org-icalendar--vtodo' and `org-icalendar--vevent', depending +;; on the component needed. + +;; Obviously, `org-icalendar--valarm' handles alarms, which can +;; happen within a VTODO component. + +(defun org-icalendar-entry (entry contents info) + "Transcode ENTRY element into iCalendar format. + +ENTRY is either a headline or an inlinetask. CONTENTS is +ignored. INFO is a plist used as a communication channel. + +This function is called on every headline, the section below +it (minus inlinetasks) being its contents. It tries to create +VEVENT and VTODO components out of scheduled date, deadline date, +plain timestamps, diary sexps. It also calls itself on every +inlinetask within the section." + (unless (org-element-property :footnote-section-p entry) + (let* ((type (org-element-type entry)) + ;; Determine contents really associated to the entry. For + ;; a headline, limit them to section, if any. For an + ;; inlinetask, this is every element within the task. + (inside + (if (eq type 'inlinetask) + (cons 'org-data (cons nil (org-element-contents entry))) + (let ((first (car (org-element-contents entry)))) + (and (eq (org-element-type first) 'section) + (cons 'org-data + (cons nil (org-element-contents first)))))))) + (concat + (unless (and (plist-get info :icalendar-agenda-view) + (not (org-element-property :ICALENDAR-MARK entry))) + (let ((todo-type (org-element-property :todo-type entry)) + (uid (or (org-element-property :ID entry) (org-id-new))) + (summary (org-icalendar-cleanup-string + (or (org-element-property :SUMMARY entry) + (org-export-data + (org-element-property :title entry) info)))) + (loc (org-icalendar-cleanup-string + (org-element-property :LOCATION entry))) + ;; Build description of the entry from associated + ;; section (headline) or contents (inlinetask). + (desc + (org-icalendar-cleanup-string + (or (org-element-property :DESCRIPTION entry) + (let ((contents (org-export-data inside info))) + (cond + ((not (org-string-nw-p contents)) nil) + ((wholenump org-icalendar-include-body) + (let ((contents (org-trim contents))) + (substring + contents 0 (min (length contents) + org-icalendar-include-body)))) + (org-icalendar-include-body (org-trim contents))))))) + (cat (org-icalendar-get-categories entry info))) + (concat + ;; Events: Delegate to `org-icalendar--vevent' to + ;; generate "VEVENT" component from scheduled, deadline, + ;; or any timestamp in the entry. + (let ((deadline (org-element-property :deadline entry))) + (and deadline + (memq (if todo-type 'event-if-todo 'event-if-not-todo) + org-icalendar-use-deadline) + (org-icalendar--vevent + entry deadline (concat "DL-" uid) + (concat "DL: " summary) loc desc cat))) + (let ((scheduled (org-element-property :scheduled entry))) + (and scheduled + (memq (if todo-type 'event-if-todo 'event-if-not-todo) + org-icalendar-use-scheduled) + (org-icalendar--vevent + entry scheduled (concat "SC-" uid) + (concat "S: " summary) loc desc cat))) + ;; When collecting plain timestamps from a headline and + ;; its title, skip inlinetasks since collection will + ;; happen once ENTRY is one of them. + (let ((counter 0)) + (mapconcat + 'identity + (org-element-map (cons (org-element-property :title entry) + (org-element-contents inside)) + 'timestamp + (lambda (ts) + (let ((uid (format "TS%d-%s" (incf counter) uid))) + (org-icalendar--vevent entry ts uid summary loc desc cat))) + info nil (and (eq type 'headline) 'inlinetask)) + "")) + ;; Task: First check if it is appropriate to export it. + ;; If so, call `org-icalendar--vtodo' to transcode it + ;; into a "VTODO" component. + (when (and todo-type + (case (plist-get info :with-vtodo) + (all t) + (unblocked + (and (eq type 'headline) + (not (org-icalendar-blocked-headline-p + entry info)))) + ('t (eq todo-type 'todo)))) + (org-icalendar--vtodo entry uid summary loc desc cat)) + ;; Diary-sexp: Collect every diary-sexp element within + ;; ENTRY and its title, and transcode them. If ENTRY is + ;; a headline, skip inlinetasks: they will be handled + ;; separately. + (when org-icalendar-include-sexps + (let ((counter 0)) + (mapconcat 'identity + (org-element-map + (cons (org-element-property :title entry) + (org-element-contents inside)) + 'diary-sexp + (lambda (sexp) + (org-icalendar-transcode-diary-sexp + (org-element-property :value sexp) + (format "DS%d-%s" (incf counter) uid) + summary)) + info nil (and (eq type 'headline) 'inlinetask)) + "")))))) + ;; If ENTRY is a headline, call current function on every + ;; inlinetask within it. In agenda export, this is independent + ;; from the mark (or lack thereof) on the entry. + (when (eq type 'headline) + (mapconcat 'identity + (org-element-map inside 'inlinetask + (lambda (task) (org-icalendar-entry task nil info)) + info) "")) + ;; Don't forget components from inner entries. + contents)))) + +(defun org-icalendar--vevent + (entry timestamp uid summary location description categories) + "Create a VEVENT component. + +ENTRY is either a headline or an inlinetask element. TIMESTAMP +is a timestamp object defining the date-time of the event. UID +is the unique identifier for the event. SUMMARY defines a short +summary or subject for the event. LOCATION defines the intended +venue for the event. DESCRIPTION provides the complete +description of the event. CATEGORIES defines the categories the +event belongs to. + +Return VEVENT component as a string." + (org-icalendar-fold-string + (if (eq (org-element-property :type timestamp) 'diary) + (org-icalendar-transcode-diary-sexp + (org-element-property :raw-value timestamp) uid summary) + (concat "BEGIN:VEVENT\n" + (org-icalendar-dtstamp) "\n" + "UID:" uid "\n" + (org-icalendar-convert-timestamp timestamp "DTSTART") "\n" + (org-icalendar-convert-timestamp timestamp "DTEND" t) "\n" + ;; RRULE. + (when (org-element-property :repeater-type timestamp) + (format "RRULE:FREQ=%s;INTERVAL=%d\n" + (case (org-element-property :repeater-unit timestamp) + (hour "HOURLY") (day "DAILY") (week "WEEKLY") + (month "MONTHLY") (year "YEARLY")) + (org-element-property :repeater-value timestamp))) + "SUMMARY:" summary "\n" + (and (org-string-nw-p location) (format "LOCATION:%s\n" location)) + (and (org-string-nw-p description) + (format "DESCRIPTION:%s\n" description)) + "CATEGORIES:" categories "\n" + ;; VALARM. + (org-icalendar--valarm entry timestamp summary) + "END:VEVENT")))) + +(defun org-icalendar--vtodo + (entry uid summary location description categories) + "Create a VTODO component. + +ENTRY is either a headline or an inlinetask element. UID is the +unique identifier for the task. SUMMARY defines a short summary +or subject for the task. LOCATION defines the intended venue for +the task. DESCRIPTION provides the complete description of the +task. CATEGORIES defines the categories the task belongs to. + +Return VTODO component as a string." + (let ((start (or (and (memq 'todo-start org-icalendar-use-scheduled) + (org-element-property :scheduled entry)) + ;; If we can't use a scheduled time for some + ;; reason, start task now. + (let ((now (decode-time (current-time)))) + (list 'timestamp + (list :type 'active + :minute-start (nth 1 now) + :hour-start (nth 2 now) + :day-start (nth 3 now) + :month-start (nth 4 now) + :year-start (nth 5 now))))))) + (org-icalendar-fold-string + (concat "BEGIN:VTODO\n" + "UID:TODO-" uid "\n" + (org-icalendar-dtstamp) "\n" + (org-icalendar-convert-timestamp start "DTSTART") "\n" + (and (memq 'todo-due org-icalendar-use-deadline) + (org-element-property :deadline entry) + (concat (org-icalendar-convert-timestamp + (org-element-property :deadline entry) "DUE") + "\n")) + "SUMMARY:" summary "\n" + (and (org-string-nw-p location) (format "LOCATION:%s\n" location)) + (and (org-string-nw-p description) + (format "DESCRIPTION:%s\n" description)) + "CATEGORIES:" categories "\n" + "SEQUENCE:1\n" + (format "PRIORITY:%d\n" + (let ((pri (or (org-element-property :priority entry) + org-default-priority))) + (floor (- 9 (* 8. (/ (float (- org-lowest-priority pri)) + (- org-lowest-priority + org-highest-priority))))))) + (format "STATUS:%s\n" + (if (eq (org-element-property :todo-type entry) 'todo) + "NEEDS-ACTION" + "COMPLETED")) + "END:VTODO")))) + +(defun org-icalendar--valarm (entry timestamp summary) + "Create a VALARM component. + +ENTRY is the calendar entry triggering the alarm. TIMESTAMP is +the start date-time of the entry. SUMMARY defines a short +summary or subject for the task. + +Return VALARM component as a string, or nil if it isn't allowed." + ;; Create a VALARM entry if the entry is timed. This is not very + ;; general in that: + ;; (a) only one alarm per entry is defined, + ;; (b) only minutes are allowed for the trigger period ahead of the + ;; start time, + ;; (c) only a DISPLAY action is defined. [ESF] + (let ((alarm-time + (let ((warntime + (org-element-property :APPT_WARNTIME entry))) + (if warntime (string-to-number warntime) 0)))) + (and (or (> alarm-time 0) (> org-icalendar-alarm-time 0)) + (org-element-property :hour-start timestamp) + (format "BEGIN:VALARM +ACTION:DISPLAY +DESCRIPTION:%s +TRIGGER:-P0DT0H%dM0S +END:VALARM\n" + summary + (if (zerop alarm-time) org-icalendar-alarm-time alarm-time))))) + + +;;;; Template + +(defun org-icalendar-template (contents info) + "Return complete document string after iCalendar conversion. +CONTENTS is the transcoded contents string. INFO is a plist used +as a communication channel." + (org-icalendar--vcalendar + ;; Name. + (if (not (plist-get info :input-file)) (buffer-name (buffer-base-buffer)) + (file-name-nondirectory + (file-name-sans-extension (plist-get info :input-file)))) + ;; Owner. + (if (not (plist-get info :with-author)) "" + (org-export-data (plist-get info :author) info)) + ;; Timezone. + (if (org-string-nw-p org-icalendar-timezone) org-icalendar-timezone + (cadr (current-time-zone))) + ;; Description. + (org-export-data (plist-get info :title) info) + contents)) + +(defun org-icalendar--vcalendar (name owner tz description contents) + "Create a VCALENDAR component. +NAME, OWNER, TZ, DESCRIPTION and CONTENTS are all strings giving, +respectively, the name of the calendar, its owner, the timezone +used, a short description and the other components included." + (concat (format "BEGIN:VCALENDAR +VERSION:2.0 +X-WR-CALNAME:%s +PRODID:-//%s//Emacs with Org mode//EN +X-WR-TIMEZONE:%s +X-WR-CALDESC:%s +CALSCALE:GREGORIAN\n" + (org-icalendar-cleanup-string name) + (org-icalendar-cleanup-string owner) + (org-icalendar-cleanup-string tz) + (org-icalendar-cleanup-string description)) + contents + "END:VCALENDAR\n")) + + + +;;; Interactive Functions + +;;;###autoload +(defun org-icalendar-export-to-ics + (&optional async subtreep visible-only body-only) + "Export current buffer to an iCalendar file. + +If narrowing is active in the current buffer, only export its +narrowed part. + +If a region is active, export that region. + +A non-nil optional argument ASYNC means the process should happen +asynchronously. The resulting file should be accessible through +the `org-export-stack' interface. + +When optional argument SUBTREEP is non-nil, export the sub-tree +at point, extracting information from the headline properties +first. + +When optional argument VISIBLE-ONLY is non-nil, don't export +contents of hidden elements. + +When optional argument BODY-ONLY is non-nil, only write code +between \"BEGIN:VCALENDAR\" and \"END:VCALENDAR\". + +Return ICS file name." + (interactive) + (let ((file (buffer-file-name (buffer-base-buffer)))) + (when (and file org-icalendar-store-UID) + (org-icalendar-create-uid file 'warn-user))) + ;; Export part. Since this back-end is backed up by `ascii', ensure + ;; links will not be collected at the end of sections. + (let ((outfile (org-export-output-file-name ".ics" subtreep))) + (org-export-to-file 'icalendar outfile + async subtreep visible-only body-only '(:ascii-charset utf-8) + (lambda (file) + (run-hook-with-args 'org-icalendar-after-save-hook file) nil)))) + +;;;###autoload +(defun org-icalendar-export-agenda-files (&optional async) + "Export all agenda files to iCalendar files. +When optional argument ASYNC is non-nil, export happens in an +external process." + (interactive) + (if async + ;; Asynchronous export is not interactive, so we will not call + ;; `org-check-agenda-file'. Instead we remove any non-existent + ;; agenda file from the list. + (let ((files (org-remove-if-not 'file-exists-p (org-agenda-files t)))) + (org-export-async-start + (lambda (results) + (mapc (lambda (f) (org-export-add-to-stack f 'icalendar)) + results)) + `(let (output-files) + (mapc (lambda (file) + (with-current-buffer (org-get-agenda-file-buffer file) + (push (expand-file-name (org-icalendar-export-to-ics)) + output-files))) + ',files) + output-files))) + (let ((files (org-agenda-files t))) + (org-agenda-prepare-buffers files) + (unwind-protect + (mapc (lambda (file) + (catch 'nextfile + (org-check-agenda-file file) + (with-current-buffer (org-get-agenda-file-buffer file) + (org-icalendar-export-to-ics)))) + files) + (org-release-buffers org-agenda-new-buffers))))) + +;;;###autoload +(defun org-icalendar-combine-agenda-files (&optional async) + "Combine all agenda files into a single iCalendar file. + +A non-nil optional argument ASYNC means the process should happen +asynchronously. The resulting file should be accessible through +the `org-export-stack' interface. + +The file is stored under the name chosen in +`org-icalendar-combined-agenda-file'." + (interactive) + (if async + (let ((files (org-remove-if-not 'file-exists-p (org-agenda-files t)))) + (org-export-async-start + (lambda (dummy) + (org-export-add-to-stack + (expand-file-name org-icalendar-combined-agenda-file) + 'icalendar)) + `(apply 'org-icalendar--combine-files nil ',files))) + (apply 'org-icalendar--combine-files nil (org-agenda-files t)))) + +(defun org-icalendar-export-current-agenda (file) + "Export current agenda view to an iCalendar FILE. +This function assumes major mode for current buffer is +`org-agenda-mode'." + (let (org-export-babel-evaluate ; Don't evaluate Babel block + (org-icalendar-combined-agenda-file file) + (marker-list + ;; Collect the markers pointing to entries in the current + ;; agenda buffer. + (let (markers) + (save-excursion + (goto-char (point-min)) + (while (not (eobp)) + (let ((m (or (org-get-at-bol 'org-hd-marker) + (org-get-at-bol 'org-marker)))) + (and m (push m markers))) + (beginning-of-line 2))) + (nreverse markers)))) + (apply 'org-icalendar--combine-files + ;; Build restriction alist. + (let (restriction) + ;; Sort markers in each association within RESTRICTION. + (mapcar (lambda (x) (setcdr x (sort (copy-sequence (cdr x)) '<)) x) + (dolist (m marker-list restriction) + (let* ((pos (marker-position m)) + (file (buffer-file-name + (org-base-buffer (marker-buffer m)))) + (file-markers (assoc file restriction))) + ;; Add POS in FILE association if one exists + ;; or create a new association for FILE. + (if file-markers (push pos (cdr file-markers)) + (push (list file pos) restriction)))))) + (org-agenda-files nil 'ifmode)))) + +(defun org-icalendar--combine-files (restriction &rest files) + "Combine entries from multiple files into an iCalendar file. +RESTRICTION, when non-nil, is an alist where key is a file name +and value a list of buffer positions pointing to entries that +should appear in the calendar. It only makes sense if the +function was called from an agenda buffer. FILES is a list of +files to build the calendar from." + (org-agenda-prepare-buffers files) + (unwind-protect + (progn + (with-temp-file org-icalendar-combined-agenda-file + (insert + (org-icalendar--vcalendar + ;; Name. + org-icalendar-combined-name + ;; Owner. + user-full-name + ;; Timezone. + (or (org-string-nw-p org-icalendar-timezone) + (cadr (current-time-zone))) + ;; Description. + org-icalendar-combined-description + ;; Contents. + (concat + ;; Agenda contents. + (mapconcat + (lambda (file) + (catch 'nextfile + (org-check-agenda-file file) + (with-current-buffer (org-get-agenda-file-buffer file) + (let ((marks (cdr (assoc (expand-file-name file) + restriction)))) + ;; Create ID if necessary. + (when org-icalendar-store-UID + (org-icalendar-create-uid file t marks)) + (unless (and restriction (not marks)) + ;; Add a hook adding :ICALENDAR_MARK: property + ;; to each entry appearing in agenda view. + ;; Use `apply-partially' because the function + ;; still has to accept one argument. + (let ((org-export-before-processing-hook + (cons (apply-partially + (lambda (m-list dummy) + (mapc (lambda (m) + (org-entry-put + m "ICALENDAR-MARK" "t")) + m-list)) + (sort marks '>)) + org-export-before-processing-hook))) + (org-export-as + 'icalendar nil nil t + (list :ascii-charset 'utf-8 + :icalendar-agenda-view restriction)))))))) + files "") + ;; BBDB anniversaries. + (when (and org-icalendar-include-bbdb-anniversaries + (require 'org-bbdb nil t)) + (with-temp-buffer + (org-bbdb-anniv-export-ical) + (buffer-string))))))) + (run-hook-with-args 'org-icalendar-after-save-hook + org-icalendar-combined-agenda-file)) + (org-release-buffers org-agenda-new-buffers))) + + +(provide 'ox-icalendar) + +;; Local variables: +;; generated-autoload-file: "org-loaddefs.el" +;; End: + +;;; ox-icalendar.el ends here diff --git a/lisp/org/ox-latex.el b/lisp/org/ox-latex.el new file mode 100644 index 00000000000..1da7f9bbc6d --- /dev/null +++ b/lisp/org/ox-latex.el @@ -0,0 +1,2920 @@ +;;; ox-latex.el --- LaTeX Back-End for Org Export Engine + +;; Copyright (C) 2011-2013 Free Software Foundation, Inc. + +;; Author: Nicolas Goaziou +;; Keywords: outlines, hypermedia, calendar, wp + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: +;; +;; See Org manual for details. + +;;; Code: + +(eval-when-compile (require 'cl)) +(require 'ox) +(require 'ox-publish) + +(defvar org-latex-default-packages-alist) +(defvar org-latex-packages-alist) +(defvar orgtbl-exp-regexp) + + + +;;; Define Back-End + +(org-export-define-backend 'latex + '((bold . org-latex-bold) + (center-block . org-latex-center-block) + (clock . org-latex-clock) + (code . org-latex-code) + (comment . (lambda (&rest args) "")) + (comment-block . (lambda (&rest args) "")) + (drawer . org-latex-drawer) + (dynamic-block . org-latex-dynamic-block) + (entity . org-latex-entity) + (example-block . org-latex-example-block) + (export-block . org-latex-export-block) + (export-snippet . org-latex-export-snippet) + (fixed-width . org-latex-fixed-width) + (footnote-definition . org-latex-footnote-definition) + (footnote-reference . org-latex-footnote-reference) + (headline . org-latex-headline) + (horizontal-rule . org-latex-horizontal-rule) + (inline-src-block . org-latex-inline-src-block) + (inlinetask . org-latex-inlinetask) + (italic . org-latex-italic) + (item . org-latex-item) + (keyword . org-latex-keyword) + (latex-environment . org-latex-latex-environment) + (latex-fragment . org-latex-latex-fragment) + (line-break . org-latex-line-break) + (link . org-latex-link) + (paragraph . org-latex-paragraph) + (plain-list . org-latex-plain-list) + (plain-text . org-latex-plain-text) + (planning . org-latex-planning) + (property-drawer . (lambda (&rest args) "")) + (quote-block . org-latex-quote-block) + (quote-section . org-latex-quote-section) + (radio-target . org-latex-radio-target) + (section . org-latex-section) + (special-block . org-latex-special-block) + (src-block . org-latex-src-block) + (statistics-cookie . org-latex-statistics-cookie) + (strike-through . org-latex-strike-through) + (subscript . org-latex-subscript) + (superscript . org-latex-superscript) + (table . org-latex-table) + (table-cell . org-latex-table-cell) + (table-row . org-latex-table-row) + (target . org-latex-target) + (template . org-latex-template) + (timestamp . org-latex-timestamp) + (underline . org-latex-underline) + (verbatim . org-latex-verbatim) + (verse-block . org-latex-verse-block)) + :export-block '("LATEX" "TEX") + :menu-entry + '(?l "Export to LaTeX" + ((?L "As LaTeX buffer" org-latex-export-as-latex) + (?l "As LaTeX file" org-latex-export-to-latex) + (?p "As PDF file" org-latex-export-to-pdf) + (?o "As PDF file and open" + (lambda (a s v b) + (if a (org-latex-export-to-pdf t s v b) + (org-open-file (org-latex-export-to-pdf nil s v b))))))) + :options-alist '((:latex-class "LATEX_CLASS" nil org-latex-default-class t) + (:latex-class-options "LATEX_CLASS_OPTIONS" nil nil t) + (:latex-header "LATEX_HEADER" nil nil newline) + (:latex-header-extra "LATEX_HEADER_EXTRA" nil nil newline) + (:latex-hyperref-p nil "texht" org-latex-with-hyperref t) + ;; Redefine regular options. + (:date "DATE" nil "\\today" t))) + + + +;;; Internal Variables + +(defconst org-latex-babel-language-alist + '(("af" . "afrikaans") + ("bg" . "bulgarian") + ("bt-br" . "brazilian") + ("ca" . "catalan") + ("cs" . "czech") + ("cy" . "welsh") + ("da" . "danish") + ("de" . "germanb") + ("de-at" . "naustrian") + ("de-de" . "ngerman") + ("el" . "greek") + ("en" . "english") + ("en-au" . "australian") + ("en-ca" . "canadian") + ("en-gb" . "british") + ("en-ie" . "irish") + ("en-nz" . "newzealand") + ("en-us" . "american") + ("es" . "spanish") + ("et" . "estonian") + ("eu" . "basque") + ("fi" . "finnish") + ("fr" . "frenchb") + ("fr-ca" . "canadien") + ("gl" . "galician") + ("hr" . "croatian") + ("hu" . "hungarian") + ("id" . "indonesian") + ("is" . "icelandic") + ("it" . "italian") + ("la" . "latin") + ("ms" . "malay") + ("nl" . "dutch") + ("nb" . "norsk") + ("nn" . "nynorsk") + ("no" . "norsk") + ("pl" . "polish") + ("pt" . "portuguese") + ("ro" . "romanian") + ("ru" . "russian") + ("sa" . "sanskrit") + ("sb" . "uppersorbian") + ("sk" . "slovak") + ("sl" . "slovene") + ("sq" . "albanian") + ("sr" . "serbian") + ("sv" . "swedish") + ("ta" . "tamil") + ("tr" . "turkish") + ("uk" . "ukrainian")) + "Alist between language code and corresponding Babel option.") + +(defconst org-latex-table-matrix-macros '(("bordermatrix" . "\\cr") + ("qbordermatrix" . "\\cr") + ("kbordermatrix" . "\\\\")) + "Alist between matrix macros and their row ending.") + + + +;;; User Configurable Variables + +(defgroup org-export-latex nil + "Options for exporting Org mode files to LaTeX." + :tag "Org Export LaTeX" + :group 'org-export) + + +;;;; Preamble + +(defcustom org-latex-default-class "article" + "The default LaTeX class." + :group 'org-export-latex + :type '(string :tag "LaTeX class")) + +(defcustom org-latex-classes + '(("article" + "\\documentclass[11pt]{article}" + ("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}") + ("\\paragraph{%s}" . "\\paragraph*{%s}") + ("\\subparagraph{%s}" . "\\subparagraph*{%s}")) + ("report" + "\\documentclass[11pt]{report}" + ("\\part{%s}" . "\\part*{%s}") + ("\\chapter{%s}" . "\\chapter*{%s}") + ("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}")) + ("book" + "\\documentclass[11pt]{book}" + ("\\part{%s}" . "\\part*{%s}") + ("\\chapter{%s}" . "\\chapter*{%s}") + ("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}"))) + "Alist of LaTeX classes and associated header and structure. +If #+LATEX_CLASS is set in the buffer, use its value and the +associated information. Here is the structure of each cell: + + \(class-name + header-string + \(numbered-section . unnumbered-section) + ...) + +The header string +----------------- + +The HEADER-STRING is the header that will be inserted into the +LaTeX file. It should contain the \\documentclass macro, and +anything else that is needed for this setup. To this header, the +following commands will be added: + +- Calls to \\usepackage for all packages mentioned in the + variables `org-latex-default-packages-alist' and + `org-latex-packages-alist'. Thus, your header definitions + should avoid to also request these packages. + +- Lines specified via \"#+LATEX_HEADER:\" and + \"#+LATEX_HEADER_EXTRA:\" keywords. + +If you need more control about the sequence in which the header +is built up, or if you want to exclude one of these building +blocks for a particular class, you can use the following +macro-like placeholders. + + [DEFAULT-PACKAGES] \\usepackage statements for default packages + [NO-DEFAULT-PACKAGES] do not include any of the default packages + [PACKAGES] \\usepackage statements for packages + [NO-PACKAGES] do not include the packages + [EXTRA] the stuff from #+LATEX_HEADER(_EXTRA) + [NO-EXTRA] do not include #+LATEX_HEADER(_EXTRA) stuff + +So a header like + + \\documentclass{article} + [NO-DEFAULT-PACKAGES] + [EXTRA] + \\providecommand{\\alert}[1]{\\textbf{#1}} + [PACKAGES] + +will omit the default packages, and will include the +#+LATEX_HEADER and #+LATEX_HEADER_EXTRA lines, then have a call +to \\providecommand, and then place \\usepackage commands based +on the content of `org-latex-packages-alist'. + +If your header, `org-latex-default-packages-alist' or +`org-latex-packages-alist' inserts \"\\usepackage[AUTO]{inputenc}\", +AUTO will automatically be replaced with a coding system derived +from `buffer-file-coding-system'. See also the variable +`org-latex-inputenc-alist' for a way to influence this mechanism. + +Likewise, if your header contains \"\\usepackage[AUTO]{babel}\", +AUTO will be replaced with the language related to the language +code specified by `org-export-default-language', which see. Note +that constructions such as \"\\usepackage[french,AUTO,english]{babel}\" +are permitted. + +The sectioning structure +------------------------ + +The sectioning structure of the class is given by the elements +following the header string. For each sectioning level, a number +of strings is specified. A %s formatter is mandatory in each +section string and will be replaced by the title of the section. + +Instead of a cons cell (numbered . unnumbered), you can also +provide a list of 2 or 4 elements, + + \(numbered-open numbered-close) + +or + + \(numbered-open numbered-close unnumbered-open unnumbered-close) + +providing opening and closing strings for a LaTeX environment +that should represent the document section. The opening clause +should have a %s to represent the section title. + +Instead of a list of sectioning commands, you can also specify +a function name. That function will be called with two +parameters, the (reduced) level of the headline, and a predicate +non-nil when the headline should be numbered. It must return +a format string in which the section title will be added." + :group 'org-export-latex + :type '(repeat + (list (string :tag "LaTeX class") + (string :tag "LaTeX header") + (repeat :tag "Levels" :inline t + (choice + (cons :tag "Heading" + (string :tag " numbered") + (string :tag "unnumbered")) + (list :tag "Environment" + (string :tag "Opening (numbered)") + (string :tag "Closing (numbered)") + (string :tag "Opening (unnumbered)") + (string :tag "Closing (unnumbered)")) + (function :tag "Hook computing sectioning")))))) + +(defcustom org-latex-inputenc-alist nil + "Alist of inputenc coding system names, and what should really be used. +For example, adding an entry + + (\"utf8\" . \"utf8x\") + +will cause \\usepackage[utf8x]{inputenc} to be used for buffers that +are written as utf8 files." + :group 'org-export-latex + :type '(repeat + (cons + (string :tag "Derived from buffer") + (string :tag "Use this instead")))) + +(defcustom org-latex-title-command "\\maketitle" + "The command used to insert the title just after \\begin{document}. +If this string contains the formatting specification \"%s\" then +it will be used as a formatting string, passing the title as an +argument." + :group 'org-export-latex + :type 'string) + +(defcustom org-latex-toc-command "\\tableofcontents\n\n" + "LaTeX command to set the table of contents, list of figures, etc. +This command only applies to the table of contents generated with +the toc:nil option, not to those generated with #+TOC keyword." + :group 'org-export-latex + :type 'string) + +(defcustom org-latex-with-hyperref t + "Toggle insertion of \\hypersetup{...} in the preamble." + :group 'org-export-latex + :type 'boolean) + +;;;; Headline + +(defcustom org-latex-format-headline-function + 'org-latex-format-headline-default-function + "Function for formatting the headline's text. + +This function will be called with 5 arguments: +TODO the todo keyword (string or nil). +TODO-TYPE the type of todo (symbol: `todo', `done', nil) +PRIORITY the priority of the headline (integer or nil) +TEXT the main headline text (string). +TAGS the tags as a list of strings (list of strings or nil). + +The function result will be used in the section format string. + +Use `org-latex-format-headline-default-function' by default, +which format headlines like for Org version prior to 8.0." + :group 'org-export-latex + :version "24.4" + :package-version '(Org . "8.0") + :type 'function) + + +;;;; Footnotes + +(defcustom org-latex-footnote-separator "\\textsuperscript{,}\\," + "Text used to separate footnotes." + :group 'org-export-latex + :type 'string) + + +;;;; Timestamps + +(defcustom org-latex-active-timestamp-format "\\textit{%s}" + "A printf format string to be applied to active timestamps." + :group 'org-export-latex + :type 'string) + +(defcustom org-latex-inactive-timestamp-format "\\textit{%s}" + "A printf format string to be applied to inactive timestamps." + :group 'org-export-latex + :type 'string) + +(defcustom org-latex-diary-timestamp-format "\\textit{%s}" + "A printf format string to be applied to diary timestamps." + :group 'org-export-latex + :type 'string) + + +;;;; Links + +(defcustom org-latex-image-default-option "" + "Default option for images." + :group 'org-export-latex + :version "24.4" + :package-version '(Org . "8.0") + :type 'string) + +(defcustom org-latex-image-default-width ".9\\linewidth" + "Default width for images. +This value will not be used if a height is provided." + :group 'org-export-latex + :version "24.4" + :package-version '(Org . "8.0") + :type 'string) + +(defcustom org-latex-image-default-height "" + "Default height for images. +This value will not be used if a width is provided, or if the +image is wrapped within a \"figure\" or \"wrapfigure\" +environment." + :group 'org-export-latex + :version "24.4" + :package-version '(Org . "8.0") + :type 'string) + +(defcustom org-latex-default-figure-position "htb" + "Default position for latex figures." + :group 'org-export-latex + :type 'string) + +(defcustom org-latex-inline-image-rules + '(("file" . "\\.\\(pdf\\|jpeg\\|jpg\\|png\\|ps\\|eps\\|tikz\\|pgf\\|svg\\)\\'")) + "Rules characterizing image files that can be inlined into LaTeX. + +A rule consists in an association whose key is the type of link +to consider, and value is a regexp that will be matched against +link's path. + +Note that, by default, the image extension *actually* allowed +depend on the way the LaTeX file is processed. When used with +pdflatex, pdf, jpg and png images are OK. When processing +through dvi to Postscript, only ps and eps are allowed. The +default we use here encompasses both." + :group 'org-export-latex + :version "24.4" + :package-version '(Org . "8.0") + :type '(alist :key-type (string :tag "Type") + :value-type (regexp :tag "Path"))) + +(defcustom org-latex-link-with-unknown-path-format "\\texttt{%s}" + "Format string for links with unknown path type." + :group 'org-export-latex + :type 'string) + + +;;;; Tables + +(defcustom org-latex-default-table-environment "tabular" + "Default environment used to build tables." + :group 'org-export-latex + :version "24.4" + :package-version '(Org . "8.0") + :type 'string) + +(defcustom org-latex-default-table-mode 'table + "Default mode for tables. + +Value can be a symbol among: + + `table' Regular LaTeX table. + + `math' In this mode, every cell is considered as being in math + mode and the complete table will be wrapped within a math + environment. It is particularly useful to write matrices. + + `inline-math' This mode is almost the same as `math', but the + math environment will be inlined. + + `verbatim' The table is exported as it appears in the Org + buffer, within a verbatim environment. + +This value can be overridden locally with, i.e. \":mode math\" in +LaTeX attributes. + +When modifying this variable, it may be useful to change +`org-latex-default-table-environment' accordingly." + :group 'org-export-latex + :version "24.4" + :package-version '(Org . "8.0") + :type '(choice (const :tag "Table" table) + (const :tag "Matrix" math) + (const :tag "Inline matrix" inline-math) + (const :tag "Verbatim" verbatim))) + +(defcustom org-latex-tables-centered t + "When non-nil, tables are exported in a center environment." + :group 'org-export-latex + :type 'boolean) + +(defcustom org-latex-tables-booktabs nil + "When non-nil, display tables in a formal \"booktabs\" style. +This option assumes that the \"booktabs\" package is properly +loaded in the header of the document. This value can be ignored +locally with \":booktabs t\" and \":booktabs nil\" LaTeX +attributes." + :group 'org-export-latex + :version "24.4" + :package-version '(Org . "8.0") + :type 'boolean) + +(defcustom org-latex-table-caption-above t + "When non-nil, place caption string at the beginning of the table. +Otherwise, place it near the end." + :group 'org-export-latex + :type 'boolean) + +(defcustom org-latex-table-scientific-notation "%s\\,(%s)" + "Format string to display numbers in scientific notation. +The format should have \"%s\" twice, for mantissa and exponent +\(i.e., \"%s\\\\times10^{%s}\"). + +When nil, no transformation is made." + :group 'org-export-latex + :version "24.4" + :package-version '(Org . "8.0") + :type '(choice + (string :tag "Format string") + (const :tag "No formatting"))) + + +;;;; Text markup + +(defcustom org-latex-text-markup-alist '((bold . "\\textbf{%s}") + (code . verb) + (italic . "\\emph{%s}") + (strike-through . "\\sout{%s}") + (underline . "\\uline{%s}") + (verbatim . protectedtexttt)) + "Alist of LaTeX expressions to convert text markup. + +The key must be a symbol among `bold', `code', `italic', +`strike-through', `underline' and `verbatim'. The value is +a formatting string to wrap fontified text with. + +Value can also be set to the following symbols: `verb' and +`protectedtexttt'. For the former, Org will use \"\\verb\" to +create a format string and select a delimiter character that +isn't in the string. For the latter, Org will use \"\\texttt\" +to typeset and try to protect special characters. + +If no association can be found for a given markup, text will be +returned as-is." + :group 'org-export-latex + :type 'alist + :options '(bold code italic strike-through underline verbatim)) + + +;;;; Drawers + +(defcustom org-latex-format-drawer-function nil + "Function called to format a drawer in LaTeX code. + +The function must accept two parameters: + NAME the drawer name, like \"LOGBOOK\" + CONTENTS the contents of the drawer. + +The function should return the string to be exported. + +For example, the variable could be set to the following function +in order to mimic default behaviour: + +\(defun org-latex-format-drawer-default \(name contents\) + \"Format a drawer element for LaTeX export.\" + contents\)" + :group 'org-export-latex + :type 'function) + + +;;;; Inlinetasks + +(defcustom org-latex-format-inlinetask-function nil + "Function called to format an inlinetask in LaTeX code. + +The function must accept six parameters: + TODO the todo keyword, as a string + TODO-TYPE the todo type, a symbol among `todo', `done' and nil. + PRIORITY the inlinetask priority, as a string + NAME the inlinetask name, as a string. + TAGS the inlinetask tags, as a list of strings. + CONTENTS the contents of the inlinetask, as a string. + +The function should return the string to be exported. + +For example, the variable could be set to the following function +in order to mimic default behaviour: + +\(defun org-latex-format-inlinetask \(todo type priority name tags contents\) +\"Format an inline task element for LaTeX export.\" + \(let ((full-title + \(concat + \(when todo + \(format \"\\\\textbf{\\\\textsf{\\\\textsc{%s}}} \" todo)) + \(when priority (format \"\\\\framebox{\\\\#%c} \" priority)) + title + \(when tags + \(format \"\\\\hfill{}\\\\textsc{:%s:}\" + \(mapconcat 'identity tags \":\"))))) + \(format (concat \"\\\\begin{center}\\n\" + \"\\\\fbox{\\n\" + \"\\\\begin{minipage}[c]{.6\\\\textwidth}\\n\" + \"%s\\n\\n\" + \"\\\\rule[.8em]{\\\\textwidth}{2pt}\\n\\n\" + \"%s\" + \"\\\\end{minipage}}\" + \"\\\\end{center}\") + full-title contents))" + :group 'org-export-latex + :type 'function) + + +;; Src blocks + +(defcustom org-latex-listings nil + "Non-nil means export source code using the listings package. + +This package will fontify source code, possibly even with color. +If you want to use this, you also need to make LaTeX use the +listings package, and if you want to have color, the color +package. Just add these to `org-latex-packages-alist', for +example using customize, or with something like: + + \(require 'ox-latex) + \(add-to-list 'org-latex-packages-alist '(\"\" \"listings\")) + \(add-to-list 'org-latex-packages-alist '(\"\" \"color\")) + +Alternatively, + + \(setq org-latex-listings 'minted) + +causes source code to be exported using the minted package as +opposed to listings. If you want to use minted, you need to add +the minted package to `org-latex-packages-alist', for example +using customize, or with + + \(require 'ox-latex) + \(add-to-list 'org-latex-packages-alist '(\"\" \"minted\")) + +In addition, it is necessary to install pygments +\(http://pygments.org), and to configure the variable +`org-latex-pdf-process' so that the -shell-escape option is +passed to pdflatex. + +The minted choice has possible repercussions on the preview of +latex fragments (see `org-preview-latex-fragment'). If you run +into previewing problems, please consult + + http://orgmode.org/worg/org-tutorials/org-latex-preview.html" + :group 'org-export-latex + :type '(choice + (const :tag "Use listings" t) + (const :tag "Use minted" minted) + (const :tag "Export verbatim" nil))) + +(defcustom org-latex-listings-langs + '((emacs-lisp "Lisp") (lisp "Lisp") (clojure "Lisp") + (c "C") (cc "C++") + (fortran "fortran") + (perl "Perl") (cperl "Perl") (python "Python") (ruby "Ruby") + (html "HTML") (xml "XML") + (tex "TeX") (latex "[LaTeX]TeX") + (shell-script "bash") + (gnuplot "Gnuplot") + (ocaml "Caml") (caml "Caml") + (sql "SQL") (sqlite "sql")) + "Alist mapping languages to their listing language counterpart. +The key is a symbol, the major mode symbol without the \"-mode\". +The value is the string that should be inserted as the language +parameter for the listings package. If the mode name and the +listings name are the same, the language does not need an entry +in this list - but it does not hurt if it is present." + :group 'org-export-latex + :type '(repeat + (list + (symbol :tag "Major mode ") + (string :tag "Listings language")))) + +(defcustom org-latex-listings-options nil + "Association list of options for the latex listings package. + +These options are supplied as a comma-separated list to the +\\lstset command. Each element of the association list should be +a list containing two strings: the name of the option, and the +value. For example, + + (setq org-latex-listings-options + '((\"basicstyle\" \"\\\\small\") + (\"keywordstyle\" \"\\\\color{black}\\\\bfseries\\\\underbar\"))) + +will typeset the code in a small size font with underlined, bold +black keywords. + +Note that the same options will be applied to blocks of all +languages." + :group 'org-export-latex + :type '(repeat + (list + (string :tag "Listings option name ") + (string :tag "Listings option value")))) + +(defcustom org-latex-minted-langs + '((emacs-lisp "common-lisp") + (cc "c++") + (cperl "perl") + (shell-script "bash") + (caml "ocaml")) + "Alist mapping languages to their minted language counterpart. +The key is a symbol, the major mode symbol without the \"-mode\". +The value is the string that should be inserted as the language +parameter for the minted package. If the mode name and the +listings name are the same, the language does not need an entry +in this list - but it does not hurt if it is present. + +Note that minted uses all lower case for language identifiers, +and that the full list of language identifiers can be obtained +with: + + pygmentize -L lexers" + :group 'org-export-latex + :type '(repeat + (list + (symbol :tag "Major mode ") + (string :tag "Minted language")))) + +(defcustom org-latex-minted-options nil + "Association list of options for the latex minted package. + +These options are supplied within square brackets in +\\begin{minted} environments. Each element of the alist should +be a list containing two strings: the name of the option, and the +value. For example, + + \(setq org-latex-minted-options + '\((\"bgcolor\" \"bg\") \(\"frame\" \"lines\"))) + +will result in src blocks being exported with + +\\begin{minted}[bgcolor=bg,frame=lines]{} + +as the start of the minted environment. Note that the same +options will be applied to blocks of all languages." + :group 'org-export-latex + :type '(repeat + (list + (string :tag "Minted option name ") + (string :tag "Minted option value")))) + +(defvar org-latex-custom-lang-environments nil + "Alist mapping languages to language-specific LaTeX environments. + +It is used during export of src blocks by the listings and minted +latex packages. For example, + + \(setq org-latex-custom-lang-environments + '\(\(python \"pythoncode\"\)\)\) + +would have the effect that if org encounters begin_src python +during latex export it will output + + \\begin{pythoncode} + + \\end{pythoncode}") + + +;;;; Compilation + +(defcustom org-latex-pdf-process + '("pdflatex -interaction nonstopmode -output-directory %o %f" + "pdflatex -interaction nonstopmode -output-directory %o %f" + "pdflatex -interaction nonstopmode -output-directory %o %f") + "Commands to process a LaTeX file to a PDF file. +This is a list of strings, each of them will be given to the +shell as a command. %f in the command will be replaced by the +full file name, %b by the file base name (i.e. without directory +and extension parts) and %o by the base directory of the file. + +The reason why this is a list is that it usually takes several +runs of `pdflatex', maybe mixed with a call to `bibtex'. Org +does not have a clever mechanism to detect which of these +commands have to be run to get to a stable result, and it also +does not do any error checking. + +By default, Org uses 3 runs of `pdflatex' to do the processing. +If you have texi2dvi on your system and if that does not cause +the infamous egrep/locale bug: + + http://lists.gnu.org/archive/html/bug-texinfo/2010-03/msg00031.html + +then `texi2dvi' is the superior choice as it automates the LaTeX +build process by calling the \"correct\" combinations of +auxiliary programs. Org does offer `texi2dvi' as one of the +customize options. Alternatively, `rubber' and `latexmk' also +provide similar functionality. The latter supports `biber' out +of the box. + +Alternatively, this may be a Lisp function that does the +processing, so you could use this to apply the machinery of +AUCTeX or the Emacs LaTeX mode. This function should accept the +file name as its single argument." + :group 'org-export-pdf + :type '(choice + (repeat :tag "Shell command sequence" + (string :tag "Shell command")) + (const :tag "2 runs of pdflatex" + ("pdflatex -interaction nonstopmode -output-directory %o %f" + "pdflatex -interaction nonstopmode -output-directory %o %f")) + (const :tag "3 runs of pdflatex" + ("pdflatex -interaction nonstopmode -output-directory %o %f" + "pdflatex -interaction nonstopmode -output-directory %o %f" + "pdflatex -interaction nonstopmode -output-directory %o %f")) + (const :tag "pdflatex,bibtex,pdflatex,pdflatex" + ("pdflatex -interaction nonstopmode -output-directory %o %f" + "bibtex %b" + "pdflatex -interaction nonstopmode -output-directory %o %f" + "pdflatex -interaction nonstopmode -output-directory %o %f")) + (const :tag "2 runs of xelatex" + ("xelatex -interaction nonstopmode -output-directory %o %f" + "xelatex -interaction nonstopmode -output-directory %o %f")) + (const :tag "3 runs of xelatex" + ("xelatex -interaction nonstopmode -output-directory %o %f" + "xelatex -interaction nonstopmode -output-directory %o %f" + "xelatex -interaction nonstopmode -output-directory %o %f")) + (const :tag "xelatex,bibtex,xelatex,xelatex" + ("xelatex -interaction nonstopmode -output-directory %o %f" + "bibtex %b" + "xelatex -interaction nonstopmode -output-directory %o %f" + "xelatex -interaction nonstopmode -output-directory %o %f")) + (const :tag "texi2dvi" + ("texi2dvi -p -b -V %f")) + (const :tag "rubber" + ("rubber -d --into %o %f")) + (const :tag "latexmk" + ("latexmk -g -pdf %f")) + (function))) + +(defcustom org-latex-logfiles-extensions + '("aux" "idx" "log" "out" "toc" "nav" "snm" "vrb") + "The list of file extensions to consider as LaTeX logfiles. +The logfiles will be remove if `org-latex-remove-logfiles' is +non-nil." + :group 'org-export-latex + :type '(repeat (string :tag "Extension"))) + +(defcustom org-latex-remove-logfiles t + "Non-nil means remove the logfiles produced by PDF production. +By default, logfiles are files with these extensions: .aux, .idx, +.log, .out, .toc, .nav, .snm and .vrb. To define the set of +logfiles to remove, set `org-latex-logfiles-extensions'." + :group 'org-export-latex + :type 'boolean) + +(defcustom org-latex-known-errors + '(("Reference.*?undefined" . "[undefined reference]") + ("Citation.*?undefined" . "[undefined citation]") + ("Undefined control sequence" . "[undefined control sequence]") + ("^! LaTeX.*?Error" . "[LaTeX error]") + ("^! Package.*?Error" . "[package error]") + ("Runaway argument" . "Runaway argument")) + "Alist of regular expressions and associated messages for the user. +The regular expressions are used to find possible errors in the +log of a latex-run." + :group 'org-export-latex + :version "24.4" + :package-version '(Org . "8.0") + :type '(repeat + (cons + (string :tag "Regexp") + (string :tag "Message")))) + + + +;;; Internal Functions + +(defun org-latex--caption/label-string (element info) + "Return caption and label LaTeX string for ELEMENT. + +INFO is a plist holding contextual information. If there's no +caption nor label, return the empty string. + +For non-floats, see `org-latex--wrap-label'." + (let* ((label (org-element-property :name element)) + (label-str (if (not (org-string-nw-p label)) "" + (format "\\label{%s}" + (org-export-solidify-link-text label)))) + (main (org-export-get-caption element)) + (short (org-export-get-caption element t)) + (caption-from-attr-latex (org-export-read-attribute :attr_latex element :caption))) + (cond + ((org-string-nw-p caption-from-attr-latex) + (concat caption-from-attr-latex "\n")) + ((and (not main) (equal label-str "")) "") + ((not main) (concat label-str "\n")) + ;; Option caption format with short name. + (short (format "\\caption[%s]{%s%s}\n" + (org-export-data short info) + label-str + (org-export-data main info))) + ;; Standard caption format. + (t (format "\\caption{%s%s}\n" label-str (org-export-data main info)))))) + +(defun org-latex-guess-inputenc (header) + "Set the coding system in inputenc to what the buffer is. + +HEADER is the LaTeX header string. This function only applies +when specified inputenc option is \"AUTO\". + +Return the new header, as a string." + (let* ((cs (or (ignore-errors + (latexenc-coding-system-to-inputenc + (or org-export-coding-system buffer-file-coding-system))) + "utf8"))) + (if (not cs) header + ;; First translate if that is requested. + (setq cs (or (cdr (assoc cs org-latex-inputenc-alist)) cs)) + ;; Then find the \usepackage statement and replace the option. + (replace-regexp-in-string "\\\\usepackage\\[\\(AUTO\\)\\]{inputenc}" + cs header t nil 1)))) + +(defun org-latex-guess-babel-language (header info) + "Set Babel's language according to LANGUAGE keyword. + +HEADER is the LaTeX header string. INFO is the plist used as +a communication channel. + +Insertion of guessed language only happens when Babel package has +explicitly been loaded. Then it is added to the rest of +package's options. + +The argument to Babel may be \"AUTO\" which is then replaced with +the language of the document or `org-export-default-language' +unless language in question is already loaded. + +Return the new header." + (let ((language-code (plist-get info :language))) + ;; If no language is set or Babel package is not loaded, return + ;; HEADER as-is. + (if (or (not (stringp language-code)) + (not (string-match "\\\\usepackage\\[\\(.*\\)\\]{babel}" header))) + header + (let ((options (save-match-data + (org-split-string (match-string 1 header) ",[ \t]*"))) + (language (cdr (assoc language-code + org-latex-babel-language-alist)))) + ;; If LANGUAGE is already loaded, return header without AUTO. + ;; Otherwise, replace AUTO with language or append language if + ;; AUTO is not present. + (replace-match + (mapconcat (lambda (option) (if (equal "AUTO" option) language option)) + (cond ((member language options) (delete "AUTO" options)) + ((member "AUTO" options) options) + (t (append options (list language)))) + ", ") + t nil header 1))))) + +(defun org-latex--find-verb-separator (s) + "Return a character not used in string S. +This is used to choose a separator for constructs like \\verb." + (let ((ll "~,./?;':\"|!@#%^&-_=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ<>()[]{}")) + (loop for c across ll + when (not (string-match (regexp-quote (char-to-string c)) s)) + return (char-to-string c)))) + +(defun org-latex--make-option-string (options) + "Return a comma separated string of keywords and values. +OPTIONS is an alist where the key is the options keyword as +a string, and the value a list containing the keyword value, or +nil." + (mapconcat (lambda (pair) + (concat (first pair) + (when (> (length (second pair)) 0) + (concat "=" (second pair))))) + options + ",")) + +(defun org-latex--wrap-label (element output) + "Wrap label associated to ELEMENT around OUTPUT, if appropriate. +This function shouldn't be used for floats. See +`org-latex--caption/label-string'." + (let ((label (org-element-property :name element))) + (if (not (and (org-string-nw-p output) (org-string-nw-p label))) output + (concat (format "\\label{%s}\n" (org-export-solidify-link-text label)) + output)))) + +(defun org-latex--text-markup (text markup) + "Format TEXT depending on MARKUP text markup. +See `org-latex-text-markup-alist' for details." + (let ((fmt (cdr (assq markup org-latex-text-markup-alist)))) + (cond + ;; No format string: Return raw text. + ((not fmt) text) + ;; Handle the `verb' special case: Find and appropriate separator + ;; and use "\\verb" command. + ((eq 'verb fmt) + (let ((separator (org-latex--find-verb-separator text))) + (concat "\\verb" separator text separator))) + ;; Handle the `protectedtexttt' special case: Protect some + ;; special chars and use "\texttt{%s}" format string. + ((eq 'protectedtexttt fmt) + (let ((start 0) + (trans '(("\\" . "\\textbackslash{}") + ("~" . "\\textasciitilde{}") + ("^" . "\\textasciicircum{}"))) + (rtn "") + char) + (while (string-match "[\\{}$%&_#~^]" text) + (setq char (match-string 0 text)) + (if (> (match-beginning 0) 0) + (setq rtn (concat rtn (substring text 0 (match-beginning 0))))) + (setq text (substring text (1+ (match-beginning 0)))) + (setq char (or (cdr (assoc char trans)) (concat "\\" char)) + rtn (concat rtn char))) + (setq text (concat rtn text) + fmt "\\texttt{%s}") + (while (string-match "--" text) + (setq text (replace-match "-{}-" t t text))) + (format fmt text))) + ;; Else use format string. + (t (format fmt text))))) + +(defun org-latex--delayed-footnotes-definitions (element info) + "Return footnotes definitions in ELEMENT as a string. + +INFO is a plist used as a communication channel. + +Footnotes definitions are returned within \"\\footnotetxt{}\" +commands. + +This function is used within constructs that don't support +\"\\footnote{}\" command (i.e. an item's tag). In that case, +\"\\footnotemark\" is used within the construct and the function +just outside of it." + (mapconcat + (lambda (ref) + (format + "\\footnotetext[%s]{%s}" + (org-export-get-footnote-number ref info) + (org-trim + (org-export-data + (org-export-get-footnote-definition ref info) info)))) + ;; Find every footnote reference in ELEMENT. + (let* (all-refs + search-refs ; For byte-compiler. + (search-refs + (function + (lambda (data) + ;; Return a list of all footnote references never seen + ;; before in DATA. + (org-element-map data 'footnote-reference + (lambda (ref) + (when (org-export-footnote-first-reference-p ref info) + (push ref all-refs) + (when (eq (org-element-property :type ref) 'standard) + (funcall search-refs + (org-export-get-footnote-definition ref info))))) + info) + (reverse all-refs))))) + (funcall search-refs element)) + "")) + + + +;;; Template + +(defun org-latex-template (contents info) + "Return complete document string after LaTeX conversion. +CONTENTS is the transcoded contents string. INFO is a plist +holding export options." + (let ((title (org-export-data (plist-get info :title) info))) + (concat + ;; Time-stamp. + (and (plist-get info :time-stamp-file) + (format-time-string "%% Created %Y-%m-%d %a %H:%M\n")) + ;; Document class and packages. + (let* ((class (plist-get info :latex-class)) + (class-options (plist-get info :latex-class-options)) + (header (nth 1 (assoc class org-latex-classes))) + (document-class-string + (and (stringp header) + (if (not class-options) header + (replace-regexp-in-string + "^[ \t]*\\\\documentclass\\(\\(\\[[^]]*\\]\\)?\\)" + class-options header t nil 1))))) + (if (not document-class-string) + (user-error "Unknown LaTeX class `%s'" class) + (org-latex-guess-babel-language + (org-latex-guess-inputenc + (org-element-normalize-string + (org-splice-latex-header + document-class-string + org-latex-default-packages-alist + org-latex-packages-alist nil + (concat (org-element-normalize-string + (plist-get info :latex-header)) + (plist-get info :latex-header-extra))))) + info))) + ;; Possibly limit depth for headline numbering. + (let ((sec-num (plist-get info :section-numbers))) + (when (integerp sec-num) + (format "\\setcounter{secnumdepth}{%d}\n" sec-num))) + ;; Author. + (let ((author (and (plist-get info :with-author) + (let ((auth (plist-get info :author))) + (and auth (org-export-data auth info))))) + (email (and (plist-get info :with-email) + (org-export-data (plist-get info :email) info)))) + (cond ((and author email (not (string= "" email))) + (format "\\author{%s\\thanks{%s}}\n" author email)) + ((or author email) (format "\\author{%s}\n" (or author email))))) + ;; Date. + (let ((date (and (plist-get info :with-date) (org-export-get-date info)))) + (format "\\date{%s}\n" (org-export-data date info))) + ;; Title + (format "\\title{%s}\n" title) + ;; Hyperref options. + (when (plist-get info :latex-hyperref-p) + (format "\\hypersetup{\n pdfkeywords={%s},\n pdfsubject={%s},\n pdfcreator={%s}}\n" + (or (plist-get info :keywords) "") + (or (plist-get info :description) "") + (if (not (plist-get info :with-creator)) "" + (plist-get info :creator)))) + ;; Document start. + "\\begin{document}\n\n" + ;; Title command. + (org-element-normalize-string + (cond ((string= "" title) nil) + ((not (stringp org-latex-title-command)) nil) + ((string-match "\\(?:[^%]\\|^\\)%s" + org-latex-title-command) + (format org-latex-title-command title)) + (t org-latex-title-command))) + ;; Table of contents. + (let ((depth (plist-get info :with-toc))) + (when depth + (concat (when (wholenump depth) + (format "\\setcounter{tocdepth}{%d}\n" depth)) + org-latex-toc-command))) + ;; Document's body. + contents + ;; Creator. + (let ((creator-info (plist-get info :with-creator))) + (cond + ((not creator-info) "") + ((eq creator-info 'comment) + (format "%% %s\n" (plist-get info :creator))) + (t (concat (plist-get info :creator) "\n")))) + ;; Document end. + "\\end{document}"))) + + + +;;; Transcode Functions + +;;;; Bold + +(defun org-latex-bold (bold contents info) + "Transcode BOLD from Org to LaTeX. +CONTENTS is the text with bold markup. INFO is a plist holding +contextual information." + (org-latex--text-markup contents 'bold)) + + +;;;; Center Block + +(defun org-latex-center-block (center-block contents info) + "Transcode a CENTER-BLOCK element from Org to LaTeX. +CONTENTS holds the contents of the center block. INFO is a plist +holding contextual information." + (org-latex--wrap-label + center-block + (format "\\begin{center}\n%s\\end{center}" contents))) + + +;;;; Clock + +(defun org-latex-clock (clock contents info) + "Transcode a CLOCK element from Org to LaTeX. +CONTENTS is nil. INFO is a plist holding contextual +information." + (concat + "\\noindent" + (format "\\textbf{%s} " org-clock-string) + (format org-latex-inactive-timestamp-format + (concat (org-translate-time + (org-element-property :raw-value + (org-element-property :value clock))) + (let ((time (org-element-property :duration clock))) + (and time (format " (%s)" time))))) + "\\\\")) + + +;;;; Code + +(defun org-latex-code (code contents info) + "Transcode a CODE object from Org to LaTeX. +CONTENTS is nil. INFO is a plist used as a communication +channel." + (org-latex--text-markup (org-element-property :value code) 'code)) + + +;;;; Drawer + +(defun org-latex-drawer (drawer contents info) + "Transcode a DRAWER element from Org to LaTeX. +CONTENTS holds the contents of the block. INFO is a plist +holding contextual information." + (let* ((name (org-element-property :drawer-name drawer)) + (output (if (functionp org-latex-format-drawer-function) + (funcall org-latex-format-drawer-function + name contents) + ;; If there's no user defined function: simply + ;; display contents of the drawer. + contents))) + (org-latex--wrap-label drawer output))) + + +;;;; Dynamic Block + +(defun org-latex-dynamic-block (dynamic-block contents info) + "Transcode a DYNAMIC-BLOCK element from Org to LaTeX. +CONTENTS holds the contents of the block. INFO is a plist +holding contextual information. See `org-export-data'." + (org-latex--wrap-label dynamic-block contents)) + + +;;;; Entity + +(defun org-latex-entity (entity contents info) + "Transcode an ENTITY object from Org to LaTeX. +CONTENTS are the definition itself. INFO is a plist holding +contextual information." + (let ((ent (org-element-property :latex entity))) + (if (org-element-property :latex-math-p entity) (format "$%s$" ent) ent))) + + +;;;; Example Block + +(defun org-latex-example-block (example-block contents info) + "Transcode an EXAMPLE-BLOCK element from Org to LaTeX. +CONTENTS is nil. INFO is a plist holding contextual +information." + (when (org-string-nw-p (org-element-property :value example-block)) + (org-latex--wrap-label + example-block + (format "\\begin{verbatim}\n%s\\end{verbatim}" + (org-export-format-code-default example-block info))))) + + +;;;; Export Block + +(defun org-latex-export-block (export-block contents info) + "Transcode a EXPORT-BLOCK element from Org to LaTeX. +CONTENTS is nil. INFO is a plist holding contextual information." + (when (member (org-element-property :type export-block) '("LATEX" "TEX")) + (org-remove-indentation (org-element-property :value export-block)))) + + +;;;; Export Snippet + +(defun org-latex-export-snippet (export-snippet contents info) + "Transcode a EXPORT-SNIPPET object from Org to LaTeX. +CONTENTS is nil. INFO is a plist holding contextual information." + (when (eq (org-export-snippet-backend export-snippet) 'latex) + (org-element-property :value export-snippet))) + + +;;;; Fixed Width + +(defun org-latex-fixed-width (fixed-width contents info) + "Transcode a FIXED-WIDTH element from Org to LaTeX. +CONTENTS is nil. INFO is a plist holding contextual information." + (org-latex--wrap-label + fixed-width + (format "\\begin{verbatim}\n%s\\end{verbatim}" + (org-remove-indentation + (org-element-property :value fixed-width))))) + + +;;;; Footnote Reference + +(defun org-latex-footnote-reference (footnote-reference contents info) + "Transcode a FOOTNOTE-REFERENCE element from Org to LaTeX. +CONTENTS is nil. INFO is a plist holding contextual information." + (concat + ;; Insert separator between two footnotes in a row. + (let ((prev (org-export-get-previous-element footnote-reference info))) + (when (eq (org-element-type prev) 'footnote-reference) + org-latex-footnote-separator)) + (cond + ;; Use \footnotemark if the footnote has already been defined. + ((not (org-export-footnote-first-reference-p footnote-reference info)) + (format "\\footnotemark[%s]{}" + (org-export-get-footnote-number footnote-reference info))) + ;; Use \footnotemark if reference is within another footnote + ;; reference, footnote definition or table cell. + ((loop for parent in (org-export-get-genealogy footnote-reference) + thereis (memq (org-element-type parent) + '(footnote-reference footnote-definition table-cell))) + "\\footnotemark") + ;; Otherwise, define it with \footnote command. + (t + (let ((def (org-export-get-footnote-definition footnote-reference info))) + (concat + (format "\\footnote{%s}" (org-trim (org-export-data def info))) + ;; Retrieve all footnote references within the footnote and + ;; add their definition after it, since LaTeX doesn't support + ;; them inside. + (org-latex--delayed-footnotes-definitions def info))))))) + + +;;;; Headline + +(defun org-latex-headline (headline contents info) + "Transcode a HEADLINE element from Org to LaTeX. +CONTENTS holds the contents of the headline. INFO is a plist +holding contextual information." + (unless (org-element-property :footnote-section-p headline) + (let* ((class (plist-get info :latex-class)) + (level (org-export-get-relative-level headline info)) + (numberedp (org-export-numbered-headline-p headline info)) + (class-sectionning (assoc class org-latex-classes)) + ;; Section formatting will set two placeholders: one for + ;; the title and the other for the contents. + (section-fmt + (let ((sec (if (functionp (nth 2 class-sectionning)) + (funcall (nth 2 class-sectionning) level numberedp) + (nth (1+ level) class-sectionning)))) + (cond + ;; No section available for that LEVEL. + ((not sec) nil) + ;; Section format directly returned by a function. Add + ;; placeholder for contents. + ((stringp sec) (concat sec "\n%s")) + ;; (numbered-section . unnumbered-section) + ((not (consp (cdr sec))) + (concat (funcall (if numberedp #'car #'cdr) sec) "\n%s")) + ;; (numbered-open numbered-close) + ((= (length sec) 2) + (when numberedp (concat (car sec) "\n%s" (nth 1 sec)))) + ;; (num-in num-out no-num-in no-num-out) + ((= (length sec) 4) + (if numberedp (concat (car sec) "\n%s" (nth 1 sec)) + (concat (nth 2 sec) "\n%s" (nth 3 sec))))))) + (text (org-export-data (org-element-property :title headline) info)) + (todo + (and (plist-get info :with-todo-keywords) + (let ((todo (org-element-property :todo-keyword headline))) + (and todo (org-export-data todo info))))) + (todo-type (and todo (org-element-property :todo-type headline))) + (tags (and (plist-get info :with-tags) + (org-export-get-tags headline info))) + (priority (and (plist-get info :with-priority) + (org-element-property :priority headline))) + ;; Create the headline text along with a no-tag version. + ;; The latter is required to remove tags from toc. + (full-text (funcall org-latex-format-headline-function + todo todo-type priority text tags)) + ;; Associate \label to the headline for internal links. + (headline-label + (format "\\label{sec-%s}\n" + (mapconcat 'number-to-string + (org-export-get-headline-number headline info) + "-"))) + (pre-blanks + (make-string (org-element-property :pre-blank headline) 10))) + (if (or (not section-fmt) (org-export-low-level-p headline info)) + ;; This is a deep sub-tree: export it as a list item. Also + ;; export as items headlines for which no section format has + ;; been found. + (let ((low-level-body + (concat + ;; If headline is the first sibling, start a list. + (when (org-export-first-sibling-p headline info) + (format "\\begin{%s}\n" (if numberedp 'enumerate 'itemize))) + ;; Itemize headline + "\\item " full-text "\n" headline-label pre-blanks contents))) + ;; If headline is not the last sibling simply return + ;; LOW-LEVEL-BODY. Otherwise, also close the list, before + ;; any blank line. + (if (not (org-export-last-sibling-p headline info)) low-level-body + (replace-regexp-in-string + "[ \t\n]*\\'" + (format "\n\\\\end{%s}" (if numberedp 'enumerate 'itemize)) + low-level-body))) + ;; This is a standard headline. Export it as a section. Add + ;; an alternative heading when possible, and when this is not + ;; identical to the usual heading. + (let ((opt-title + (funcall org-latex-format-headline-function + todo todo-type priority + (org-export-data + (org-export-get-alt-title headline info) info) + (and (eq (plist-get info :with-tags) t) tags)))) + (if (and numberedp opt-title + (not (equal opt-title full-text)) + (string-match "\\`\\\\\\(.*?[^*]\\){" section-fmt)) + (format (replace-match "\\1[%s]" nil nil section-fmt 1) + ;; Replace square brackets with parenthesis + ;; since square brackets are not supported in + ;; optional arguments. + (replace-regexp-in-string + "\\[" "(" (replace-regexp-in-string "\\]" ")" opt-title)) + full-text + (concat headline-label pre-blanks contents)) + ;; Impossible to add an alternative heading. Fallback to + ;; regular sectioning format string. + (format section-fmt full-text + (concat headline-label pre-blanks contents)))))))) + +(defun org-latex-format-headline-default-function + (todo todo-type priority text tags) + "Default format function for a headline. +See `org-latex-format-headline-function' for details." + (concat + (and todo (format "{\\bfseries\\sffamily %s} " todo)) + (and priority (format "\\framebox{\\#%c} " priority)) + text + (and tags + (format "\\hfill{}\\textsc{%s}" (mapconcat 'identity tags ":"))))) + + +;;;; Horizontal Rule + +(defun org-latex-horizontal-rule (horizontal-rule contents info) + "Transcode an HORIZONTAL-RULE object from Org to LaTeX. +CONTENTS is nil. INFO is a plist holding contextual information." + (let ((attr (org-export-read-attribute :attr_latex horizontal-rule)) + (prev (org-export-get-previous-element horizontal-rule info))) + (concat + ;; Make sure the rule doesn't start at the end of the current + ;; line by separating it with a blank line from previous element. + (when (and prev + (let ((prev-blank (org-element-property :post-blank prev))) + (or (not prev-blank) (zerop prev-blank)))) + "\n") + (org-latex--wrap-label + horizontal-rule + (format "\\rule{%s}{%s}" + (or (plist-get attr :width) "\\linewidth") + (or (plist-get attr :thickness) "0.5pt")))))) + + +;;;; Inline Src Block + +(defun org-latex-inline-src-block (inline-src-block contents info) + "Transcode an INLINE-SRC-BLOCK element from Org to LaTeX. +CONTENTS holds the contents of the item. INFO is a plist holding +contextual information." + (let* ((code (org-element-property :value inline-src-block)) + (separator (org-latex--find-verb-separator code))) + (cond + ;; Do not use a special package: transcode it verbatim. + ((not org-latex-listings) + (concat "\\verb" separator code separator)) + ;; Use minted package. + ((eq org-latex-listings 'minted) + (let* ((org-lang (org-element-property :language inline-src-block)) + (mint-lang (or (cadr (assq (intern org-lang) + org-latex-minted-langs)) + org-lang)) + (options (org-latex--make-option-string + org-latex-minted-options))) + (concat (format "\\mint%s{%s}" + (if (string= options "") "" (format "[%s]" options)) + mint-lang) + separator code separator))) + ;; Use listings package. + (t + ;; Maybe translate language's name. + (let* ((org-lang (org-element-property :language inline-src-block)) + (lst-lang (or (cadr (assq (intern org-lang) + org-latex-listings-langs)) + org-lang)) + (options (org-latex--make-option-string + (append org-latex-listings-options + `(("language" ,lst-lang)))))) + (concat (format "\\lstinline[%s]" options) + separator code separator)))))) + + +;;;; Inlinetask + +(defun org-latex-inlinetask (inlinetask contents info) + "Transcode an INLINETASK element from Org to LaTeX. +CONTENTS holds the contents of the block. INFO is a plist +holding contextual information." + (let ((title (org-export-data (org-element-property :title inlinetask) info)) + (todo (and (plist-get info :with-todo-keywords) + (let ((todo (org-element-property :todo-keyword inlinetask))) + (and todo (org-export-data todo info))))) + (todo-type (org-element-property :todo-type inlinetask)) + (tags (and (plist-get info :with-tags) + (org-export-get-tags inlinetask info))) + (priority (and (plist-get info :with-priority) + (org-element-property :priority inlinetask)))) + ;; If `org-latex-format-inlinetask-function' is provided, call it + ;; with appropriate arguments. + (if (functionp org-latex-format-inlinetask-function) + (funcall org-latex-format-inlinetask-function + todo todo-type priority title tags contents) + ;; Otherwise, use a default template. + (org-latex--wrap-label + inlinetask + (let ((full-title + (concat + (when todo (format "\\textbf{\\textsf{\\textsc{%s}}} " todo)) + (when priority (format "\\framebox{\\#%c} " priority)) + title + (when tags (format "\\hfill{}\\textsc{:%s:}" + (mapconcat 'identity tags ":")))))) + (format (concat "\\begin{center}\n" + "\\fbox{\n" + "\\begin{minipage}[c]{.6\\textwidth}\n" + "%s\n\n" + "\\rule[.8em]{\\textwidth}{2pt}\n\n" + "%s" + "\\end{minipage}\n" + "}\n" + "\\end{center}") + full-title contents)))))) + + +;;;; Italic + +(defun org-latex-italic (italic contents info) + "Transcode ITALIC from Org to LaTeX. +CONTENTS is the text with italic markup. INFO is a plist holding +contextual information." + (org-latex--text-markup contents 'italic)) + + +;;;; Item + +(defun org-latex-item (item contents info) + "Transcode an ITEM element from Org to LaTeX. +CONTENTS holds the contents of the item. INFO is a plist holding +contextual information." + (let* ((counter + (let ((count (org-element-property :counter item)) + (level + ;; Determine level of current item to determine the + ;; correct LaTeX counter to use (enumi, enumii...). + (let ((parent item) (level 0)) + (while (memq (org-element-type + (setq parent (org-export-get-parent parent))) + '(plain-list item)) + (when (and (eq (org-element-type parent) 'plain-list) + (eq (org-element-property :type parent) + 'ordered)) + (incf level))) + level))) + (and count + (< level 5) + (format "\\setcounter{enum%s}{%s}\n" + (nth (1- level) '("i" "ii" "iii" "iv")) + (1- count))))) + (checkbox (case (org-element-property :checkbox item) + (on "$\\boxtimes$ ") + (off "$\\square$ ") + (trans "$\\boxminus$ "))) + (tag (let ((tag (org-element-property :tag item))) + ;; Check-boxes must belong to the tag. + (and tag (format "[{%s}] " + (concat checkbox + (org-export-data tag info))))))) + (concat counter "\\item" (or tag (concat " " checkbox)) + (and contents (org-trim contents)) + ;; If there are footnotes references in tag, be sure to + ;; add their definition at the end of the item. This + ;; workaround is necessary since "\footnote{}" command is + ;; not supported in tags. + (and tag + (org-latex--delayed-footnotes-definitions + (org-element-property :tag item) info))))) + + +;;;; Keyword + +(defun org-latex-keyword (keyword contents info) + "Transcode a KEYWORD element from Org to LaTeX. +CONTENTS is nil. INFO is a plist holding contextual information." + (let ((key (org-element-property :key keyword)) + (value (org-element-property :value keyword))) + (cond + ((string= key "LATEX") value) + ((string= key "INDEX") (format "\\index{%s}" value)) + ((string= key "TOC") + (let ((value (downcase value))) + (cond + ((string-match "\\" value) + (let ((depth (or (and (string-match "[0-9]+" value) + (string-to-number (match-string 0 value))) + (plist-get info :with-toc)))) + (concat + (when (wholenump depth) + (format "\\setcounter{tocdepth}{%s}\n" depth)) + "\\tableofcontents"))) + ((string= "tables" value) "\\listoftables") + ((string= "listings" value) + (cond + ((eq org-latex-listings 'minted) "\\listoflistings") + (org-latex-listings "\\lstlistoflistings") + ;; At the moment, src blocks with a caption are wrapped + ;; into a figure environment. + (t "\\listoffigures"))))))))) + + +;;;; Latex Environment + +(defun org-latex-latex-environment (latex-environment contents info) + "Transcode a LATEX-ENVIRONMENT element from Org to LaTeX. +CONTENTS is nil. INFO is a plist holding contextual information." + (when (plist-get info :with-latex) + (let ((label (org-element-property :name latex-environment)) + (value (org-remove-indentation + (org-element-property :value latex-environment)))) + (if (not (org-string-nw-p label)) value + ;; Environment is labelled: label must be within the environment + ;; (otherwise, a reference pointing to that element will count + ;; the section instead). + (with-temp-buffer + (insert value) + (goto-char (point-min)) + (forward-line) + (insert + (format "\\label{%s}\n" (org-export-solidify-link-text label))) + (buffer-string)))))) + + +;;;; Latex Fragment + +(defun org-latex-latex-fragment (latex-fragment contents info) + "Transcode a LATEX-FRAGMENT object from Org to LaTeX. +CONTENTS is nil. INFO is a plist holding contextual information." + (when (plist-get info :with-latex) + (org-element-property :value latex-fragment))) + + +;;;; Line Break + +(defun org-latex-line-break (line-break contents info) + "Transcode a LINE-BREAK object from Org to LaTeX. +CONTENTS is nil. INFO is a plist holding contextual information." + "\\\\\n") + + +;;;; Link + +(defun org-latex--inline-image (link info) + "Return LaTeX code for an inline image. +LINK is the link pointing to the inline image. INFO is a plist +used as a communication channel." + (let* ((parent (org-export-get-parent-element link)) + (path (let ((raw-path (org-element-property :path link))) + (if (not (file-name-absolute-p raw-path)) raw-path + (expand-file-name raw-path)))) + (filetype (file-name-extension path)) + (caption (org-latex--caption/label-string parent info)) + ;; Retrieve latex attributes from the element around. + (attr (org-export-read-attribute :attr_latex parent)) + (float (let ((float (plist-get attr :float))) + (cond ((and (not float) (plist-member attr :float)) nil) + ((string= float "wrap") 'wrap) + ((string= float "multicolumn") 'multicolumn) + ((or float + (org-element-property :caption parent) + (org-string-nw-p (plist-get attr :caption))) + 'figure)))) + (placement + (let ((place (plist-get attr :placement))) + (cond (place (format "%s" place)) + ((eq float 'wrap) "{l}{0.5\\textwidth}") + ((eq float 'figure) + (format "[%s]" org-latex-default-figure-position)) + (t "")))) + (comment-include (if (plist-get attr :comment-include) "%" "")) + ;; It is possible to specify width and height in the + ;; ATTR_LATEX line, and also via default variables. + (width (cond ((plist-get attr :width)) + ((plist-get attr :height) "") + ((eq float 'wrap) "0.48\\textwidth") + (t org-latex-image-default-width))) + (height (cond ((plist-get attr :height)) + ((or (plist-get attr :width) + (memq float '(figure wrap))) "") + (t org-latex-image-default-height))) + (options (let ((opt (or (plist-get attr :options) + org-latex-image-default-option))) + (if (not (string-match "\\`\\[\\(.*\\)\\]\\'" opt)) opt + (match-string 1 opt)))) + image-code) + (if (member filetype '("tikz" "pgf")) + ;; For tikz images: + ;; - use \input to read in image file. + ;; - if options are present, wrap in a tikzpicture environment. + ;; - if width or height are present, use \resizebox to change + ;; the image size. + (progn + (setq image-code (format "\\input{%s}" path)) + (when (org-string-nw-p options) + (setq image-code + (format "\\begin{tikzpicture}[%s]\n%s\n\\end{tikzpicture}" + options + image-code))) + (when (or (org-string-nw-p width) (org-string-nw-p height)) + (setq image-code (format "\\resizebox{%s}{%s}{%s}" + (if (org-string-nw-p width) width "!") + (if (org-string-nw-p height) height "!") + image-code)))) + ;; For other images: + ;; - add width and height to options. + ;; - include the image with \includegraphics. + (when (org-string-nw-p width) + (setq options (concat options ",width=" width))) + (when (org-string-nw-p height) + (setq options (concat options ",height=" height))) + (setq image-code + (format "\\includegraphics%s{%s}" + (cond ((not (org-string-nw-p options)) "") + ((= (aref options 0) ?,) + (format "[%s]"(substring options 1))) + (t (format "[%s]" options))) + path)) + (when (equal filetype "svg") + (setq image-code (replace-regexp-in-string "^\\\\includegraphics" + "\\includesvg" + image-code + nil t)) + (setq image-code (replace-regexp-in-string "\\.svg}" + "}" + image-code + nil t)))) + ;; Return proper string, depending on FLOAT. + (case float + (wrap (format "\\begin{wrapfigure}%s +\\centering +%s%s +%s\\end{wrapfigure}" placement comment-include image-code caption)) + (multicolumn (format "\\begin{figure*}%s +\\centering +%s%s +%s\\end{figure*}" placement comment-include image-code caption)) + (figure (format "\\begin{figure}%s +\\centering +%s%s +%s\\end{figure}" placement comment-include image-code caption)) + (otherwise image-code)))) + +(defun org-latex-link (link desc info) + "Transcode a LINK object from Org to LaTeX. + +DESC is the description part of the link, or the empty string. +INFO is a plist holding contextual information. See +`org-export-data'." + (let* ((type (org-element-property :type link)) + (raw-path (org-element-property :path link)) + ;; Ensure DESC really exists, or set it to nil. + (desc (and (not (string= desc "")) desc)) + (imagep (org-export-inline-image-p + link org-latex-inline-image-rules)) + (path (cond + ((member type '("http" "https" "ftp" "mailto")) + (concat type ":" raw-path)) + ((string= type "file") + (if (not (file-name-absolute-p raw-path)) raw-path + (concat "file://" (expand-file-name raw-path)))) + (t raw-path))) + protocol) + (cond + ;; Image file. + (imagep (org-latex--inline-image link info)) + ;; Radio link: Transcode target's contents and use them as link's + ;; description. + ((string= type "radio") + (let ((destination (org-export-resolve-radio-link link info))) + (when destination + (format "\\hyperref[%s]{%s}" + (org-export-solidify-link-text path) + (org-export-data (org-element-contents destination) info))))) + ;; Links pointing to a headline: Find destination and build + ;; appropriate referencing command. + ((member type '("custom-id" "fuzzy" "id")) + (let ((destination (if (string= type "fuzzy") + (org-export-resolve-fuzzy-link link info) + (org-export-resolve-id-link link info)))) + (case (org-element-type destination) + ;; Id link points to an external file. + (plain-text + (if desc (format "\\href{%s}{%s}" destination desc) + (format "\\url{%s}" destination))) + ;; Fuzzy link points nowhere. + ('nil + (format org-latex-link-with-unknown-path-format + (or desc + (org-export-data + (org-element-property :raw-link link) info)))) + ;; LINK points to a headline. If headlines are numbered + ;; and the link has no description, display headline's + ;; number. Otherwise, display description or headline's + ;; title. + (headline + (let ((label + (format "sec-%s" + (mapconcat + 'number-to-string + (org-export-get-headline-number destination info) + "-")))) + (if (and (plist-get info :section-numbers) (not desc)) + (format "\\ref{%s}" label) + (format "\\hyperref[%s]{%s}" label + (or desc + (org-export-data + (org-element-property :title destination) info)))))) + ;; Fuzzy link points to a target. Do as above. + (otherwise + (let ((path (org-export-solidify-link-text path))) + (if (not desc) (format "\\ref{%s}" path) + (format "\\hyperref[%s]{%s}" path desc))))))) + ;; Coderef: replace link with the reference name or the + ;; equivalent line number. + ((string= type "coderef") + (format (org-export-get-coderef-format path desc) + (org-export-resolve-coderef path info))) + ;; Link type is handled by a special function. + ((functionp (setq protocol (nth 2 (assoc type org-link-protocols)))) + (funcall protocol (org-link-unescape path) desc 'latex)) + ;; External link with a description part. + ((and path desc) (format "\\href{%s}{%s}" path desc)) + ;; External link without a description part. + (path (format "\\url{%s}" path)) + ;; No path, only description. Try to do something useful. + (t (format org-latex-link-with-unknown-path-format desc))))) + + +;;;; Paragraph + +(defun org-latex-paragraph (paragraph contents info) + "Transcode a PARAGRAPH element from Org to LaTeX. +CONTENTS is the contents of the paragraph, as a string. INFO is +the plist used as a communication channel." + contents) + + +;;;; Plain List + +(defun org-latex-plain-list (plain-list contents info) + "Transcode a PLAIN-LIST element from Org to LaTeX. +CONTENTS is the contents of the list. INFO is a plist holding +contextual information." + (let* ((type (org-element-property :type plain-list)) + (attr (org-export-read-attribute :attr_latex plain-list)) + (latex-type (let ((env (plist-get attr :environment))) + (cond (env (format "%s" env)) + ((eq type 'ordered) "enumerate") + ((eq type 'unordered) "itemize") + ((eq type 'descriptive) "description"))))) + (org-latex--wrap-label + plain-list + (format "\\begin{%s}%s\n%s\\end{%s}" + latex-type + ;; Put optional arguments, if any inside square brackets + ;; when necessary. + (let ((options (format "%s" (or (plist-get attr :options) "")))) + (cond ((equal options "") "") + ((string-match "\\`\\[.*\\]\\'" options) options) + (t (format "[%s]" options)))) + contents + latex-type)))) + + +;;;; Plain Text + +(defun org-latex-plain-text (text info) + "Transcode a TEXT string from Org to LaTeX. +TEXT is the string to transcode. INFO is a plist holding +contextual information." + (let ((specialp (plist-get info :with-special-strings)) + (output text)) + ;; Protect %, #, &, $, _, { and }. + (while (string-match "\\([^\\]\\|^\\)\\([%$#&{}_]\\)" output) + (setq output + (replace-match + (format "\\%s" (match-string 2 output)) nil t output 2))) + ;; Protect ^. + (setq output + (replace-regexp-in-string + "\\([^\\]\\|^\\)\\(\\^\\)" "\\\\^{}" output nil nil 2)) + ;; Protect \. If special strings are used, be careful not to + ;; protect "\" in "\-" constructs. + (let ((symbols (if specialp "-%$#&{}^_\\" "%$#&{}^_\\"))) + (setq output + (replace-regexp-in-string + (format "\\(?:[^\\]\\|^\\)\\(\\\\\\)\\(?:[^%s]\\|$\\)" symbols) + "$\\backslash$" output nil t 1))) + ;; Protect ~. + (setq output + (replace-regexp-in-string + "\\([^\\]\\|^\\)\\(~\\)" "\\textasciitilde{}" output nil t 2)) + ;; Activate smart quotes. Be sure to provide original TEXT string + ;; since OUTPUT may have been modified. + (when (plist-get info :with-smart-quotes) + (setq output (org-export-activate-smart-quotes output :latex info text))) + ;; LaTeX into \LaTeX{} and TeX into \TeX{}. + (let ((case-fold-search nil) + (start 0)) + (while (string-match "\\<\\(\\(?:La\\)?TeX\\)\\>" output start) + (setq output (replace-match + (format "\\%s{}" (match-string 1 output)) nil t output) + start (match-end 0)))) + ;; Convert special strings. + (when specialp + (setq output + (replace-regexp-in-string "\\.\\.\\." "\\ldots{}" output nil t))) + ;; Handle break preservation if required. + (when (plist-get info :preserve-breaks) + (setq output (replace-regexp-in-string + "\\(\\\\\\\\\\)?[ \t]*\n" " \\\\\\\\\n" output))) + ;; Return value. + output)) + + +;;;; Planning + +(defun org-latex-planning (planning contents info) + "Transcode a PLANNING element from Org to LaTeX. +CONTENTS is nil. INFO is a plist holding contextual +information." + (concat + "\\noindent" + (mapconcat + 'identity + (delq nil + (list + (let ((closed (org-element-property :closed planning))) + (when closed + (concat + (format "\\textbf{%s} " org-closed-string) + (format org-latex-inactive-timestamp-format + (org-translate-time + (org-element-property :raw-value closed)))))) + (let ((deadline (org-element-property :deadline planning))) + (when deadline + (concat + (format "\\textbf{%s} " org-deadline-string) + (format org-latex-active-timestamp-format + (org-translate-time + (org-element-property :raw-value deadline)))))) + (let ((scheduled (org-element-property :scheduled planning))) + (when scheduled + (concat + (format "\\textbf{%s} " org-scheduled-string) + (format org-latex-active-timestamp-format + (org-translate-time + (org-element-property :raw-value scheduled)))))))) + " ") + "\\\\")) + + +;;;; Quote Block + +(defun org-latex-quote-block (quote-block contents info) + "Transcode a QUOTE-BLOCK element from Org to LaTeX. +CONTENTS holds the contents of the block. INFO is a plist +holding contextual information." + (org-latex--wrap-label + quote-block + (format "\\begin{quote}\n%s\\end{quote}" contents))) + + +;;;; Quote Section + +(defun org-latex-quote-section (quote-section contents info) + "Transcode a QUOTE-SECTION element from Org to LaTeX. +CONTENTS is nil. INFO is a plist holding contextual information." + (let ((value (org-remove-indentation + (org-element-property :value quote-section)))) + (when value (format "\\begin{verbatim}\n%s\\end{verbatim}" value)))) + + +;;;; Radio Target + +(defun org-latex-radio-target (radio-target text info) + "Transcode a RADIO-TARGET object from Org to LaTeX. +TEXT is the text of the target. INFO is a plist holding +contextual information." + (format "\\label{%s}%s" + (org-export-solidify-link-text + (org-element-property :value radio-target)) + text)) + + +;;;; Section + +(defun org-latex-section (section contents info) + "Transcode a SECTION element from Org to LaTeX. +CONTENTS holds the contents of the section. INFO is a plist +holding contextual information." + contents) + + +;;;; Special Block + +(defun org-latex-special-block (special-block contents info) + "Transcode a SPECIAL-BLOCK element from Org to LaTeX. +CONTENTS holds the contents of the block. INFO is a plist +holding contextual information." + (let ((type (downcase (org-element-property :type special-block))) + (opt (org-export-read-attribute :attr_latex special-block :options))) + (concat (format "\\begin{%s}%s\n" type (or opt "")) + ;; Insert any label or caption within the block + ;; (otherwise, a reference pointing to that element will + ;; count the section instead). + (org-latex--caption/label-string special-block info) + contents + (format "\\end{%s}" type)))) + + +;;;; Src Block + +(defun org-latex-src-block (src-block contents info) + "Transcode a SRC-BLOCK element from Org to LaTeX. +CONTENTS holds the contents of the item. INFO is a plist holding +contextual information." + (when (org-string-nw-p (org-element-property :value src-block)) + (let* ((lang (org-element-property :language src-block)) + (caption (org-element-property :caption src-block)) + (label (org-element-property :name src-block)) + (custom-env (and lang + (cadr (assq (intern lang) + org-latex-custom-lang-environments)))) + (num-start (case (org-element-property :number-lines src-block) + (continued (org-export-get-loc src-block info)) + (new 0))) + (retain-labels (org-element-property :retain-labels src-block)) + (attributes (org-export-read-attribute :attr_latex src-block)) + (float (plist-get attributes :float))) + (cond + ;; Case 1. No source fontification. + ((not org-latex-listings) + (let* ((caption-str (org-latex--caption/label-string src-block info)) + (float-env + (cond ((and (not float) (plist-member attributes :float)) "%s") + ((string= "multicolumn" float) + (format "\\begin{figure*}[%s]\n%%s%s\n\\end{figure*}" + org-latex-default-figure-position + caption-str)) + ((or caption float) + (format "\\begin{figure}[H]\n%%s%s\n\\end{figure}" + caption-str)) + (t "%s")))) + (format + float-env + (concat (format "\\begin{verbatim}\n%s\\end{verbatim}" + (org-export-format-code-default src-block info)))))) + ;; Case 2. Custom environment. + (custom-env (format "\\begin{%s}\n%s\\end{%s}\n" + custom-env + (org-export-format-code-default src-block info) + custom-env)) + ;; Case 3. Use minted package. + ((eq org-latex-listings 'minted) + (let* ((caption-str (org-latex--caption/label-string src-block info)) + (float-env + (cond ((and (not float) (plist-member attributes :float)) "%s") + ((string= "multicolumn" float) + (format "\\begin{listing*}\n%%s\n%s\\end{listing*}" + caption-str)) + ((or caption float) + (format "\\begin{listing}[H]\n%%s\n%s\\end{listing}" + caption-str)) + (t "%s"))) + (body + (format + "\\begin{minted}[%s]{%s}\n%s\\end{minted}" + ;; Options. + (org-latex--make-option-string + (if (or (not num-start) + (assoc "linenos" org-latex-minted-options)) + org-latex-minted-options + (append + `(("linenos") + ("firstnumber" ,(number-to-string (1+ num-start)))) + org-latex-minted-options))) + ;; Language. + (or (cadr (assq (intern lang) org-latex-minted-langs)) lang) + ;; Source code. + (let* ((code-info (org-export-unravel-code src-block)) + (max-width + (apply 'max + (mapcar 'length + (org-split-string (car code-info) + "\n"))))) + (org-export-format-code + (car code-info) + (lambda (loc num ref) + (concat + loc + (when ref + ;; Ensure references are flushed to the right, + ;; separated with 6 spaces from the widest line + ;; of code. + (concat (make-string (+ (- max-width (length loc)) 6) + ?\s) + (format "(%s)" ref))))) + nil (and retain-labels (cdr code-info))))))) + ;; Return value. + (format float-env body))) + ;; Case 4. Use listings package. + (t + (let ((lst-lang + (or (cadr (assq (intern lang) org-latex-listings-langs)) lang)) + (caption-str + (when caption + (let ((main (org-export-get-caption src-block)) + (secondary (org-export-get-caption src-block t))) + (if (not secondary) + (format "{%s}" (org-export-data main info)) + (format "{[%s]%s}" + (org-export-data secondary info) + (org-export-data main info))))))) + (concat + ;; Options. + (format + "\\lstset{%s}\n" + (org-latex--make-option-string + (append + org-latex-listings-options + (cond + ((and (not float) (plist-member attributes :float)) nil) + ((string= "multicolumn" float) '(("float" "*"))) + ((and float (not (assoc "float" org-latex-listings-options))) + `(("float" ,org-latex-default-figure-position)))) + `(("language" ,lst-lang)) + (when label `(("label" ,label))) + (when caption-str `(("caption" ,caption-str))) + (cond ((assoc "numbers" org-latex-listings-options) nil) + ((not num-start) '(("numbers" "none"))) + ((zerop num-start) '(("numbers" "left"))) + (t `(("numbers" "left") + ("firstnumber" + ,(number-to-string (1+ num-start))))))))) + ;; Source code. + (format + "\\begin{lstlisting}\n%s\\end{lstlisting}" + (let* ((code-info (org-export-unravel-code src-block)) + (max-width + (apply 'max + (mapcar 'length + (org-split-string (car code-info) "\n"))))) + (org-export-format-code + (car code-info) + (lambda (loc num ref) + (concat + loc + (when ref + ;; Ensure references are flushed to the right, + ;; separated with 6 spaces from the widest line of + ;; code + (concat (make-string (+ (- max-width (length loc)) 6) ? ) + (format "(%s)" ref))))) + nil (and retain-labels (cdr code-info)))))))))))) + + +;;;; Statistics Cookie + +(defun org-latex-statistics-cookie (statistics-cookie contents info) + "Transcode a STATISTICS-COOKIE object from Org to LaTeX. +CONTENTS is nil. INFO is a plist holding contextual information." + (replace-regexp-in-string + "%" "\\%" (org-element-property :value statistics-cookie) nil t)) + + +;;;; Strike-Through + +(defun org-latex-strike-through (strike-through contents info) + "Transcode STRIKE-THROUGH from Org to LaTeX. +CONTENTS is the text with strike-through markup. INFO is a plist +holding contextual information." + (org-latex--text-markup contents 'strike-through)) + + +;;;; Subscript + +(defun org-latex--script-size (object info) + "Transcode a subscript or superscript object. +OBJECT is an Org object. INFO is a plist used as a communication +channel." + (let ((in-script-p + ;; Non-nil if object is already in a sub/superscript. + (let ((parent object)) + (catch 'exit + (while (setq parent (org-export-get-parent parent)) + (let ((type (org-element-type parent))) + (cond ((memq type '(subscript superscript)) + (throw 'exit t)) + ((memq type org-element-all-elements) + (throw 'exit nil)))))))) + (type (org-element-type object)) + (output "")) + (org-element-map (org-element-contents object) + (cons 'plain-text org-element-all-objects) + (lambda (obj) + (case (org-element-type obj) + ((entity latex-fragment) + (let ((data (org-trim (org-export-data obj info)))) + (string-match + "\\`\\(?:\\\\[([]\\|\\$+\\)?\\(.*?\\)\\(?:\\\\[])]\\|\\$+\\)?\\'" + data) + (setq output + (concat output + (match-string 1 data) + (let ((blank (org-element-property :post-blank obj))) + (and blank (> blank 0) "\\ ")))))) + (plain-text + (setq output + (format "%s\\text{%s}" output (org-export-data obj info)))) + (otherwise + (setq output + (concat output + (org-export-data obj info) + (let ((blank (org-element-property :post-blank obj))) + (and blank (> blank 0) "\\ "))))))) + info nil org-element-recursive-objects) + ;; Result. Do not wrap into math mode if already in a subscript + ;; or superscript. Do not wrap into curly brackets if OUTPUT is + ;; a single character. Also merge consecutive subscript and + ;; superscript into the same math snippet. + (concat (and (not in-script-p) + (let ((prev (org-export-get-previous-element object info))) + (or (not prev) + (not (eq (org-element-type prev) + (if (eq type 'subscript) 'superscript + 'subscript))) + (let ((blank (org-element-property :post-blank prev))) + (and blank (> blank 0))))) + "$") + (if (eq (org-element-type object) 'subscript) "_" "^") + (and (> (length output) 1) "{") + output + (and (> (length output) 1) "}") + (and (not in-script-p) + (or (let ((blank (org-element-property :post-blank object))) + (and blank (> blank 0))) + (not (eq (org-element-type + (org-export-get-next-element object info)) + (if (eq type 'subscript) 'superscript + 'subscript)))) + "$")))) + +(defun org-latex-subscript (subscript contents info) + "Transcode a SUBSCRIPT object from Org to LaTeX. +CONTENTS is the contents of the object. INFO is a plist holding +contextual information." + (org-latex--script-size subscript info)) + + +;;;; Superscript + +(defun org-latex-superscript (superscript contents info) + "Transcode a SUPERSCRIPT object from Org to LaTeX. +CONTENTS is the contents of the object. INFO is a plist holding +contextual information." + (org-latex--script-size superscript info)) + + +;;;; Table +;; +;; `org-latex-table' is the entry point for table transcoding. It +;; takes care of tables with a "verbatim" mode. Otherwise, it +;; delegates the job to either `org-latex--table.el-table', +;; `org-latex--org-table' or `org-latex--math-table' functions, +;; depending of the type of the table and the mode requested. +;; +;; `org-latex--align-string' is a subroutine used to build alignment +;; string for Org tables. + +(defun org-latex-table (table contents info) + "Transcode a TABLE element from Org to LaTeX. +CONTENTS is the contents of the table. INFO is a plist holding +contextual information." + (if (eq (org-element-property :type table) 'table.el) + ;; "table.el" table. Convert it using appropriate tools. + (org-latex--table.el-table table info) + (let ((type (or (org-export-read-attribute :attr_latex table :mode) + org-latex-default-table-mode))) + (cond + ;; Case 1: Verbatim table. + ((string= type "verbatim") + (format "\\begin{verbatim}\n%s\n\\end{verbatim}" + ;; Re-create table, without affiliated keywords. + (org-trim (org-element-interpret-data + `(table nil ,@(org-element-contents table)))))) + ;; Case 2: Matrix. + ((or (string= type "math") (string= type "inline-math")) + (org-latex--math-table table info)) + ;; Case 3: Standard table. + (t (concat (org-latex--org-table table contents info) + ;; When there are footnote references within the + ;; table, insert their definition just after it. + (org-latex--delayed-footnotes-definitions table info))))))) + +(defun org-latex--align-string (table info) + "Return an appropriate LaTeX alignment string. +TABLE is the considered table. INFO is a plist used as +a communication channel." + (or (org-export-read-attribute :attr_latex table :align) + (let (align) + ;; Extract column groups and alignment from first (non-rule) + ;; row. + (org-element-map + (org-element-map table 'table-row + (lambda (row) + (and (eq (org-element-property :type row) 'standard) row)) + info 'first-match) + 'table-cell + (lambda (cell) + (let ((borders (org-export-table-cell-borders cell info))) + ;; Check left border for the first cell only. + (when (and (memq 'left borders) (not align)) + (push "|" align)) + (push (case (org-export-table-cell-alignment cell info) + (left "l") + (right "r") + (center "c")) + align) + (when (memq 'right borders) (push "|" align)))) + info) + (apply 'concat (nreverse align))))) + +(defun org-latex--org-table (table contents info) + "Return appropriate LaTeX code for an Org table. + +TABLE is the table type element to transcode. CONTENTS is its +contents, as a string. INFO is a plist used as a communication +channel. + +This function assumes TABLE has `org' as its `:type' property and +`table' as its `:mode' attribute." + (let* ((caption (org-latex--caption/label-string table info)) + (attr (org-export-read-attribute :attr_latex table)) + ;; Determine alignment string. + (alignment (org-latex--align-string table info)) + ;; Determine environment for the table: longtable, tabular... + (table-env (or (plist-get attr :environment) + org-latex-default-table-environment)) + ;; If table is a float, determine environment: table, table* + ;; or sidewaystable. + (float-env (unless (member table-env '("longtable" "longtabu")) + (let ((float (plist-get attr :float))) + (cond + ((and (not float) (plist-member attr :float)) nil) + ((string= float "sidewaystable") "sidewaystable") + ((string= float "multicolumn") "table*") + ((or float + (org-element-property :caption table) + (org-string-nw-p (plist-get attr :caption))) + "table"))))) + ;; Extract others display options. + (fontsize (let ((font (plist-get attr :font))) + (and font (concat font "\n")))) + (width (plist-get attr :width)) + (spreadp (plist-get attr :spread)) + (placement (or (plist-get attr :placement) + (format "[%s]" org-latex-default-figure-position))) + (centerp (if (plist-member attr :center) (plist-get attr :center) + org-latex-tables-centered))) + ;; Prepare the final format string for the table. + (cond + ;; Longtable. + ((equal "longtable" table-env) + (concat (and fontsize (concat "{" fontsize)) + (format "\\begin{longtable}{%s}\n" alignment) + (and org-latex-table-caption-above + (org-string-nw-p caption) + (concat caption "\\\\\n")) + contents + (and (not org-latex-table-caption-above) + (org-string-nw-p caption) + (concat caption "\\\\\n")) + "\\end{longtable}\n" + (and fontsize "}"))) + ;; Longtabu + ((equal "longtabu" table-env) + (concat (and fontsize (concat "{" fontsize)) + (format "\\begin{longtabu}%s{%s}\n" + (if width + (format " %s %s " + (if spreadp "spread" "to") width) "") + alignment) + (and org-latex-table-caption-above + (org-string-nw-p caption) + (concat caption "\\\\\n")) + contents + (and (not org-latex-table-caption-above) + (org-string-nw-p caption) + (concat caption "\\\\\n")) + "\\end{longtabu}\n" + (and fontsize "}"))) + ;; Others. + (t (concat (cond + (float-env + (concat (format "\\begin{%s}%s\n" float-env placement) + (if org-latex-table-caption-above caption "") + (when centerp "\\centering\n") + fontsize)) + (centerp (concat "\\begin{center}\n" fontsize)) + (fontsize (concat "{" fontsize))) + (cond ((equal "tabu" table-env) + (format "\\begin{tabu}%s{%s}\n%s\\end{tabu}" + (if width (format + (if spreadp " spread %s " " to %s ") + width) "") + alignment + contents)) + (t (format "\\begin{%s}%s{%s}\n%s\\end{%s}" + table-env + (if width (format "{%s}" width) "") + alignment + contents + table-env))) + (cond + (float-env + (concat (if org-latex-table-caption-above "" caption) + (format "\n\\end{%s}" float-env))) + (centerp "\n\\end{center}") + (fontsize "}"))))))) + +(defun org-latex--table.el-table (table info) + "Return appropriate LaTeX code for a table.el table. + +TABLE is the table type element to transcode. INFO is a plist +used as a communication channel. + +This function assumes TABLE has `table.el' as its `:type' +property." + (require 'table) + ;; Ensure "*org-export-table*" buffer is empty. + (with-current-buffer (get-buffer-create "*org-export-table*") + (erase-buffer)) + (let ((output (with-temp-buffer + (insert (org-element-property :value table)) + (goto-char 1) + (re-search-forward "^[ \t]*|[^|]" nil t) + (table-generate-source 'latex "*org-export-table*") + (with-current-buffer "*org-export-table*" + (org-trim (buffer-string)))))) + (kill-buffer (get-buffer "*org-export-table*")) + ;; Remove left out comments. + (while (string-match "^%.*\n" output) + (setq output (replace-match "" t t output))) + (let ((attr (org-export-read-attribute :attr_latex table))) + (when (plist-get attr :rmlines) + ;; When the "rmlines" attribute is provided, remove all hlines + ;; but the the one separating heading from the table body. + (let ((n 0) (pos 0)) + (while (and (< (length output) pos) + (setq pos (string-match "^\\\\hline\n?" output pos))) + (incf n) + (unless (= n 2) (setq output (replace-match "" nil nil output)))))) + (let ((centerp (if (plist-member attr :center) (plist-get attr :center) + org-latex-tables-centered))) + (if (not centerp) output + (format "\\begin{center}\n%s\n\\end{center}" output)))))) + +(defun org-latex--math-table (table info) + "Return appropriate LaTeX code for a matrix. + +TABLE is the table type element to transcode. INFO is a plist +used as a communication channel. + +This function assumes TABLE has `org' as its `:type' property and +`inline-math' or `math' as its `:mode' attribute.." + (let* ((caption (org-latex--caption/label-string table info)) + (attr (org-export-read-attribute :attr_latex table)) + (inlinep (equal (plist-get attr :mode) "inline-math")) + (env (or (plist-get attr :environment) + org-latex-default-table-environment)) + (contents + (mapconcat + (lambda (row) + ;; Ignore horizontal rules. + (when (eq (org-element-property :type row) 'standard) + ;; Return each cell unmodified. + (concat + (mapconcat + (lambda (cell) + (substring (org-element-interpret-data cell) 0 -1)) + (org-element-map row 'table-cell 'identity info) "&") + (or (cdr (assoc env org-latex-table-matrix-macros)) "\\\\") + "\n"))) + (org-element-map table 'table-row 'identity info) "")) + ;; Variables related to math clusters (contiguous math tables + ;; of the same type). + (mode (org-export-read-attribute :attr_latex table :mode)) + (prev (org-export-get-previous-element table info)) + (next (org-export-get-next-element table info)) + (same-mode-p + (lambda (table) + ;; Non-nil when TABLE has the same mode as current table. + (string= (or (org-export-read-attribute :attr_latex table :mode) + org-latex-default-table-mode) + mode)))) + (concat + ;; Opening string. If TABLE is in the middle of a table cluster, + ;; do not insert any. + (cond ((and prev + (eq (org-element-type prev) 'table) + (memq (org-element-property :post-blank prev) '(0 nil)) + (funcall same-mode-p prev)) + nil) + (inlinep "\\(") + ((org-string-nw-p caption) (concat "\\begin{equation}\n" caption)) + (t "\\[")) + ;; Prefix. + (or (plist-get attr :math-prefix) "") + ;; Environment. Also treat special cases. + (cond ((equal env "array") + (let ((align (org-latex--align-string table info))) + (format "\\begin{array}{%s}\n%s\\end{array}" align contents))) + ((assoc env org-latex-table-matrix-macros) + (format "\\%s%s{\n%s}" + env + (or (plist-get attr :math-arguments) "") + contents)) + (t (format "\\begin{%s}\n%s\\end{%s}" env contents env))) + ;; Suffix. + (or (plist-get attr :math-suffix) "") + ;; Closing string. If TABLE is in the middle of a table cluster, + ;; do not insert any. If it closes such a cluster, be sure to + ;; close the cluster with a string matching the opening string. + (cond ((and next + (eq (org-element-type next) 'table) + (memq (org-element-property :post-blank table) '(0 nil)) + (funcall same-mode-p next)) + nil) + (inlinep "\\)") + ;; Find cluster beginning to know which environment to use. + ((let ((cluster-beg table) prev) + (while (and (setq prev (org-export-get-previous-element + cluster-beg info)) + (memq (org-element-property :post-blank prev) + '(0 nil)) + (funcall same-mode-p prev)) + (setq cluster-beg prev)) + (and (or (org-element-property :caption cluster-beg) + (org-element-property :name cluster-beg)) + "\n\\end{equation}"))) + (t "\\]"))))) + + +;;;; Table Cell + +(defun org-latex-table-cell (table-cell contents info) + "Transcode a TABLE-CELL element from Org to LaTeX. +CONTENTS is the cell contents. INFO is a plist used as +a communication channel." + (concat (if (and contents + org-latex-table-scientific-notation + (string-match orgtbl-exp-regexp contents)) + ;; Use appropriate format string for scientific + ;; notation. + (format org-latex-table-scientific-notation + (match-string 1 contents) + (match-string 2 contents)) + contents) + (when (org-export-get-next-element table-cell info) " & "))) + + +;;;; Table Row + +(defun org-latex-table-row (table-row contents info) + "Transcode a TABLE-ROW element from Org to LaTeX. +CONTENTS is the contents of the row. INFO is a plist used as +a communication channel." + ;; Rules are ignored since table separators are deduced from + ;; borders of the current row. + (when (eq (org-element-property :type table-row) 'standard) + (let* ((attr (org-export-read-attribute :attr_latex + (org-export-get-parent table-row))) + (longtablep (member (or (plist-get attr :environment) + org-latex-default-table-environment) + '("longtable" "longtabu"))) + (booktabsp (if (plist-member attr :booktabs) + (plist-get attr :booktabs) + org-latex-tables-booktabs)) + ;; TABLE-ROW's borders are extracted from its first cell. + (borders (org-export-table-cell-borders + (car (org-element-contents table-row)) info))) + (concat + ;; When BOOKTABS are activated enforce top-rule even when no + ;; hline was specifically marked. + (cond ((and booktabsp (memq 'top borders)) "\\toprule\n") + ((and (memq 'top borders) (memq 'above borders)) "\\hline\n")) + contents "\\\\\n" + (cond + ;; Special case for long tables. Define header and footers. + ((and longtablep (org-export-table-row-ends-header-p table-row info)) + (format "%s +\\endhead +%s\\multicolumn{%d}{r}{Continued on next page} \\\\ +\\endfoot +\\endlastfoot" + (if booktabsp "\\midrule" "\\hline") + (if booktabsp "\\midrule" "\\hline") + ;; Number of columns. + (cdr (org-export-table-dimensions + (org-export-get-parent-table table-row) info)))) + ;; When BOOKTABS are activated enforce bottom rule even when + ;; no hline was specifically marked. + ((and booktabsp (memq 'bottom borders)) "\\bottomrule") + ((and (memq 'bottom borders) (memq 'below borders)) "\\hline") + ((memq 'below borders) (if booktabsp "\\midrule" "\\hline"))))))) + + +;;;; Target + +(defun org-latex-target (target contents info) + "Transcode a TARGET object from Org to LaTeX. +CONTENTS is nil. INFO is a plist holding contextual +information." + (format "\\label{%s}" + (org-export-solidify-link-text (org-element-property :value target)))) + + +;;;; Timestamp + +(defun org-latex-timestamp (timestamp contents info) + "Transcode a TIMESTAMP object from Org to LaTeX. +CONTENTS is nil. INFO is a plist holding contextual +information." + (let ((value (org-latex-plain-text + (org-timestamp-translate timestamp) info))) + (case (org-element-property :type timestamp) + ((active active-range) (format org-latex-active-timestamp-format value)) + ((inactive inactive-range) + (format org-latex-inactive-timestamp-format value)) + (otherwise (format org-latex-diary-timestamp-format value))))) + + +;;;; Underline + +(defun org-latex-underline (underline contents info) + "Transcode UNDERLINE from Org to LaTeX. +CONTENTS is the text with underline markup. INFO is a plist +holding contextual information." + (org-latex--text-markup contents 'underline)) + + +;;;; Verbatim + +(defun org-latex-verbatim (verbatim contents info) + "Transcode a VERBATIM object from Org to LaTeX. +CONTENTS is nil. INFO is a plist used as a communication +channel." + (org-latex--text-markup (org-element-property :value verbatim) 'verbatim)) + + +;;;; Verse Block + +(defun org-latex-verse-block (verse-block contents info) + "Transcode a VERSE-BLOCK element from Org to LaTeX. +CONTENTS is verse block contents. INFO is a plist holding +contextual information." + (org-latex--wrap-label + verse-block + ;; In a verse environment, add a line break to each newline + ;; character and change each white space at beginning of a line + ;; into a space of 1 em. Also change each blank line with + ;; a vertical space of 1 em. + (progn + (setq contents (replace-regexp-in-string + "^ *\\\\\\\\$" "\\\\vspace*{1em}" + (replace-regexp-in-string + "\\(\\\\\\\\\\)?[ \t]*\n" " \\\\\\\\\n" contents))) + (while (string-match "^[ \t]+" contents) + (let ((new-str (format "\\hspace*{%dem}" + (length (match-string 0 contents))))) + (setq contents (replace-match new-str nil t contents)))) + (format "\\begin{verse}\n%s\\end{verse}" contents)))) + + + +;;; End-user functions + +;;;###autoload +(defun org-latex-export-as-latex + (&optional async subtreep visible-only body-only ext-plist) + "Export current buffer as a LaTeX buffer. + +If narrowing is active in the current buffer, only export its +narrowed part. + +If a region is active, export that region. + +A non-nil optional argument ASYNC means the process should happen +asynchronously. The resulting buffer should be accessible +through the `org-export-stack' interface. + +When optional argument SUBTREEP is non-nil, export the sub-tree +at point, extracting information from the headline properties +first. + +When optional argument VISIBLE-ONLY is non-nil, don't export +contents of hidden elements. + +When optional argument BODY-ONLY is non-nil, only write code +between \"\\begin{document}\" and \"\\end{document}\". + +EXT-PLIST, when provided, is a property list with external +parameters overriding Org default settings, but still inferior to +file-local settings. + +Export is done in a buffer named \"*Org LATEX Export*\", which +will be displayed when `org-export-show-temporary-export-buffer' +is non-nil." + (interactive) + (org-export-to-buffer 'latex "*Org LATEX Export*" + async subtreep visible-only body-only ext-plist (lambda () (LaTeX-mode)))) + +;;;###autoload +(defun org-latex-convert-region-to-latex () + "Assume the current region has org-mode syntax, and convert it to LaTeX. +This can be used in any buffer. For example, you can write an +itemized list in org-mode syntax in an LaTeX buffer and use this +command to convert it." + (interactive) + (org-export-replace-region-by 'latex)) + +;;;###autoload +(defun org-latex-export-to-latex + (&optional async subtreep visible-only body-only ext-plist) + "Export current buffer to a LaTeX file. + +If narrowing is active in the current buffer, only export its +narrowed part. + +If a region is active, export that region. + +A non-nil optional argument ASYNC means the process should happen +asynchronously. The resulting file should be accessible through +the `org-export-stack' interface. + +When optional argument SUBTREEP is non-nil, export the sub-tree +at point, extracting information from the headline properties +first. + +When optional argument VISIBLE-ONLY is non-nil, don't export +contents of hidden elements. + +When optional argument BODY-ONLY is non-nil, only write code +between \"\\begin{document}\" and \"\\end{document}\". + +EXT-PLIST, when provided, is a property list with external +parameters overriding Org default settings, but still inferior to +file-local settings." + (interactive) + (let ((outfile (org-export-output-file-name ".tex" subtreep))) + (org-export-to-file 'latex outfile + async subtreep visible-only body-only ext-plist))) + +;;;###autoload +(defun org-latex-export-to-pdf + (&optional async subtreep visible-only body-only ext-plist) + "Export current buffer to LaTeX then process through to PDF. + +If narrowing is active in the current buffer, only export its +narrowed part. + +If a region is active, export that region. + +A non-nil optional argument ASYNC means the process should happen +asynchronously. The resulting file should be accessible through +the `org-export-stack' interface. + +When optional argument SUBTREEP is non-nil, export the sub-tree +at point, extracting information from the headline properties +first. + +When optional argument VISIBLE-ONLY is non-nil, don't export +contents of hidden elements. + +When optional argument BODY-ONLY is non-nil, only write code +between \"\\begin{document}\" and \"\\end{document}\". + +EXT-PLIST, when provided, is a property list with external +parameters overriding Org default settings, but still inferior to +file-local settings. + +Return PDF file's name." + (interactive) + (let ((outfile (org-export-output-file-name ".tex" subtreep))) + (org-export-to-file 'latex outfile + async subtreep visible-only body-only ext-plist + (lambda (file) (org-latex-compile file))))) + +(defun org-latex-compile (texfile &optional snippet) + "Compile a TeX file. + +TEXFILE is the name of the file being compiled. Processing is +done through the command specified in `org-latex-pdf-process'. + +When optional argument SNIPPET is non-nil, TEXFILE is a temporary +file used to preview a LaTeX snippet. In this case, do not +create a log buffer and do not bother removing log files. + +Return PDF file name or an error if it couldn't be produced." + (let* ((base-name (file-name-sans-extension (file-name-nondirectory texfile))) + (full-name (file-truename texfile)) + (out-dir (file-name-directory texfile)) + ;; Properly set working directory for compilation. + (default-directory (if (file-name-absolute-p texfile) + (file-name-directory full-name) + default-directory)) + errors) + (unless snippet (message (format "Processing LaTeX file %s..." texfile))) + (save-window-excursion + (cond + ;; A function is provided: Apply it. + ((functionp org-latex-pdf-process) + (funcall org-latex-pdf-process (shell-quote-argument texfile))) + ;; A list is provided: Replace %b, %f and %o with appropriate + ;; values in each command before applying it. Output is + ;; redirected to "*Org PDF LaTeX Output*" buffer. + ((consp org-latex-pdf-process) + (let ((outbuf (and (not snippet) + (get-buffer-create "*Org PDF LaTeX Output*")))) + (mapc + (lambda (command) + (shell-command + (replace-regexp-in-string + "%b" (shell-quote-argument base-name) + (replace-regexp-in-string + "%f" (shell-quote-argument full-name) + (replace-regexp-in-string + "%o" (shell-quote-argument out-dir) command t t) t t) t t) + outbuf)) + org-latex-pdf-process) + ;; Collect standard errors from output buffer. + (setq errors (and (not snippet) (org-latex--collect-errors outbuf))))) + (t (error "No valid command to process to PDF"))) + (let ((pdffile (concat out-dir base-name ".pdf"))) + ;; Check for process failure. Provide collected errors if + ;; possible. + (if (not (file-exists-p pdffile)) + (error (concat (format "PDF file %s wasn't produced" pdffile) + (when errors (concat ": " errors)))) + ;; Else remove log files, when specified, and signal end of + ;; process to user, along with any error encountered. + (when (and (not snippet) org-latex-remove-logfiles) + (dolist (file (directory-files + out-dir t + (concat (regexp-quote base-name) + "\\(?:\\.[0-9]+\\)?" + "\\." + (regexp-opt org-latex-logfiles-extensions)))) + (delete-file file))) + (message (concat "Process completed" + (if (not errors) "." + (concat " with errors: " errors))))) + ;; Return output file name. + pdffile)))) + +(defun org-latex--collect-errors (buffer) + "Collect some kind of errors from \"pdflatex\" command output. + +BUFFER is the buffer containing output. + +Return collected error types as a string, or nil if there was +none." + (with-current-buffer buffer + (save-excursion + (goto-char (point-max)) + (when (re-search-backward "^[ \t]*This is .*?TeX.*?Version" nil t) + (let ((case-fold-search t) + (errors "")) + (dolist (latex-error org-latex-known-errors) + (when (save-excursion (re-search-forward (car latex-error) nil t)) + (setq errors (concat errors " " (cdr latex-error))))) + (and (org-string-nw-p errors) (org-trim errors))))))) + +;;;###autoload +(defun org-latex-publish-to-latex (plist filename pub-dir) + "Publish an Org file to LaTeX. + +FILENAME is the filename of the Org file to be published. PLIST +is the property list for the given project. PUB-DIR is the +publishing directory. + +Return output file name." + (org-publish-org-to 'latex filename ".tex" plist pub-dir)) + +;;;###autoload +(defun org-latex-publish-to-pdf (plist filename pub-dir) + "Publish an Org file to PDF (via LaTeX). + +FILENAME is the filename of the Org file to be published. PLIST +is the property list for the given project. PUB-DIR is the +publishing directory. + +Return output file name." + ;; Unlike to `org-latex-publish-to-latex', PDF file is generated + ;; in working directory and then moved to publishing directory. + (org-publish-attachment + plist + (org-latex-compile (org-publish-org-to 'latex filename ".tex" plist)) + pub-dir)) + + +(provide 'ox-latex) + +;; Local variables: +;; generated-autoload-file: "org-loaddefs.el" +;; End: + +;;; ox-latex.el ends here diff --git a/lisp/org/ox-man.el b/lisp/org/ox-man.el new file mode 100644 index 00000000000..a160e4cff48 --- /dev/null +++ b/lisp/org/ox-man.el @@ -0,0 +1,1260 @@ +;; ox-man.el --- Man Back-End for Org Export Engine + +;; Copyright (C) 2011-2013 Free Software Foundation, Inc. + +;; Author: Nicolas Goaziou +;; Luis R Anaya +;; Keywords: outlines, hypermedia, calendar, wp + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: +;; +;; This library implements a Man back-end for Org generic exporter. +;; +;; To test it, run +;; +;; M-: (org-export-to-buffer 'man "*Test Man*") RET +;; +;; in an org-mode buffer then switch to the buffer to see the Man +;; export. See ox.el for more details on how this exporter works. +;; +;; It introduces one new buffer keywords: +;; "MAN_CLASS_OPTIONS". + +;;; Code: + +(require 'ox) + +(eval-when-compile (require 'cl)) + +(defvar org-export-man-default-packages-alist) +(defvar org-export-man-packages-alist) +(defvar orgtbl-exp-regexp) + + + +;;; Define Back-End + +(org-export-define-backend 'man + '((babel-call . org-man-babel-call) + (bold . org-man-bold) + (center-block . org-man-center-block) + (clock . org-man-clock) + (code . org-man-code) + (comment . (lambda (&rest args) "")) + (comment-block . (lambda (&rest args) "")) + (drawer . org-man-drawer) + (dynamic-block . org-man-dynamic-block) + (entity . org-man-entity) + (example-block . org-man-example-block) + (export-block . org-man-export-block) + (export-snippet . org-man-export-snippet) + (fixed-width . org-man-fixed-width) + (footnote-definition . org-man-footnote-definition) + (footnote-reference . org-man-footnote-reference) + (headline . org-man-headline) + (horizontal-rule . org-man-horizontal-rule) + (inline-babel-call . org-man-inline-babel-call) + (inline-src-block . org-man-inline-src-block) + (inlinetask . org-man-inlinetask) + (italic . org-man-italic) + (item . org-man-item) + (keyword . org-man-keyword) + (line-break . org-man-line-break) + (link . org-man-link) + (paragraph . org-man-paragraph) + (plain-list . org-man-plain-list) + (plain-text . org-man-plain-text) + (planning . org-man-planning) + (property-drawer . (lambda (&rest args) "")) + (quote-block . org-man-quote-block) + (quote-section . org-man-quote-section) + (radio-target . org-man-radio-target) + (section . org-man-section) + (special-block . org-man-special-block) + (src-block . org-man-src-block) + (statistics-cookie . org-man-statistics-cookie) + (strike-through . org-man-strike-through) + (subscript . org-man-subscript) + (superscript . org-man-superscript) + (table . org-man-table) + (table-cell . org-man-table-cell) + (table-row . org-man-table-row) + (target . org-man-target) + (template . org-man-template) + (timestamp . org-man-timestamp) + (underline . org-man-underline) + (verbatim . org-man-verbatim) + (verse-block . org-man-verse-block)) + :export-block "MAN" + :menu-entry + '(?m "Export to MAN" + ((?m "As MAN file" org-man-export-to-man) + (?p "As PDF file" org-man-export-to-pdf) + (?o "As PDF file and open" + (lambda (a s v b) + (if a (org-man-export-to-pdf t s v b) + (org-open-file (org-man-export-to-pdf nil s v b))))))) + :options-alist + '((:man-class "MAN_CLASS" nil nil t) + (:man-class-options "MAN_CLASS_OPTIONS" nil nil t) + (:man-header-extra "MAN_HEADER" nil nil newline))) + + + +;;; User Configurable Variables + +(defgroup org-export-man nil + "Options for exporting Org mode files to Man." + :tag "Org Export Man" + :group 'org-export) + +;;; Tables + +(defcustom org-man-tables-centered t + "When non-nil, tables are exported in a center environment." + :group 'org-export-man + :version "24.4" + :package-version '(Org . "8.0") + :type 'boolean) + +(defcustom org-man-tables-verbatim nil + "When non-nil, tables are exported verbatim." + :group 'org-export-man + :version "24.4" + :package-version '(Org . "8.0") + :type 'boolean) + + +(defcustom org-man-table-scientific-notation "%sE%s" + "Format string to display numbers in scientific notation. +The format should have \"%s\" twice, for mantissa and exponent +\(i.e. \"%s\\\\times10^{%s}\"). + +When nil, no transformation is made." + :group 'org-export-man + :version "24.4" + :package-version '(Org . "8.0") + :type '(choice + (string :tag "Format string") + (const :tag "No formatting"))) + + +;;; Inlinetasks +;; Src blocks + +(defcustom org-man-source-highlight nil + "Use GNU source highlight to embellish source blocks " + :group 'org-export-man + :version "24.4" + :package-version '(Org . "8.0") + :type 'boolean) + + +(defcustom org-man-source-highlight-langs + '((emacs-lisp "lisp") (lisp "lisp") (clojure "lisp") + (scheme "scheme") + (c "c") (cc "cpp") (csharp "csharp") (d "d") + (fortran "fortran") (cobol "cobol") (pascal "pascal") + (ada "ada") (asm "asm") + (perl "perl") (cperl "perl") + (python "python") (ruby "ruby") (tcl "tcl") (lua "lua") + (java "java") (javascript "javascript") + (tex "latex") + (shell-script "sh") (awk "awk") (diff "diff") (m4 "m4") + (ocaml "caml") (caml "caml") + (sql "sql") (sqlite "sql") + (html "html") (css "css") (xml "xml") + (bat "bat") (bison "bison") (clipper "clipper") + (ldap "ldap") (opa "opa") + (php "php") (postscript "postscript") (prolog "prolog") + (properties "properties") (makefile "makefile") + (tml "tml") (vala "vala") (vbscript "vbscript") (xorg "xorg")) + "Alist mapping languages to their listing language counterpart. +The key is a symbol, the major mode symbol without the \"-mode\". +The value is the string that should be inserted as the language +parameter for the listings package. If the mode name and the +listings name are the same, the language does not need an entry +in this list - but it does not hurt if it is present." + :group 'org-export-man + :version "24.4" + :package-version '(Org . "8.0") + :type '(repeat + (list + (symbol :tag "Major mode ") + (string :tag "Listings language")))) + + + +(defvar org-man-custom-lang-environments nil + "Alist mapping languages to language-specific Man environments. + +It is used during export of src blocks by the listings and +man packages. For example, + + \(setq org-man-custom-lang-environments + '\(\(python \"pythoncode\"\)\)\) + +would have the effect that if org encounters begin_src python +during man export." +) + + +;;; Compilation + +(defcustom org-man-pdf-process + '("tbl %f | eqn | groff -man | ps2pdf - > %b.pdf" + "tbl %f | eqn | groff -man | ps2pdf - > %b.pdf" + "tbl %f | eqn | groff -man | ps2pdf - > %b.pdf") + + "Commands to process a Man file to a PDF file. +This is a list of strings, each of them will be given to the +shell as a command. %f in the command will be replaced by the +full file name, %b by the file base name (i.e. without directory +and extension parts) and %o by the base directory of the file. + + +By default, Org uses 3 runs of to do the processing. + +Alternatively, this may be a Lisp function that does the +processing. This function should accept the file name as +its single argument." + :group 'org-export-pdf + :group 'org-export-man + :version "24.4" + :package-version '(Org . "8.0") + :type '(choice + (repeat :tag "Shell command sequence" + (string :tag "Shell command")) + (const :tag "2 runs of pdfgroff" + ("tbl %f | eqn | groff -mm | ps2pdf - > %b.pdf" + "tbl %f | eqn | groff -mm | ps2pdf - > %b.pdf" )) + (const :tag "3 runs of pdfgroff" + ("tbl %f | eqn | groff -mm | ps2pdf - > %b.pdf" + "tbl %f | eqn | groff -mm | ps2pdf - > %b.pdf" + "tbl %f | eqn | groff -mm | ps2pdf - > %b.pdf")) + (function))) + +(defcustom org-man-logfiles-extensions + '("log" "out" "toc") + "The list of file extensions to consider as Man logfiles." + :group 'org-export-man + :version "24.4" + :package-version '(Org . "8.0") + :type '(repeat (string :tag "Extension"))) + +(defcustom org-man-remove-logfiles t + "Non-nil means remove the logfiles produced by PDF production. +These are the .aux, .log, .out, and .toc files." + :group 'org-export-man + :version "24.4" + :package-version '(Org . "8.0") + :type 'boolean) + + + +;;; Internal Functions + +(defun org-man--caption/label-string (element info) + "Return caption and label Man string for ELEMENT. + +INFO is a plist holding contextual information. If there's no +caption nor label, return the empty string. + +For non-floats, see `org-man--wrap-label'." + (let ((label (org-element-property :label element)) + (main (org-export-get-caption element)) + (short (org-export-get-caption element t))) + (cond ((and (not main) (not label)) "") + ((not main) (format "\\fI%s\\fP" label)) + ;; Option caption format with short name. + (short (format "\\fR%s\\fP - \\fI\\P - %s\n" + (org-export-data short info) + (org-export-data main info))) + ;; Standard caption format. + (t (format "\\fR%s\\fP" (org-export-data main info)))))) + +(defun org-man--wrap-label (element output) + "Wrap label associated to ELEMENT around OUTPUT, if appropriate. +This function shouldn't be used for floats. See +`org-man--caption/label-string'." + (let ((label (org-element-property :name element))) + (if (or (not output) (not label) (string= output "") (string= label "")) + output + (concat (format "%s\n.br\n" label) output)))) + + + +;;; Template + +(defun org-man-template (contents info) + "Return complete document string after Man conversion. +CONTENTS is the transcoded contents string. INFO is a plist +holding export options." + (let* ((title (org-export-data (plist-get info :title) info)) + (attr (read (format "(%s)" + (mapconcat + #'identity + (list (plist-get info :man-class-options)) + " ")))) + (section-item (plist-get attr :section-id))) + + (concat + + (cond + ((and title (stringp section-item)) + (format ".TH \"%s\" \"%s\" \n" title section-item)) + ((and (string= "" title) (stringp section-item)) + (format ".TH \"%s\" \"%s\" \n" " " section-item)) + (title + (format ".TH \"%s\" \"1\" \n" title)) + (t + ".TH \" \" \"1\" ")) + contents))) + + + + +;;; Transcode Functions + +;;; Babel Call +;; +;; Babel Calls are ignored. + + +;;; Bold + +(defun org-man-bold (bold contents info) + "Transcode BOLD from Org to Man. +CONTENTS is the text with bold markup. INFO is a plist holding +contextual information." + (format "\\fB%s\\fP" contents)) + + +;;; Center Block + +(defun org-man-center-block (center-block contents info) + "Transcode a CENTER-BLOCK element from Org to Man. +CONTENTS holds the contents of the center block. INFO is a plist +holding contextual information." + (org-man--wrap-label + center-block + (format ".ce %d\n.nf\n%s\n.fi" + (- (length (split-string contents "\n")) 1 ) + contents))) + + +;;; Clock + +(defun org-man-clock (clock contents info) + "Transcode a CLOCK element from Org to Man. +CONTENTS is nil. INFO is a plist holding contextual +information." + "" ) + + +;;; Code + +(defun org-man-code (code contents info) + "Transcode a CODE object from Org to Man. +CONTENTS is nil. INFO is a plist used as a communication +channel." + (format "\\fC%s\\fP" code)) + + +;;; Comment +;; +;; Comments are ignored. + + +;;; Comment Block +;; +;; Comment Blocks are ignored. + + +;;; Drawer + +(defun org-man-drawer (drawer contents info) + "Transcode a DRAWER element from Org to Man. + DRAWER holds the drawer information + CONTENTS holds the contents of the block. + INFO is a plist holding contextual information. " + contents) + + +;;; Dynamic Block + +(defun org-man-dynamic-block (dynamic-block contents info) + "Transcode a DYNAMIC-BLOCK element from Org to Man. +CONTENTS holds the contents of the block. INFO is a plist +holding contextual information. See `org-export-data'." + (org-man--wrap-label dynamic-block contents)) + + +;;; Entity + +(defun org-man-entity (entity contents info) + "Transcode an ENTITY object from Org to Man. +CONTENTS are the definition itself. INFO is a plist holding +contextual information." + (org-element-property :utf-8 entity)) + + +;;; Example Block + +(defun org-man-example-block (example-block contents info) + "Transcode an EXAMPLE-BLOCK element from Org to Man. +CONTENTS is nil. INFO is a plist holding contextual +information." + (org-man--wrap-label + example-block + (format ".RS\n.nf\n%s\n.fi\n.RE" + (org-export-format-code-default example-block info)))) + + +;;; Export Block + +(defun org-man-export-block (export-block contents info) + "Transcode a EXPORT-BLOCK element from Org to Man. +CONTENTS is nil. INFO is a plist holding contextual information." + (when (string= (org-element-property :type export-block) "MAN") + (org-remove-indentation (org-element-property :value export-block)))) + + +;;; Export Snippet + +(defun org-man-export-snippet (export-snippet contents info) + "Transcode a EXPORT-SNIPPET object from Org to Man. +CONTENTS is nil. INFO is a plist holding contextual information." + (when (eq (org-export-snippet-backend export-snippet) 'man) + (org-element-property :value export-snippet))) + + +;;; Fixed Width + +(defun org-man-fixed-width (fixed-width contents info) + "Transcode a FIXED-WIDTH element from Org to Man. +CONTENTS is nil. INFO is a plist holding contextual information." + (org-man--wrap-label + fixed-width + (format "\\fC\n%s\\fP" + (org-remove-indentation + (org-element-property :value fixed-width))))) + + +;;; Footnote Definition +;; +;; Footnote Definitions are ignored. + +;;; Footnote References +;; +;; Footnote References are Ignored + + +;;; Headline + +(defun org-man-headline (headline contents info) + "Transcode a HEADLINE element from Org to Man. +CONTENTS holds the contents of the headline. INFO is a plist +holding contextual information." + (let* ((level (org-export-get-relative-level headline info)) + (numberedp (org-export-numbered-headline-p headline info)) + ;; Section formatting will set two placeholders: one for the + ;; title and the other for the contents. + (section-fmt + (case level + (1 ".SH \"%s\"\n%s") + (2 ".SS \"%s\"\n%s") + (3 ".SS \"%s\"\n%s") + (t nil))) + (text (org-export-data (org-element-property :title headline) info))) + + (cond + ;; Case 1: This is a footnote section: ignore it. + ((org-element-property :footnote-section-p headline) nil) + + ;; Case 2. This is a deep sub-tree: export it as a list item. + ;; Also export as items headlines for which no section + ;; format has been found. + ((or (not section-fmt) (org-export-low-level-p headline info)) + ;; Build the real contents of the sub-tree. + (let ((low-level-body + (concat + ;; If the headline is the first sibling, start a list. + (when (org-export-first-sibling-p headline info) + (format "%s\n" ".RS")) + ;; Itemize headline + ".TP\n.ft I\n" text "\n.ft\n" + contents ".RE"))) + ;; If headline is not the last sibling simply return + ;; LOW-LEVEL-BODY. Otherwise, also close the list, before any + ;; blank line. + (if (not (org-export-last-sibling-p headline info)) low-level-body + (replace-regexp-in-string + "[ \t\n]*\\'" "" + low-level-body)))) + + ;; Case 3. Standard headline. Export it as a section. + (t (format section-fmt text contents ))))) + +;;; Horizontal Rule +;; Not supported + +;;; Inline Babel Call +;; +;; Inline Babel Calls are ignored. + +;;; Inline Src Block + +(defun org-man-inline-src-block (inline-src-block contents info) + "Transcode an INLINE-SRC-BLOCK element from Org to Man. +CONTENTS holds the contents of the item. INFO is a plist holding +contextual information." + (let* ((code (org-element-property :value inline-src-block))) + (cond + (org-man-source-highlight + (let* ((tmpdir (if (featurep 'xemacs) + temp-directory + temporary-file-directory )) + (in-file (make-temp-name + (expand-file-name "srchilite" tmpdir))) + (out-file (make-temp-name + (expand-file-name "reshilite" tmpdir))) + (org-lang (org-element-property :language inline-src-block)) + (lst-lang (cadr (assq (intern org-lang) + org-man-source-highlight-langs))) + + (cmd (concat (expand-file-name "source-highlight") + " -s " lst-lang + " -f groff_man" + " -i " in-file + " -o " out-file ))) + + (if lst-lang + (let ((code-block "" )) + (with-temp-file in-file (insert code)) + (shell-command cmd) + (setq code-block (org-file-contents out-file)) + (delete-file in-file) + (delete-file out-file) + code-block) + (format ".RS\n.nf\n\\fC\\m[black]%s\\m[]\\fP\n.fi\n.RE\n" + code)))) + + ;; Do not use a special package: transcode it verbatim. + (t + (concat ".RS\n.nf\n" "\\fC" "\n" code "\n" + "\\fP\n.fi\n.RE\n"))))) + + +;;; Inlinetask +;;; Italic + +(defun org-man-italic (italic contents info) + "Transcode ITALIC from Org to Man. +CONTENTS is the text with italic markup. INFO is a plist holding +contextual information." + (format "\\fI%s\\fP" contents)) + + +;;; Item + + +(defun org-man-item (item contents info) + + "Transcode an ITEM element from Org to Man. +CONTENTS holds the contents of the item. INFO is a plist holding +contextual information." + + (let* ((bullet (org-element-property :bullet item)) + (type (org-element-property :type (org-element-property :parent item))) + (checkbox (case (org-element-property :checkbox item) + (on "\\o'\\(sq\\(mu'") ;; + (off "\\(sq ") ;; + (trans "\\o'\\(sq\\(mi'" ))) ;; + + (tag (let ((tag (org-element-property :tag item))) + ;; Check-boxes must belong to the tag. + (and tag (format "\\fB%s\\fP" + (concat checkbox + (org-export-data tag info))))))) + + (if (and (null tag ) + (null checkbox)) + (let* ((bullet (org-trim bullet)) + (marker (cond ((string= "-" bullet) "\\(em") + ((string= "*" bullet) "\\(bu") + ((eq type 'ordered) + (format "%s " (org-trim bullet))) + (t "\\(dg")))) + (concat ".IP " marker " 4\n" + (org-trim (or contents " " )))) + ; else + (concat ".TP\n" (or tag (concat " " checkbox)) "\n" + (org-trim (or contents " " )))))) + +;;; Keyword + + +(defun org-man-keyword (keyword contents info) + "Transcode a KEYWORD element from Org to Man. +CONTENTS is nil. INFO is a plist holding contextual information." + (let ((key (org-element-property :key keyword)) + (value (org-element-property :value keyword))) + (cond + ((string= key "MAN") value) + ((string= key "INDEX") nil) + ((string= key "TOC" ) nil)))) + + +;;; Line Break + +(defun org-man-line-break (line-break contents info) + "Transcode a LINE-BREAK object from Org to Man. +CONTENTS is nil. INFO is a plist holding contextual information." + ".br\n") + + +;;; Link + + +(defun org-man-link (link desc info) + "Transcode a LINK object from Org to Man. + +DESC is the description part of the link, or the empty string. +INFO is a plist holding contextual information. See +`org-export-data'." + + (let* ((type (org-element-property :type link)) + (raw-path (org-element-property :path link)) + ;; Ensure DESC really exists, or set it to nil. + (desc (and (not (string= desc "")) desc)) + + (path (cond + ((member type '("http" "https" "ftp" "mailto")) + (concat type ":" raw-path)) + ((string= type "file") + (when (string-match "\\(.+\\)::.+" raw-path) + (setq raw-path (match-string 1 raw-path))) + (if (file-name-absolute-p raw-path) + (concat "file://" (expand-file-name raw-path)) + (concat "file://" raw-path))) + (t raw-path))) + protocol) + (cond + ;; External link with a description part. + ((and path desc) (format "%s \\fBat\\fP \\fI%s\\fP" path desc)) + ;; External link without a description part. + (path (format "\\fI%s\\fP" path)) + ;; No path, only description. Try to do something useful. + (t (format "\\fI%s\\fP" desc))))) + + +;;; Paragraph + +(defun org-man-paragraph (paragraph contents info) + "Transcode a PARAGRAPH element from Org to Man. +CONTENTS is the contents of the paragraph, as a string. INFO is +the plist used as a communication channel." + (let ((parent (plist-get (nth 1 paragraph) :parent))) + (when parent + (let ((parent-type (car parent)) + (fixed-paragraph "")) + (cond ((and (eq parent-type 'item) + (plist-get (nth 1 parent) :bullet )) + (setq fixed-paragraph (concat "" contents))) + ((eq parent-type 'section) + (setq fixed-paragraph (concat ".PP\n" contents))) + ((eq parent-type 'footnote-definition) + (setq fixed-paragraph contents)) + (t (setq fixed-paragraph (concat "" contents)))) + fixed-paragraph )))) + + +;;; Plain List + +(defun org-man-plain-list (plain-list contents info) + "Transcode a PLAIN-LIST element from Org to Man. +CONTENTS is the contents of the list. INFO is a plist holding +contextual information." + contents) + +;;; Plain Text + +(defun org-man-plain-text (text info) + "Transcode a TEXT string from Org to Man. +TEXT is the string to transcode. INFO is a plist holding +contextual information." + (let ((output text)) + ;; Protect various chars. + (setq output (replace-regexp-in-string + "\\(?:[^\\]\\|^\\)\\(\\\\\\)\\(?:[^%$#&{}~^_\\]\\|$\\)" + "$\\" output nil t 1)) + ;; Activate smart quotes. Be sure to provide original TEXT string + ;; since OUTPUT may have been modified. + (when (plist-get info :with-smart-quotes) + (setq output (org-export-activate-smart-quotes output :utf-8 info text))) + ;; Handle break preservation if required. + (when (plist-get info :preserve-breaks) + (setq output (replace-regexp-in-string "\\(\\\\\\\\\\)?[ \t]*\n" ".br\n" + output))) + ;; Return value. + output)) + + + +;;; Planning + + +;;; Property Drawer + + +;;; Quote Block + +(defun org-man-quote-block (quote-block contents info) + "Transcode a QUOTE-BLOCK element from Org to Man. +CONTENTS holds the contents of the block. INFO is a plist +holding contextual information." + (org-man--wrap-label + quote-block + (format ".RS\n%s\n.RE" contents))) + +;;; Quote Section + +(defun org-man-quote-section (quote-section contents info) + "Transcode a QUOTE-SECTION element from Org to Man. +CONTENTS is nil. INFO is a plist holding contextual information." + (let ((value (org-remove-indentation + (org-element-property :value quote-section)))) + (when value (format ".RS\\fI%s\\fP\n.RE\n" value)))) + + +;;; Radio Target + +(defun org-man-radio-target (radio-target text info) + "Transcode a RADIO-TARGET object from Org to Man. +TEXT is the text of the target. INFO is a plist holding +contextual information." + text ) + + +;;; Section + +(defun org-man-section (section contents info) + "Transcode a SECTION element from Org to Man. +CONTENTS holds the contents of the section. INFO is a plist +holding contextual information." + contents) + + +;;; Special Block + +(defun org-man-special-block (special-block contents info) + "Transcode a SPECIAL-BLOCK element from Org to Man. +CONTENTS holds the contents of the block. INFO is a plist +holding contextual information." + (let ((type (downcase (org-element-property :type special-block)))) + (org-man--wrap-label + special-block + (format "%s\n" contents)))) + + +;;; Src Block + +(defun org-man-src-block (src-block contents info) + "Transcode a SRC-BLOCK element from Org to Man. +CONTENTS holds the contents of the item. INFO is a plist holding +contextual information." + (let* ((lang (org-element-property :language src-block)) + (code (org-element-property :value src-block)) + (custom-env (and lang + (cadr (assq (intern lang) + org-man-custom-lang-environments)))) + (num-start (case (org-element-property :number-lines src-block) + (continued (org-export-get-loc src-block info)) + (new 0))) + (retain-labels (org-element-property :retain-labels src-block))) + (cond + ;; Case 1. No source fontification. + ((not org-man-source-highlight) + (format ".RS\n.nf\n\\fC%s\\fP\n.fi\n.RE\n\n" + (org-export-format-code-default src-block info))) + (org-man-source-highlight + (let* ((tmpdir (if (featurep 'xemacs) + temp-directory + temporary-file-directory )) + + (in-file (make-temp-name + (expand-file-name "srchilite" tmpdir))) + (out-file (make-temp-name + (expand-file-name "reshilite" tmpdir))) + + (org-lang (org-element-property :language src-block)) + (lst-lang (cadr (assq (intern org-lang) + org-man-source-highlight-langs))) + + (cmd (concat "source-highlight" + " -s " lst-lang + " -f groff_man " + " -i " in-file + " -o " out-file))) + + (if lst-lang + (let ((code-block "")) + (with-temp-file in-file (insert code)) + (shell-command cmd) + (setq code-block (org-file-contents out-file)) + (delete-file in-file) + (delete-file out-file) + code-block) + (format ".RS\n.nf\n\\fC\\m[black]%s\\m[]\\fP\n.fi\n.RE" code))))))) + + +;;; Statistics Cookie + +(defun org-man-statistics-cookie (statistics-cookie contents info) + "Transcode a STATISTICS-COOKIE object from Org to Man. +CONTENTS is nil. INFO is a plist holding contextual information." + (org-element-property :value statistics-cookie)) + + +;;; Strike-Through + +(defun org-man-strike-through (strike-through contents info) + "Transcode STRIKE-THROUGH from Org to Man. +CONTENTS is the text with strike-through markup. INFO is a plist +holding contextual information." + (format "\\fI%s\\fP" contents)) + +;;; Subscript + +(defun org-man-subscript (subscript contents info) + "Transcode a SUBSCRIPT object from Org to Man. +CONTENTS is the contents of the object. INFO is a plist holding +contextual information." + (format "\\d\\s-2%s\\s+2\\u" contents)) + +;;; Superscript "^_%s$ + +(defun org-man-superscript (superscript contents info) + "Transcode a SUPERSCRIPT object from Org to Man. +CONTENTS is the contents of the object. INFO is a plist holding +contextual information." + (format "\\u\\s-2%s\\s+2\\d" contents)) + + +;;; Table +;; +;; `org-man-table' is the entry point for table transcoding. It +;; takes care of tables with a "verbatim" attribute. Otherwise, it +;; delegates the job to either `org-man-table--table.el-table' or +;; `org-man-table--org-table' functions, depending of the type of +;; the table. +;; +;; `org-man-table--align-string' is a subroutine used to build +;; alignment string for Org tables. + +(defun org-man-table (table contents info) + "Transcode a TABLE element from Org to Man. +CONTENTS is the contents of the table. INFO is a plist holding +contextual information." + (cond + ;; Case 1: verbatim table. + ((or org-man-tables-verbatim + (let ((attr (read (format "(%s)" + (mapconcat + #'identity + (org-element-property :attr_man table) + " "))))) + + (and attr (plist-get attr :verbatim)))) + + (format ".nf\n\\fC%s\\fP\n.fi" + ;; Re-create table, without affiliated keywords. + (org-trim + (org-element-interpret-data + `(table nil ,@(org-element-contents table)))))) + ;; Case 2: Standard table. + (t (org-man-table--org-table table contents info)))) + +(defun org-man-table--align-string (divider table info) + "Return an appropriate Man alignment string. +TABLE is the considered table. INFO is a plist used as +a communication channel." + (let (alignment) + ;; Extract column groups and alignment from first (non-rule) row. + (org-element-map + (org-element-map table 'table-row + (lambda (row) + (and (eq (org-element-property :type row) 'standard) row)) + info 'first-match) + 'table-cell + (lambda (cell) + (let* ((borders (org-export-table-cell-borders cell info)) + (raw-width (org-export-table-cell-width cell info)) + (width-cm (when raw-width (/ raw-width 5))) + (width (if raw-width (format "w(%dc)" + (if (< width-cm 1) 1 width-cm)) ""))) + ;; Check left border for the first cell only. + (when (and (memq 'left borders) (not alignment)) + (push "|" alignment)) + (push + (case (org-export-table-cell-alignment cell info) + (left (concat "l" width divider)) + (right (concat "r" width divider)) + (center (concat "c" width divider))) + alignment) + (when (memq 'right borders) (push "|" alignment)))) + info) + (apply 'concat (reverse alignment)))) + +(defun org-man-table--org-table (table contents info) + "Return appropriate Man code for an Org table. + +TABLE is the table type element to transcode. CONTENTS is its +contents, as a string. INFO is a plist used as a communication +channel. + +This function assumes TABLE has `org' as its `:type' attribute." + (let* ((attr (org-export-read-attribute :attr_man table)) + (label (org-element-property :name table)) + (caption (and (not (plist-get attr :disable-caption)) + (org-man--caption/label-string table info))) + (divider (if (plist-get attr :divider) "|" " ")) + + ;; Determine alignment string. + (alignment (org-man-table--align-string divider table info)) + ;; Extract others display options. + + (lines (org-split-string contents "\n")) + + (attr-list + (delq nil + (list + (and (plist-get attr :expand) "expand") + (let ((placement (plist-get attr :placement))) + (cond ((string= placement 'center) "center") + ((string= placement 'left) nil) + (t (if org-man-tables-centered "center" "")))) + (or (plist-get attr :boxtype) "box")))) + + (title-line (plist-get attr :title-line)) + (long-cells (plist-get attr :long-cells)) + + (table-format (concat + (format "%s" (or (car attr-list) "" )) + (or + (let ((output-list '())) + (when (cdr attr-list) + (dolist (attr-item (cdr attr-list)) + (setq output-list (concat output-list (format ",%s" attr-item))))) + output-list) + ""))) + + (first-line (when lines (org-split-string (car lines) "\t")))) + ;; Prepare the final format string for the table. + + + (cond + ;; Others. + (lines (concat ".TS\n " table-format ";\n" + + (format "%s.\n" + (let ((final-line "")) + (when title-line + (dotimes (i (length first-line)) + (setq final-line (concat final-line "cb" divider)))) + + (setq final-line (concat final-line "\n")) + + (if alignment + (setq final-line (concat final-line alignment)) + (dotimes (i (length first-line)) + (setq final-line (concat final-line "c" divider)))) + final-line )) + + (format "%s.TE\n" + (let ((final-line "") + (long-line "") + (lines (org-split-string contents "\n"))) + + (dolist (line-item lines) + (setq long-line "") + + (if long-cells + (progn + (if (string= line-item "_") + (setq long-line (format "%s\n" line-item)) + ;; else string = + (let ((cell-item-list (org-split-string line-item "\t"))) + (dolist (cell-item cell-item-list) + + (cond ((eq cell-item (car (last cell-item-list))) + (setq long-line (concat long-line + (format "T{\n%s\nT}\t\n" cell-item )))) + (t + (setq long-line (concat long-line + (format "T{\n%s\nT}\t" cell-item )))))) + long-line)) + ;; else long cells + (setq final-line (concat final-line long-line ))) + + (setq final-line (concat final-line line-item "\n")))) + final-line)) + + (and caption (format ".TB \"%s\"" caption))))))) + +;;; Table Cell + +(defun org-man-table-cell (table-cell contents info) + "Transcode a TABLE-CELL element from Org to Man +CONTENTS is the cell contents. INFO is a plist used as +a communication channel." + (concat (if (and contents + org-man-table-scientific-notation + (string-match orgtbl-exp-regexp contents)) + ;; Use appropriate format string for scientific + ;; notation. + (format org-man-table-scientific-notation + (match-string 1 contents) + (match-string 2 contents)) + contents ) + (when (org-export-get-next-element table-cell info) "\t"))) + + +;;; Table Row + +(defun org-man-table-row (table-row contents info) + "Transcode a TABLE-ROW element from Org to Man +CONTENTS is the contents of the row. INFO is a plist used as +a communication channel." + ;; Rules are ignored since table separators are deduced from + ;; borders of the current row. + (when (eq (org-element-property :type table-row) 'standard) + (let* ((attr (mapconcat 'identity + (org-element-property + :attr_man (org-export-get-parent table-row)) + " ")) + ;; TABLE-ROW's borders are extracted from its first cell. + (borders + (org-export-table-cell-borders + (car (org-element-contents table-row)) info))) + (concat + ;; Mark horizontal lines + (cond ((and (memq 'top borders) (memq 'above borders)) "_\n")) + contents + + (cond + ;; When BOOKTABS are activated enforce bottom rule even when + ;; no hline was specifically marked. + ((and (memq 'bottom borders) (memq 'below borders)) "\n_") + ((memq 'below borders) "\n_")))))) + + +;;; Target + +(defun org-man-target (target contents info) + "Transcode a TARGET object from Org to Man. +CONTENTS is nil. INFO is a plist holding contextual +information." + (format "\\fI%s\\fP" + (org-export-solidify-link-text (org-element-property :value target)))) + + +;;; Timestamp + +(defun org-man-timestamp (timestamp contents info) + "Transcode a TIMESTAMP object from Org to Man. + CONTENTS is nil. INFO is a plist holding contextual + information." + "" ) + + +;;; Underline + +(defun org-man-underline (underline contents info) + "Transcode UNDERLINE from Org to Man. +CONTENTS is the text with underline markup. INFO is a plist +holding contextual information." + (format "\\fI%s\\fP" contents)) + + +;;; Verbatim + +(defun org-man-verbatim (verbatim contents info) + "Transcode a VERBATIM object from Org to Man. +CONTENTS is nil. INFO is a plist used as a communication +channel." + (format ".nf\n%s\n.fi" contents)) + + +;;; Verse Block + +(defun org-man-verse-block (verse-block contents info) + "Transcode a VERSE-BLOCK element from Org to Man. +CONTENTS is verse block contents. INFO is a plist holding +contextual information." + (format ".RS\n.ft I\n%s\n.ft\n.RE" contents)) + + + +;;; Interactive functions + +(defun org-man-export-to-man + (&optional async subtreep visible-only body-only ext-plist) + "Export current buffer to a Man file. + +If narrowing is active in the current buffer, only export its +narrowed part. + +If a region is active, export that region. + +A non-nil optional argument ASYNC means the process should happen +asynchronously. The resulting file should be accessible through +the `org-export-stack' interface. + +When optional argument SUBTREEP is non-nil, export the sub-tree +at point, extracting information from the headline properties +first. + +When optional argument VISIBLE-ONLY is non-nil, don't export +contents of hidden elements. + +When optional argument BODY-ONLY is non-nil, only the body +without any markers. + +EXT-PLIST, when provided, is a property list with external +parameters overriding Org default settings, but still inferior to +file-local settings. + +Return output file's name." + (interactive) + (let ((outfile (org-export-output-file-name ".man" subtreep))) + (org-export-to-file 'man outfile + async subtreep visible-only body-only ext-plist))) + +(defun org-man-export-to-pdf + (&optional async subtreep visible-only body-only ext-plist) + "Export current buffer to Groff then process through to PDF. + +If narrowing is active in the current buffer, only export its +narrowed part. + +If a region is active, export that region. + +A non-nil optional argument ASYNC means the process should happen +asynchronously. The resulting file should be accessible through +the `org-export-stack' interface. + +When optional argument SUBTREEP is non-nil, export the sub-tree +at point, extracting information from the headline properties +first. + +When optional argument VISIBLE-ONLY is non-nil, don't export +contents of hidden elements. + +When optional argument BODY-ONLY is non-nil, only write between +markers. + +EXT-PLIST, when provided, is a property list with external +parameters overriding Org default settings, but still inferior to +file-local settings. + +Return PDF file's name." + (interactive) + (let ((outfile (org-export-output-file-name ".man" subtreep))) + (org-export-to-file 'man outfile + async subtreep visible-only body-only ext-plist + (lambda (file) (org-latex-compile file))))) + +(defun org-man-compile (file) + "Compile a Groff file. + +FILE is the name of the file being compiled. Processing is done +through the command specified in `org-man-pdf-process'. + +Return PDF file name or an error if it couldn't be produced." + (let* ((base-name (file-name-sans-extension (file-name-nondirectory file))) + (full-name (file-truename file)) + (out-dir (file-name-directory file)) + ;; Properly set working directory for compilation. + (default-directory (if (file-name-absolute-p file) + (file-name-directory full-name) + default-directory)) + errors) + (message (format "Processing Groff file %s..." file)) + (save-window-excursion + (cond + ;; A function is provided: Apply it. + ((functionp org-man-pdf-process) + (funcall org-man-pdf-process (shell-quote-argument file))) + ;; A list is provided: Replace %b, %f and %o with appropriate + ;; values in each command before applying it. Output is + ;; redirected to "*Org PDF Groff Output*" buffer. + ((consp org-man-pdf-process) + (let ((outbuf (get-buffer-create "*Org PDF Groff Output*"))) + (mapc + (lambda (command) + (shell-command + (replace-regexp-in-string + "%b" (shell-quote-argument base-name) + (replace-regexp-in-string + "%f" (shell-quote-argument full-name) + (replace-regexp-in-string + "%o" (shell-quote-argument out-dir) command t t) t t) t t) + outbuf)) + org-man-pdf-process) + ;; Collect standard errors from output buffer. + (setq errors (org-man-collect-errors outbuf)))) + (t (error "No valid command to process to PDF"))) + (let ((pdffile (concat out-dir base-name ".pdf"))) + ;; Check for process failure. Provide collected errors if + ;; possible. + (if (not (file-exists-p pdffile)) + (error (concat (format "PDF file %s wasn't produced" pdffile) + (when errors (concat ": " errors)))) + ;; Else remove log files, when specified, and signal end of + ;; process to user, along with any error encountered. + (when org-man-remove-logfiles + (dolist (ext org-man-logfiles-extensions) + (let ((file (concat out-dir base-name "." ext))) + (when (file-exists-p file) (delete-file file))))) + (message (concat "Process completed" + (if (not errors) "." + (concat " with errors: " errors))))) + ;; Return output file name. + pdffile)))) + +(defun org-man-collect-errors (buffer) + "Collect some kind of errors from \"groff\" output +BUFFER is the buffer containing output. +Return collected error types as a string, or nil if there was +none." + (with-current-buffer buffer + (save-excursion + (goto-char (point-max)) + ;; Find final run + nil ))) + + +(provide 'ox-man) + +;; Local variables: +;; generated-autoload-file: "org-loaddefs.el" +;; End: + +;;; ox-man.el ends here diff --git a/lisp/org/ox-md.el b/lisp/org/ox-md.el new file mode 100644 index 00000000000..7d540787d98 --- /dev/null +++ b/lisp/org/ox-md.el @@ -0,0 +1,483 @@ +;;; ox-md.el --- Markdown Back-End for Org Export Engine + +;; Copyright (C) 2012, 2013 Free Software Foundation, Inc. + +;; Author: Nicolas Goaziou +;; Keywords: org, wp, markdown + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;; This library implements a Markdown back-end (vanilla flavour) for +;; Org exporter, based on `html' back-end. See Org manual for more +;; information. + +;;; Code: + +(eval-when-compile (require 'cl)) +(require 'ox-html) + + + +;;; User-Configurable Variables + +(defgroup org-export-md nil + "Options specific to Markdown export back-end." + :tag "Org Markdown" + :group 'org-export + :version "24.4" + :package-version '(Org . "8.0")) + +(defcustom org-md-headline-style 'atx + "Style used to format headlines. +This variable can be set to either `atx' or `setext'." + :group 'org-export-md + :type '(choice + (const :tag "Use \"atx\" style" atx) + (const :tag "Use \"Setext\" style" setext))) + + + +;;; Define Back-End + +(org-export-define-derived-backend 'md 'html + :export-block '("MD" "MARKDOWN") + :filters-alist '((:filter-parse-tree . org-md-separate-elements)) + :menu-entry + '(?m "Export to Markdown" + ((?M "To temporary buffer" + (lambda (a s v b) (org-md-export-as-markdown a s v))) + (?m "To file" (lambda (a s v b) (org-md-export-to-markdown a s v))) + (?o "To file and open" + (lambda (a s v b) + (if a (org-md-export-to-markdown t s v) + (org-open-file (org-md-export-to-markdown nil s v))))))) + :translate-alist '((bold . org-md-bold) + (code . org-md-verbatim) + (comment . (lambda (&rest args) "")) + (comment-block . (lambda (&rest args) "")) + (example-block . org-md-example-block) + (fixed-width . org-md-example-block) + (footnote-definition . ignore) + (footnote-reference . ignore) + (headline . org-md-headline) + (horizontal-rule . org-md-horizontal-rule) + (inline-src-block . org-md-verbatim) + (italic . org-md-italic) + (item . org-md-item) + (line-break . org-md-line-break) + (link . org-md-link) + (paragraph . org-md-paragraph) + (plain-list . org-md-plain-list) + (plain-text . org-md-plain-text) + (quote-block . org-md-quote-block) + (quote-section . org-md-example-block) + (section . org-md-section) + (src-block . org-md-example-block) + (template . org-md-template) + (verbatim . org-md-verbatim))) + + + +;;; Filters + +(defun org-md-separate-elements (tree backend info) + "Make sure elements are separated by at least one blank line. + +TREE is the parse tree being exported. BACKEND is the export +back-end used. INFO is a plist used as a communication channel. + +Assume BACKEND is `md'." + (org-element-map tree org-element-all-elements + (lambda (elem) + (unless (eq (org-element-type elem) 'org-data) + (org-element-put-property + elem :post-blank + (let ((post-blank (org-element-property :post-blank elem))) + (if (not post-blank) 1 (max 1 post-blank))))))) + ;; Return updated tree. + tree) + + + +;;; Transcode Functions + +;;;; Bold + +(defun org-md-bold (bold contents info) + "Transcode BOLD object into Markdown format. +CONTENTS is the text within bold markup. INFO is a plist used as +a communication channel." + (format "**%s**" contents)) + + +;;;; Code and Verbatim + +(defun org-md-verbatim (verbatim contents info) + "Transcode VERBATIM object into Markdown format. +CONTENTS is nil. INFO is a plist used as a communication +channel." + (let ((value (org-element-property :value verbatim))) + (format (cond ((not (string-match "`" value)) "`%s`") + ((or (string-match "\\``" value) + (string-match "`\\'" value)) + "`` %s ``") + (t "``%s``")) + value))) + + +;;;; Example Block and Src Block + +(defun org-md-example-block (example-block contents info) + "Transcode EXAMPLE-BLOCK element into Markdown format. +CONTENTS is nil. INFO is a plist used as a communication +channel." + (replace-regexp-in-string + "^" " " + (org-remove-indentation + (org-element-property :value example-block)))) + + +;;;; Headline + +(defun org-md-headline (headline contents info) + "Transcode HEADLINE element into Markdown format. +CONTENTS is the headline contents. INFO is a plist used as +a communication channel." + (unless (org-element-property :footnote-section-p headline) + (let* ((level (org-export-get-relative-level headline info)) + (title (org-export-data (org-element-property :title headline) info)) + (todo (and (plist-get info :with-todo-keywords) + (let ((todo (org-element-property :todo-keyword + headline))) + (and todo (concat (org-export-data todo info) " "))))) + (tags (and (plist-get info :with-tags) + (let ((tag-list (org-export-get-tags headline info))) + (and tag-list + (format " :%s:" + (mapconcat 'identity tag-list ":")))))) + (priority + (and (plist-get info :with-priority) + (let ((char (org-element-property :priority headline))) + (and char (format "[#%c] " char))))) + ;; Headline text without tags. + (heading (concat todo priority title))) + (cond + ;; Cannot create a headline. Fall-back to a list. + ((or (org-export-low-level-p headline info) + (not (memq org-md-headline-style '(atx setext))) + (and (eq org-md-headline-style 'atx) (> level 6)) + (and (eq org-md-headline-style 'setext) (> level 2))) + (let ((bullet + (if (not (org-export-numbered-headline-p headline info)) "-" + (concat (number-to-string + (car (last (org-export-get-headline-number + headline info)))) + ".")))) + (concat bullet (make-string (- 4 (length bullet)) ? ) heading tags + "\n\n" + (and contents + (replace-regexp-in-string "^" " " contents))))) + ;; Use "Setext" style. + ((eq org-md-headline-style 'setext) + (concat heading tags "\n" + (make-string (length heading) (if (= level 1) ?= ?-)) + "\n\n" + contents)) + ;; Use "atx" style. + (t (concat (make-string level ?#) " " heading tags "\n\n" contents)))))) + + +;;;; Horizontal Rule + +(defun org-md-horizontal-rule (horizontal-rule contents info) + "Transcode HORIZONTAL-RULE element into Markdown format. +CONTENTS is the horizontal rule contents. INFO is a plist used +as a communication channel." + "---") + + +;;;; Italic + +(defun org-md-italic (italic contents info) + "Transcode ITALIC object into Markdown format. +CONTENTS is the text within italic markup. INFO is a plist used +as a communication channel." + (format "*%s*" contents)) + + +;;;; Item + +(defun org-md-item (item contents info) + "Transcode ITEM element into Markdown format. +CONTENTS is the item contents. INFO is a plist used as +a communication channel." + (let* ((type (org-element-property :type (org-export-get-parent item))) + (struct (org-element-property :structure item)) + (bullet (if (not (eq type 'ordered)) "-" + (concat (number-to-string + (car (last (org-list-get-item-number + (org-element-property :begin item) + struct + (org-list-prevs-alist struct) + (org-list-parents-alist struct))))) + ".")))) + (concat bullet + (make-string (- 4 (length bullet)) ? ) + (case (org-element-property :checkbox item) + (on "[X] ") + (trans "[-] ") + (off "[ ] ")) + (let ((tag (org-element-property :tag item))) + (and tag (format "**%s:** "(org-export-data tag info)))) + (org-trim (replace-regexp-in-string "^" " " contents))))) + + +;;;; Line Break + +(defun org-md-line-break (line-break contents info) + "Transcode LINE-BREAK object into Markdown format. +CONTENTS is nil. INFO is a plist used as a communication +channel." + " \n") + + +;;;; Link + +(defun org-md-link (link contents info) + "Transcode LINE-BREAK object into Markdown format. +CONTENTS is the link's description. INFO is a plist used as +a communication channel." + (let ((--link-org-files-as-html-maybe + (function + (lambda (raw-path info) + ;; Treat links to `file.org' as links to `file.html', if + ;; needed. See `org-html-link-org-files-as-html'. + (cond + ((and org-html-link-org-files-as-html + (string= ".org" + (downcase (file-name-extension raw-path ".")))) + (concat (file-name-sans-extension raw-path) "." + (plist-get info :html-extension))) + (t raw-path))))) + (type (org-element-property :type link))) + (cond ((member type '("custom-id" "id")) + (let ((destination (org-export-resolve-id-link link info))) + (if (stringp destination) ; External file. + (let ((path (funcall --link-org-files-as-html-maybe + destination info))) + (if (not contents) (format "<%s>" path) + (format "[%s](%s)" contents path))) + (concat + (and contents (concat contents " ")) + (format "(%s)" + (format (org-export-translate "See section %s" :html info) + (mapconcat 'number-to-string + (org-export-get-headline-number + destination info) + "."))))))) + ((org-export-inline-image-p link org-html-inline-image-rules) + (let ((path (let ((raw-path (org-element-property :path link))) + (if (not (file-name-absolute-p raw-path)) raw-path + (expand-file-name raw-path))))) + (format "![%s](%s)" + (let ((caption (org-export-get-caption + (org-export-get-parent-element link)))) + (when caption (org-export-data caption info))) + path))) + ((string= type "coderef") + (let ((ref (org-element-property :path link))) + (format (org-export-get-coderef-format ref contents) + (org-export-resolve-coderef ref info)))) + ((equal type "radio") + (let ((destination (org-export-resolve-radio-link link info))) + (org-export-data (org-element-contents destination) info))) + ((equal type "fuzzy") + (let ((destination (org-export-resolve-fuzzy-link link info))) + (if (org-string-nw-p contents) contents + (when destination + (let ((number (org-export-get-ordinal destination info))) + (when number + (if (atom number) (number-to-string number) + (mapconcat 'number-to-string number ".")))))))) + (t (let* ((raw-path (org-element-property :path link)) + (path (cond + ((member type '("http" "https" "ftp")) + (concat type ":" raw-path)) + ((equal type "file") + ;; Treat links to ".org" files as ".html", + ;; if needed. + (setq raw-path + (funcall --link-org-files-as-html-maybe + raw-path info)) + ;; If file path is absolute, prepend it + ;; with protocol component - "file://". + (if (not (file-name-absolute-p raw-path)) raw-path + (concat "file://" (expand-file-name raw-path)))) + (t raw-path)))) + (if (not contents) (format "<%s>" path) + (format "[%s](%s)" contents path))))))) + + +;;;; Paragraph + +(defun org-md-paragraph (paragraph contents info) + "Transcode PARAGRAPH element into Markdown format. +CONTENTS is the paragraph contents. INFO is a plist used as +a communication channel." + (let ((first-object (car (org-element-contents paragraph)))) + ;; If paragraph starts with a #, protect it. + (if (and (stringp first-object) (string-match "\\`#" first-object)) + (replace-regexp-in-string "\\`#" "\\#" contents nil t) + contents))) + + +;;;; Plain List + +(defun org-md-plain-list (plain-list contents info) + "Transcode PLAIN-LIST element into Markdown format. +CONTENTS is the plain-list contents. INFO is a plist used as +a communication channel." + contents) + + +;;;; Plain Text + +(defun org-md-plain-text (text info) + "Transcode a TEXT string into Markdown format. +TEXT is the string to transcode. INFO is a plist holding +contextual information." + (when (plist-get info :with-smart-quotes) + (setq text (org-export-activate-smart-quotes text :html info))) + ;; Protect ambiguous #. This will protect # at the beginning of + ;; a line, but not at the beginning of a paragraph. See + ;; `org-md-paragraph'. + (setq text (replace-regexp-in-string "\n#" "\n\\\\#" text)) + ;; Protect ambiguous ! + (setq text (replace-regexp-in-string "\\(!\\)\\[" "\\\\!" text nil nil 1)) + ;; Protect `, *, _ and \ + (setq text (replace-regexp-in-string "[`*_\\]" "\\\\\\&" text)) + ;; Handle special strings, if required. + (when (plist-get info :with-special-strings) + (setq text (org-html-convert-special-strings text))) + ;; Handle break preservation, if required. + (when (plist-get info :preserve-breaks) + (setq text (replace-regexp-in-string "[ \t]*\n" " \n" text))) + ;; Return value. + text) + + +;;;; Quote Block + +(defun org-md-quote-block (quote-block contents info) + "Transcode QUOTE-BLOCK element into Markdown format. +CONTENTS is the quote-block contents. INFO is a plist used as +a communication channel." + (replace-regexp-in-string + "^" "> " + (replace-regexp-in-string "\n\\'" "" contents))) + + +;;;; Section + +(defun org-md-section (section contents info) + "Transcode SECTION element into Markdown format. +CONTENTS is the section contents. INFO is a plist used as +a communication channel." + contents) + + +;;;; Template + +(defun org-md-template (contents info) + "Return complete document string after Markdown conversion. +CONTENTS is the transcoded contents string. INFO is a plist used +as a communication channel." + contents) + + + +;;; Interactive function + +;;;###autoload +(defun org-md-export-as-markdown (&optional async subtreep visible-only) + "Export current buffer to a Markdown buffer. + +If narrowing is active in the current buffer, only export its +narrowed part. + +If a region is active, export that region. + +A non-nil optional argument ASYNC means the process should happen +asynchronously. The resulting buffer should be accessible +through the `org-export-stack' interface. + +When optional argument SUBTREEP is non-nil, export the sub-tree +at point, extracting information from the headline properties +first. + +When optional argument VISIBLE-ONLY is non-nil, don't export +contents of hidden elements. + +Export is done in a buffer named \"*Org MD Export*\", which will +be displayed when `org-export-show-temporary-export-buffer' is +non-nil." + (interactive) + (org-export-to-buffer 'md "*Org MD Export*" + async subtreep visible-only nil nil (lambda () (text-mode)))) + +;;;###autoload +(defun org-md-convert-region-to-md () + "Assume the current region has org-mode syntax, and convert it to Markdown. +This can be used in any buffer. For example, you can write an +itemized list in org-mode syntax in a Markdown buffer and use +this command to convert it." + (interactive) + (org-export-replace-region-by 'md)) + + +;;;###autoload +(defun org-md-export-to-markdown (&optional async subtreep visible-only) + "Export current buffer to a Markdown file. + +If narrowing is active in the current buffer, only export its +narrowed part. + +If a region is active, export that region. + +A non-nil optional argument ASYNC means the process should happen +asynchronously. The resulting file should be accessible through +the `org-export-stack' interface. + +When optional argument SUBTREEP is non-nil, export the sub-tree +at point, extracting information from the headline properties +first. + +When optional argument VISIBLE-ONLY is non-nil, don't export +contents of hidden elements. + +Return output file's name." + (interactive) + (let ((outfile (org-export-output-file-name ".md" subtreep))) + (org-export-to-file 'md outfile async subtreep visible-only))) + + +(provide 'ox-md) + +;; Local variables: +;; generated-autoload-file: "org-loaddefs.el" +;; End: + +;;; ox-md.el ends here diff --git a/lisp/org/ox-odt.el b/lisp/org/ox-odt.el new file mode 100644 index 00000000000..07f6889ae95 --- /dev/null +++ b/lisp/org/ox-odt.el @@ -0,0 +1,4413 @@ +;;; ox-odt.el --- OpenDocument Text Exporter for Org Mode + +;; Copyright (C) 2010-2013 Free Software Foundation, Inc. + +;; Author: Jambunathan K +;; Keywords: outlines, hypermedia, calendar, wp +;; Homepage: http://orgmode.org + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;;; Code: + +(eval-when-compile + (require 'cl) + (require 'table nil 'noerror)) +(require 'format-spec) +(require 'ox) +(require 'org-compat) + +;;; Define Back-End + +(org-export-define-backend 'odt + '((bold . org-odt-bold) + (center-block . org-odt-center-block) + (clock . org-odt-clock) + (code . org-odt-code) + (drawer . org-odt-drawer) + (dynamic-block . org-odt-dynamic-block) + (entity . org-odt-entity) + (example-block . org-odt-example-block) + (export-block . org-odt-export-block) + (export-snippet . org-odt-export-snippet) + (fixed-width . org-odt-fixed-width) + (footnote-definition . org-odt-footnote-definition) + (footnote-reference . org-odt-footnote-reference) + (headline . org-odt-headline) + (horizontal-rule . org-odt-horizontal-rule) + (inline-src-block . org-odt-inline-src-block) + (inlinetask . org-odt-inlinetask) + (italic . org-odt-italic) + (item . org-odt-item) + (keyword . org-odt-keyword) + (latex-environment . org-odt-latex-environment) + (latex-fragment . org-odt-latex-fragment) + (line-break . org-odt-line-break) + (link . org-odt-link) + (paragraph . org-odt-paragraph) + (plain-list . org-odt-plain-list) + (plain-text . org-odt-plain-text) + (planning . org-odt-planning) + (property-drawer . org-odt-property-drawer) + (quote-block . org-odt-quote-block) + (quote-section . org-odt-quote-section) + (radio-target . org-odt-radio-target) + (section . org-odt-section) + (special-block . org-odt-special-block) + (src-block . org-odt-src-block) + (statistics-cookie . org-odt-statistics-cookie) + (strike-through . org-odt-strike-through) + (subscript . org-odt-subscript) + (superscript . org-odt-superscript) + (table . org-odt-table) + (table-cell . org-odt-table-cell) + (table-row . org-odt-table-row) + (target . org-odt-target) + (template . org-odt-template) + (timestamp . org-odt-timestamp) + (underline . org-odt-underline) + (verbatim . org-odt-verbatim) + (verse-block . org-odt-verse-block)) + :export-block "ODT" + :filters-alist '((:filter-parse-tree + . (org-odt--translate-latex-fragments + org-odt--translate-description-lists + org-odt--translate-list-tables))) + :menu-entry + '(?o "Export to ODT" + ((?o "As ODT file" org-odt-export-to-odt) + (?O "As ODT file and open" + (lambda (a s v b) + (if a (org-odt-export-to-odt t s v) + (org-open-file (org-odt-export-to-odt nil s v) 'system)))))) + :options-alist + '((:odt-styles-file "ODT_STYLES_FILE" nil nil t) + ;; Redefine regular option. + (:with-latex nil "tex" org-odt-with-latex))) + + +;;; Dependencies + +;;; Hooks + +;;; Function Declarations + +(declare-function org-id-find-id-file "org-id" (id)) +(declare-function hfy-face-to-style "htmlfontify" (fn)) +(declare-function hfy-face-or-def-to-name "htmlfontify" (fn)) +(declare-function archive-zip-extract "arc-mode" (archive name)) +(declare-function org-create-math-formula "org" (latex-frag &optional mathml-file)) +(declare-function browse-url-file-url "browse-url" (file)) + + + +;;; Internal Variables + +(defconst org-odt-lib-dir + (file-name-directory load-file-name) + "Location of ODT exporter. +Use this to infer values of `org-odt-styles-dir' and +`org-odt-schema-dir'.") + +(defvar org-odt-data-dir + (expand-file-name "../../etc/" org-odt-lib-dir) + "Data directory for ODT exporter. +Use this to infer values of `org-odt-styles-dir' and +`org-odt-schema-dir'.") + +(defconst org-odt-special-string-regexps + '(("\\\\-" . "­\\1") ; shy + ("---\\([^-]\\)" . "—\\1") ; mdash + ("--\\([^-]\\)" . "–\\1") ; ndash + ("\\.\\.\\." . "…")) ; hellip + "Regular expressions for special string conversion.") + +(defconst org-odt-schema-dir-list + (list + (and org-odt-data-dir + (expand-file-name "./schema/" org-odt-data-dir)) ; bail out + (eval-when-compile + (and (boundp 'org-odt-data-dir) org-odt-data-dir ; see make install + (expand-file-name "./schema/" org-odt-data-dir)))) + "List of directories to search for OpenDocument schema files. +Use this list to set the default value of +`org-odt-schema-dir'. The entries in this list are +populated heuristically based on the values of `org-odt-lib-dir' +and `org-odt-data-dir'.") + +(defconst org-odt-styles-dir-list + (list + (and org-odt-data-dir + (expand-file-name "./styles/" org-odt-data-dir)) ; bail out + (eval-when-compile + (and (boundp 'org-odt-data-dir) org-odt-data-dir ; see make install + (expand-file-name "./styles/" org-odt-data-dir))) + (expand-file-name "../../etc/styles/" org-odt-lib-dir) ; git + (expand-file-name "./etc/styles/" org-odt-lib-dir) ; elpa + (expand-file-name "./org/" data-directory) ; system + ) + "List of directories to search for OpenDocument styles files. +See `org-odt-styles-dir'. The entries in this list are populated +heuristically based on the values of `org-odt-lib-dir' and +`org-odt-data-dir'.") + +(defconst org-odt-styles-dir + (let* ((styles-dir + (catch 'styles-dir + (message "Debug (ox-odt): Searching for OpenDocument styles files...") + (mapc (lambda (styles-dir) + (when styles-dir + (message "Debug (ox-odt): Trying %s..." styles-dir) + (when (and (file-readable-p + (expand-file-name + "OrgOdtContentTemplate.xml" styles-dir)) + (file-readable-p + (expand-file-name + "OrgOdtStyles.xml" styles-dir))) + (message "Debug (ox-odt): Using styles under %s" + styles-dir) + (throw 'styles-dir styles-dir)))) + org-odt-styles-dir-list) + nil))) + (unless styles-dir + (error "Error (ox-odt): Cannot find factory styles files, aborting")) + styles-dir) + "Directory that holds auxiliary XML files used by the ODT exporter. + +This directory contains the following XML files - + \"OrgOdtStyles.xml\" and \"OrgOdtContentTemplate.xml\". These + XML files are used as the default values of + `org-odt-styles-file' and + `org-odt-content-template-file'. + +The default value of this variable varies depending on the +version of org in use and is initialized from +`org-odt-styles-dir-list'. Note that the user could be using org +from one of: org's own private git repository, GNU ELPA tar or +standard Emacs.") + +(defconst org-odt-bookmark-prefix "OrgXref.") + +(defconst org-odt-manifest-file-entry-tag + "\n") + +(defconst org-odt-file-extensions + '(("odt" . "OpenDocument Text") + ("ott" . "OpenDocument Text Template") + ("odm" . "OpenDocument Master Document") + ("ods" . "OpenDocument Spreadsheet") + ("ots" . "OpenDocument Spreadsheet Template") + ("odg" . "OpenDocument Drawing (Graphics)") + ("otg" . "OpenDocument Drawing Template") + ("odp" . "OpenDocument Presentation") + ("otp" . "OpenDocument Presentation Template") + ("odi" . "OpenDocument Image") + ("odf" . "OpenDocument Formula") + ("odc" . "OpenDocument Chart"))) + +(defconst org-odt-table-style-format + " + + + +" + "Template for auto-generated Table styles.") + +(defvar org-odt-automatic-styles '() + "Registry of automatic styles for various OBJECT-TYPEs. +The variable has the following form: +\(\(OBJECT-TYPE-A + \(\(OBJECT-NAME-A.1 OBJECT-PROPS-A.1\) + \(OBJECT-NAME-A.2 OBJECT-PROPS-A.2\) ...\)\) + \(OBJECT-TYPE-B + \(\(OBJECT-NAME-B.1 OBJECT-PROPS-B.1\) + \(OBJECT-NAME-B.2 OBJECT-PROPS-B.2\) ...\)\) + ...\). + +OBJECT-TYPEs could be \"Section\", \"Table\", \"Figure\" etc. +OBJECT-PROPS is (typically) a plist created by passing +\"#+ATTR_ODT: \" option to `org-odt-parse-block-attributes'. + +Use `org-odt-add-automatic-style' to add update this variable.'") + +(defvar org-odt-object-counters nil + "Running counters for various OBJECT-TYPEs. +Use this to generate automatic names and style-names. See +`org-odt-add-automatic-style'.") + +(defvar org-odt-src-block-paragraph-format + " + + + + + " + "Custom paragraph style for colorized source and example blocks. +This style is much the same as that of \"OrgFixedWidthBlock\" +except that the foreground and background colors are set +according to the default face identified by the `htmlfontify'.") + +(defvar hfy-optimisations) +(defvar org-odt-embedded-formulas-count 0) +(defvar org-odt-embedded-images-count 0) +(defvar org-odt-image-size-probe-method + (append (and (executable-find "identify") '(imagemagick)) ; See Bug#10675 + '(emacs fixed)) + "Ordered list of methods for determining image sizes.") + +(defvar org-odt-default-image-sizes-alist + '(("as-char" . (5 . 0.4)) + ("paragraph" . (5 . 5))) + "Hardcoded image dimensions one for each of the anchor + methods.") + +;; A4 page size is 21.0 by 29.7 cms +;; The default page settings has 2cm margin on each of the sides. So +;; the effective text area is 17.0 by 25.7 cm +(defvar org-odt-max-image-size '(17.0 . 20.0) + "Limiting dimensions for an embedded image.") + +(defconst org-odt-label-styles + '(("math-formula" "%c" "text" "(%n)") + ("math-label" "(%n)" "text" "(%n)") + ("category-and-value" "%e %n: %c" "category-and-value" "%e %n") + ("value" "%e %n: %c" "value" "%n")) + "Specify how labels are applied and referenced. + +This is an alist where each element is of the form: + + \(STYLE-NAME ATTACH-FMT REF-MODE REF-FMT) + +ATTACH-FMT controls how labels and captions are attached to an +entity. It may contain following specifiers - %e and %c. %e is +replaced with the CATEGORY-NAME. %n is replaced with +\" SEQNO \". %c is replaced +with CAPTION. + +REF-MODE and REF-FMT controls how label references are generated. +The following XML is generated for a label reference - +\" +REF-FMT \". REF-FMT may contain following +specifiers - %e and %n. %e is replaced with the CATEGORY-NAME. +%n is replaced with SEQNO. + +See also `org-odt-format-label'.") + +(defvar org-odt-category-map-alist + '(("__Table__" "Table" "value" "Table" org-odt--enumerable-p) + ("__Figure__" "Illustration" "value" "Figure" org-odt--enumerable-image-p) + ("__MathFormula__" "Text" "math-formula" "Equation" org-odt--enumerable-formula-p) + ("__DvipngImage__" "Equation" "value" "Equation" org-odt--enumerable-latex-image-p) + ("__Listing__" "Listing" "value" "Listing" org-odt--enumerable-p)) + "Map a CATEGORY-HANDLE to OD-VARIABLE and LABEL-STYLE. + +This is a list where each entry is of the form: + + \(CATEGORY-HANDLE OD-VARIABLE LABEL-STYLE CATEGORY-NAME ENUMERATOR-PREDICATE) + +CATEGORY_HANDLE identifies the captionable entity in question. + +OD-VARIABLE is the OpenDocument sequence counter associated with +the entity. These counters are declared within +\"...\" block of +`org-odt-content-template-file'. + +LABEL-STYLE is a key into `org-odt-label-styles' and specifies +how a given entity should be captioned and referenced. + +CATEGORY-NAME is used for qualifying captions on export. + +ENUMERATOR-PREDICATE is used for assigning a sequence number to +the entity. See `org-odt--enumerate'.") + +(defvar org-odt-manifest-file-entries nil) +(defvar hfy-user-sheet-assoc) + +(defvar org-odt-zip-dir nil + "Temporary work directory for OpenDocument exporter.") + + + +;;; User Configuration Variables + +(defgroup org-export-odt nil + "Options for exporting Org mode files to ODT." + :tag "Org Export ODT" + :group 'org-export) + + +;;;; Debugging + +(defcustom org-odt-prettify-xml nil + "Specify whether or not the xml output should be prettified. +When this option is turned on, `indent-region' is run on all +component xml buffers before they are saved. Turn this off for +regular use. Turn this on if you need to examine the xml +visually." + :group 'org-export-odt + :version "24.1" + :type 'boolean) + + +;;;; Document schema + +(require 'rng-loc) +(defcustom org-odt-schema-dir + (let* ((schema-dir + (catch 'schema-dir + (message "Debug (ox-odt): Searching for OpenDocument schema files...") + (mapc + (lambda (schema-dir) + (when schema-dir + (message "Debug (ox-odt): Trying %s..." schema-dir) + (when (and (file-expand-wildcards + (expand-file-name "od-manifest-schema*.rnc" + schema-dir)) + (file-expand-wildcards + (expand-file-name "od-schema*.rnc" + schema-dir)) + (file-readable-p + (expand-file-name "schemas.xml" schema-dir))) + (message "Debug (ox-odt): Using schema files under %s" + schema-dir) + (throw 'schema-dir schema-dir)))) + org-odt-schema-dir-list) + (message "Debug (ox-odt): No OpenDocument schema files installed") + nil))) + schema-dir) + "Directory that contains OpenDocument schema files. + +This directory contains: +1. rnc files for OpenDocument schema +2. a \"schemas.xml\" file that specifies locating rules needed + for auto validation of OpenDocument XML files. + +Use the customize interface to set this variable. This ensures +that `rng-schema-locating-files' is updated and auto-validation +of OpenDocument XML takes place based on the value +`rng-nxml-auto-validate-flag'. + +The default value of this variable varies depending on the +version of org in use and is initialized from +`org-odt-schema-dir-list'. The OASIS schema files are available +only in the org's private git repository. It is *not* bundled +with GNU ELPA tar or standard Emacs distribution." + :type '(choice + (const :tag "Not set" nil) + (directory :tag "Schema directory")) + :group 'org-export-odt + :version "24.1" + :set + (lambda (var value) + "Set `org-odt-schema-dir'. +Also add it to `rng-schema-locating-files'." + (let ((schema-dir value)) + (set var + (if (and + (file-expand-wildcards + (expand-file-name "od-manifest-schema*.rnc" schema-dir)) + (file-expand-wildcards + (expand-file-name "od-schema*.rnc" schema-dir)) + (file-readable-p + (expand-file-name "schemas.xml" schema-dir))) + schema-dir + (when value + (message "Error (ox-odt): %s has no OpenDocument schema files" + value)) + nil))) + (when org-odt-schema-dir + (eval-after-load 'rng-loc + '(add-to-list 'rng-schema-locating-files + (expand-file-name "schemas.xml" + org-odt-schema-dir)))))) + + +;;;; Document styles + +(defcustom org-odt-content-template-file nil + "Template file for \"content.xml\". +The exporter embeds the exported content just before +\"\" element. + +If unspecified, the file named \"OrgOdtContentTemplate.xml\" +under `org-odt-styles-dir' is used." + :type '(choice (const nil) + (file)) + :group 'org-export-odt + :version "24.1") + +(defcustom org-odt-styles-file nil + "Default styles file for use with ODT export. +Valid values are one of: +1. nil +2. path to a styles.xml file +3. path to a *.odt or a *.ott file +4. list of the form (ODT-OR-OTT-FILE (FILE-MEMBER-1 FILE-MEMBER-2 +...)) + +In case of option 1, an in-built styles.xml is used. See +`org-odt-styles-dir' for more information. + +In case of option 3, the specified file is unzipped and the +styles.xml embedded therein is used. + +In case of option 4, the specified ODT-OR-OTT-FILE is unzipped +and FILE-MEMBER-1, FILE-MEMBER-2 etc are copied in to the +generated odt file. Use relative path for specifying the +FILE-MEMBERS. styles.xml must be specified as one of the +FILE-MEMBERS. + +Use options 1, 2 or 3 only if styles.xml alone suffices for +achieving the desired formatting. Use option 4, if the styles.xml +references additional files like header and footer images for +achieving the desired formatting. + +Use \"#+ODT_STYLES_FILE: ...\" directive to set this variable on +a per-file basis. For example, + +#+ODT_STYLES_FILE: \"/path/to/styles.xml\" or +#+ODT_STYLES_FILE: (\"/path/to/file.ott\" (\"styles.xml\" \"image/hdr.png\"))." + :group 'org-export-odt + :version "24.1" + :type + '(choice + (const :tag "Factory settings" nil) + (file :must-match t :tag "styles.xml") + (file :must-match t :tag "ODT or OTT file") + (list :tag "ODT or OTT file + Members" + (file :must-match t :tag "ODF Text or Text Template file") + (cons :tag "Members" + (file :tag " Member" "styles.xml") + (repeat (file :tag "Member")))))) + +(defcustom org-odt-display-outline-level 2 + "Outline levels considered for enumerating captioned entities." + :group 'org-export-odt + :version "24.2" + :type 'integer) + +;;;; Document conversion + +(defcustom org-odt-convert-processes + '(("LibreOffice" + "soffice --headless --convert-to %f%x --outdir %d %i") + ("unoconv" + "unoconv -f %f -o %d %i")) + "Specify a list of document converters and their usage. +The converters in this list are offered as choices while +customizing `org-odt-convert-process'. + +This variable is a list where each element is of the +form (CONVERTER-NAME CONVERTER-CMD). CONVERTER-NAME is the name +of the converter. CONVERTER-CMD is the shell command for the +converter and can contain format specifiers. These format +specifiers are interpreted as below: + +%i input file name in full +%I input file name as a URL +%f format of the output file +%o output file name in full +%O output file name as a URL +%d output dir in full +%D output dir as a URL. +%x extra options as set in `org-odt-convert-capabilities'." + :group 'org-export-odt + :version "24.1" + :type + '(choice + (const :tag "None" nil) + (alist :tag "Converters" + :key-type (string :tag "Converter Name") + :value-type (group (string :tag "Command line"))))) + +(defcustom org-odt-convert-process "LibreOffice" + "Use this converter to convert from \"odt\" format to other formats. +During customization, the list of converter names are populated +from `org-odt-convert-processes'." + :group 'org-export-odt + :version "24.1" + :type '(choice :convert-widget + (lambda (w) + (apply 'widget-convert (widget-type w) + (eval (car (widget-get w :args))))) + `((const :tag "None" nil) + ,@(mapcar (lambda (c) + `(const :tag ,(car c) ,(car c))) + org-odt-convert-processes)))) + +(defcustom org-odt-convert-capabilities + '(("Text" + ("odt" "ott" "doc" "rtf" "docx") + (("pdf" "pdf") ("odt" "odt") ("rtf" "rtf") ("ott" "ott") + ("doc" "doc" ":\"MS Word 97\"") ("docx" "docx") ("html" "html"))) + ("Web" + ("html") + (("pdf" "pdf") ("odt" "odt") ("html" "html"))) + ("Spreadsheet" + ("ods" "ots" "xls" "csv" "xlsx") + (("pdf" "pdf") ("ots" "ots") ("html" "html") ("csv" "csv") ("ods" "ods") + ("xls" "xls") ("xlsx" "xlsx"))) + ("Presentation" + ("odp" "otp" "ppt" "pptx") + (("pdf" "pdf") ("swf" "swf") ("odp" "odp") ("otp" "otp") ("ppt" "ppt") + ("pptx" "pptx") ("odg" "odg")))) + "Specify input and output formats of `org-odt-convert-process'. +More correctly, specify the set of input and output formats that +the user is actually interested in. + +This variable is an alist where each element is of the +form (DOCUMENT-CLASS INPUT-FMT-LIST OUTPUT-FMT-ALIST). +INPUT-FMT-LIST is a list of INPUT-FMTs. OUTPUT-FMT-ALIST is an +alist where each element is of the form (OUTPUT-FMT +OUTPUT-FILE-EXTENSION EXTRA-OPTIONS). + +The variable is interpreted as follows: +`org-odt-convert-process' can take any document that is in +INPUT-FMT-LIST and produce any document that is in the +OUTPUT-FMT-LIST. A document converted to OUTPUT-FMT will have +OUTPUT-FILE-EXTENSION as the file name extension. OUTPUT-FMT +serves dual purposes: +- It is used for populating completion candidates during + `org-odt-convert' commands. +- It is used as the value of \"%f\" specifier in + `org-odt-convert-process'. + +EXTRA-OPTIONS is used as the value of \"%x\" specifier in +`org-odt-convert-process'. + +DOCUMENT-CLASS is used to group a set of file formats in +INPUT-FMT-LIST in to a single class. + +Note that this variable inherently captures how LibreOffice based +converters work. LibreOffice maps documents of various formats +to classes like Text, Web, Spreadsheet, Presentation etc and +allow document of a given class (irrespective of it's source +format) to be converted to any of the export formats associated +with that class. + +See default setting of this variable for an typical +configuration." + :group 'org-export-odt + :version "24.1" + :type + '(choice + (const :tag "None" nil) + (alist :tag "Capabilities" + :key-type (string :tag "Document Class") + :value-type + (group (repeat :tag "Input formats" (string :tag "Input format")) + (alist :tag "Output formats" + :key-type (string :tag "Output format") + :value-type + (group (string :tag "Output file extension") + (choice + (const :tag "None" nil) + (string :tag "Extra options")))))))) + +(defcustom org-odt-preferred-output-format nil + "Automatically post-process to this format after exporting to \"odt\". +Command `org-odt-export-to-odt' exports first to \"odt\" format +and then uses `org-odt-convert-process' to convert the +resulting document to this format. During customization of this +variable, the list of valid values are populated based on +`org-odt-convert-capabilities'. + +You can set this option on per-file basis using file local +values. See Info node `(emacs) File Variables'." + :group 'org-export-odt + :version "24.1" + :type '(choice :convert-widget + (lambda (w) + (apply 'widget-convert (widget-type w) + (eval (car (widget-get w :args))))) + `((const :tag "None" nil) + ,@(mapcar (lambda (c) + `(const :tag ,c ,c)) + (org-odt-reachable-formats "odt"))))) +;;;###autoload +(put 'org-odt-preferred-output-format 'safe-local-variable 'stringp) + + +;;;; Drawers + +(defcustom org-odt-format-drawer-function nil + "Function called to format a drawer in ODT code. + +The function must accept two parameters: + NAME the drawer name, like \"LOGBOOK\" + CONTENTS the contents of the drawer. + +The function should return the string to be exported. + +For example, the variable could be set to the following function +in order to mimic default behaviour: + +\(defun org-odt-format-drawer-default \(name contents\) + \"Format a drawer element for ODT export.\" + contents\)" + :group 'org-export-odt + :version "24.4" + :package-version '(Org . "8.0") + :type 'function) + + +;;;; Headline + +(defcustom org-odt-format-headline-function nil + "Function to format headline text. + +This function will be called with 5 arguments: +TODO the todo keyword \(string or nil\). +TODO-TYPE the type of todo \(symbol: `todo', `done', nil\) +PRIORITY the priority of the headline \(integer or nil\) +TEXT the main headline text \(string\). +TAGS the tags string, separated with colons \(string or nil\). + +The function result will be used as headline text." + :group 'org-export-odt + :version "24.4" + :package-version '(Org . "8.0") + :type 'function) + + +;;;; Inlinetasks + +(defcustom org-odt-format-inlinetask-function nil + "Function called to format an inlinetask in ODT code. + +The function must accept six parameters: + TODO the todo keyword, as a string + TODO-TYPE the todo type, a symbol among `todo', `done' and nil. + PRIORITY the inlinetask priority, as a string + NAME the inlinetask name, as a string. + TAGS the inlinetask tags, as a string. + CONTENTS the contents of the inlinetask, as a string. + +The function should return the string to be exported." + :group 'org-export-odt + :version "24.4" + :package-version '(Org . "8.0") + :type 'function) + + +;;;; LaTeX + +(defcustom org-odt-with-latex org-export-with-latex + "Non-nil means process LaTeX math snippets. + +When set, the exporter will process LaTeX environments and +fragments. + +This option can also be set with the +OPTIONS line, +e.g. \"tex:mathjax\". Allowed values are: + +nil Ignore math snippets. +`verbatim' Keep everything in verbatim +`dvipng' Process the LaTeX fragments to images. This will also + include processing of non-math environments. +`imagemagick' Convert the LaTeX fragments to pdf files and use + imagemagick to convert pdf files to png files. +`mathjax' Do MathJax preprocessing and arrange for MathJax.js to + be loaded. +t Synonym for `mathjax'." + :group 'org-export-odt + :version "24.4" + :package-version '(Org . "8.0") + :type '(choice + (const :tag "Do not process math in any way" nil) + (const :tag "Use dvipng to make images" dvipng) + (const :tag "Use imagemagick to make images" imagemagick) + (const :tag "Use MathJax to display math" mathjax) + (const :tag "Leave math verbatim" verbatim))) + + +;;;; Links + +(defcustom org-odt-inline-formula-rules + '(("file" . "\\.\\(mathml\\|mml\\|odf\\)\\'")) + "Rules characterizing formula files that can be inlined into ODT. + +A rule consists in an association whose key is the type of link +to consider, and value is a regexp that will be matched against +link's path." + :group 'org-export-odt + :type '(alist :key-type (string :tag "Type") + :value-type (regexp :tag "Path"))) + +(defcustom org-odt-inline-image-rules + '(("file" . "\\.\\(jpeg\\|jpg\\|png\\|gif\\)\\'")) + "Rules characterizing image files that can be inlined into ODT. + +A rule consists in an association whose key is the type of link +to consider, and value is a regexp that will be matched against +link's path." + :group 'org-export-odt + :type '(alist :key-type (string :tag "Type") + :value-type (regexp :tag "Path"))) + +(defcustom org-odt-pixels-per-inch 96.0 + "Scaling factor for converting images pixels to inches. +Use this for sizing of embedded images. See Info node `(org) +Images in ODT export' for more information." + :type 'float + :group 'org-export-odt + :version "24.4" + :package-version '(Org . "8.1")) + + +;;;; Src Block + +(defcustom org-odt-create-custom-styles-for-srcblocks t + "Whether custom styles for colorized source blocks be automatically created. +When this option is turned on, the exporter creates custom styles +for source blocks based on the advice of `htmlfontify'. Creation +of custom styles happen as part of `org-odt-hfy-face-to-css'. + +When this option is turned off exporter does not create such +styles. + +Use the latter option if you do not want the custom styles to be +based on your current display settings. It is necessary that the +styles.xml already contains needed styles for colorizing to work. + +This variable is effective only if +`org-odt-fontify-srcblocks' is turned on." + :group 'org-export-odt + :version "24.1" + :type 'boolean) + +(defcustom org-odt-fontify-srcblocks t + "Specify whether or not source blocks need to be fontified. +Turn this option on if you want to colorize the source code +blocks in the exported file. For colorization to work, you need +to make available an enhanced version of `htmlfontify' library." + :type 'boolean + :group 'org-export-odt + :version "24.1") + + +;;;; Table + +(defcustom org-odt-table-styles + '(("OrgEquation" "OrgEquation" + ((use-first-column-styles . t) + (use-last-column-styles . t))) + ("TableWithHeaderRowAndColumn" "Custom" + ((use-first-row-styles . t) + (use-first-column-styles . t))) + ("TableWithFirstRowandLastRow" "Custom" + ((use-first-row-styles . t) + (use-last-row-styles . t))) + ("GriddedTable" "Custom" nil)) + "Specify how Table Styles should be derived from a Table Template. +This is a list where each element is of the +form (TABLE-STYLE-NAME TABLE-TEMPLATE-NAME TABLE-CELL-OPTIONS). + +TABLE-STYLE-NAME is the style associated with the table through +\"#+ATTR_ODT: :style TABLE-STYLE-NAME\" line. + +TABLE-TEMPLATE-NAME is a set of - upto 9 - automatic +TABLE-CELL-STYLE-NAMEs and PARAGRAPH-STYLE-NAMEs (as defined +below) that is included in +`org-odt-content-template-file'. + +TABLE-CELL-STYLE-NAME := TABLE-TEMPLATE-NAME + TABLE-CELL-TYPE + + \"TableCell\" +PARAGRAPH-STYLE-NAME := TABLE-TEMPLATE-NAME + TABLE-CELL-TYPE + + \"TableParagraph\" +TABLE-CELL-TYPE := \"FirstRow\" | \"LastColumn\" | + \"FirstRow\" | \"LastRow\" | + \"EvenRow\" | \"OddRow\" | + \"EvenColumn\" | \"OddColumn\" | \"\" +where \"+\" above denotes string concatenation. + +TABLE-CELL-OPTIONS is an alist where each element is of the +form (TABLE-CELL-STYLE-SELECTOR . ON-OR-OFF). +TABLE-CELL-STYLE-SELECTOR := `use-first-row-styles' | + `use-last-row-styles' | + `use-first-column-styles' | + `use-last-column-styles' | + `use-banding-rows-styles' | + `use-banding-columns-styles' | + `use-first-row-styles' +ON-OR-OFF := `t' | `nil' + +For example, with the following configuration + +\(setq org-odt-table-styles + '\(\(\"TableWithHeaderRowsAndColumns\" \"Custom\" + \(\(use-first-row-styles . t\) + \(use-first-column-styles . t\)\)\) + \(\"TableWithHeaderColumns\" \"Custom\" + \(\(use-first-column-styles . t\)\)\)\)\) + +1. A table associated with \"TableWithHeaderRowsAndColumns\" + style will use the following table-cell styles - + \"CustomFirstRowTableCell\", \"CustomFirstColumnTableCell\", + \"CustomTableCell\" and the following paragraph styles + \"CustomFirstRowTableParagraph\", + \"CustomFirstColumnTableParagraph\", \"CustomTableParagraph\" + as appropriate. + +2. A table associated with \"TableWithHeaderColumns\" style will + use the following table-cell styles - + \"CustomFirstColumnTableCell\", \"CustomTableCell\" and the + following paragraph styles + \"CustomFirstColumnTableParagraph\", \"CustomTableParagraph\" + as appropriate.. + +Note that TABLE-TEMPLATE-NAME corresponds to the +\"\" elements contained within +\"\". The entries (TABLE-STYLE-NAME +TABLE-TEMPLATE-NAME TABLE-CELL-OPTIONS) correspond to +\"table:template-name\" and \"table:use-first-row-styles\" etc +attributes of \"\" element. Refer ODF-1.2 +specification for more information. Also consult the +implementation filed under `org-odt-get-table-cell-styles'. + +The TABLE-STYLE-NAME \"OrgEquation\" is used internally for +formatting of numbered display equations. Do not delete this +style from the list." + :group 'org-export-odt + :version "24.1" + :type '(choice + (const :tag "None" nil) + (repeat :tag "Table Styles" + (list :tag "Table Style Specification" + (string :tag "Table Style Name") + (string :tag "Table Template Name") + (alist :options (use-first-row-styles + use-last-row-styles + use-first-column-styles + use-last-column-styles + use-banding-rows-styles + use-banding-columns-styles) + :key-type symbol + :value-type (const :tag "True" t)))))) + +;;;; Timestamps + +(defcustom org-odt-use-date-fields nil + "Non-nil, if timestamps should be exported as date fields. + +When nil, export timestamps as plain text. + +When non-nil, map `org-time-stamp-custom-formats' to a pair of +OpenDocument date-styles with names \"OrgDate1\" and \"OrgDate2\" +respectively. A timestamp with no time component is formatted +with style \"OrgDate1\" while one with explicit hour and minutes +is formatted with style \"OrgDate2\". + +This feature is experimental. Most (but not all) of the common +%-specifiers in `format-time-string' are supported. +Specifically, locale-dependent specifiers like \"%c\", \"%x\" are +formatted as canonical Org timestamps. For finer control, avoid +these %-specifiers. + +Textutal specifiers like \"%b\", \"%h\", \"%B\", \"%a\", \"%A\" +etc., are displayed by the application in the default language +and country specified in `org-odt-styles-file'. Note that the +default styles file uses language \"en\" and country \"GB\". You +can localize the week day and month strings in the exported +document by setting the default language and country either using +the application UI or through a custom styles file. + +See `org-odt--build-date-styles' for implementation details." + :group 'org-export-odt + :type 'boolean) + + + +;;; Internal functions + +;;;; Date + +(defun org-odt--format-timestamp (timestamp &optional end iso-date-p) + (let* ((format-timestamp + (lambda (timestamp format &optional end utc) + (if timestamp + (org-timestamp-format timestamp format end utc) + (format-time-string format nil utc)))) + (has-time-p (or (not timestamp) + (org-timestamp-has-time-p timestamp))) + (iso-date (let ((format (if has-time-p "%Y-%m-%dT%H:%M:%S" + "%Y-%m-%dT%H:%M:%S"))) + (funcall format-timestamp timestamp format end)))) + (if iso-date-p iso-date + (let* ((style (if has-time-p "OrgDate2" "OrgDate1")) + ;; LibreOffice does not care about end goes as content + ;; within the "..." field. The + ;; displayed date is automagically corrected to match the + ;; format requested by "style:data-style-name" attribute. So + ;; don't bother about formatting the date contents to be + ;; compatible with "OrgDate1" and "OrgDateTime" styles. A + ;; simple Org-style date should suffice. + (date (let* ((formats + (if org-display-custom-times + (cons (substring + (car org-time-stamp-custom-formats) 1 -1) + (substring + (cdr org-time-stamp-custom-formats) 1 -1)) + '("%Y-%m-%d %a" . "%Y-%m-%d %a %H:%M"))) + (format (if has-time-p (cdr formats) (car formats)))) + (funcall format-timestamp timestamp format end))) + (repeater (let ((repeater-type (org-element-property + :repeater-type timestamp)) + (repeater-value (org-element-property + :repeater-value timestamp)) + (repeater-unit (org-element-property + :repeater-unit timestamp))) + (concat + (case repeater-type + (catchup "++") (restart ".+") (cumulate "+")) + (when repeater-value + (number-to-string repeater-value)) + (case repeater-unit + (hour "h") (day "d") (week "w") (month "m") + (year "y")))))) + (concat + (format "%s" + iso-date style date) + (and (not (string= repeater "")) " ") + repeater))))) + +;;;; Frame + +(defun org-odt--frame (text width height style &optional extra + anchor-type &rest title-and-desc) + (let ((frame-attrs + (concat + (if width (format " svg:width=\"%0.2fcm\"" width) "") + (if height (format " svg:height=\"%0.2fcm\"" height) "") + extra + (format " text:anchor-type=\"%s\"" (or anchor-type "paragraph"))))) + (format + "\n\n%s\n" + style frame-attrs + (concat text + (let ((title (car title-and-desc)) + (desc (cadr title-and-desc))) + (concat (when title + (format "%s" + (org-odt--encode-plain-text title t))) + (when desc + (format "%s" + (org-odt--encode-plain-text desc t))))))))) + + +;;;; Library wrappers + +(defun org-odt--zip-extract (archive members target) + (when (atom members) (setq members (list members))) + (mapc (lambda (member) + (require 'arc-mode) + (let* ((--quote-file-name + ;; This is shamelessly stolen from `archive-zip-extract'. + (lambda (name) + (if (or (not (memq system-type '(windows-nt ms-dos))) + (and (boundp 'w32-quote-process-args) + (null w32-quote-process-args))) + (shell-quote-argument name) + name))) + (target (funcall --quote-file-name target)) + (archive (expand-file-name archive)) + (archive-zip-extract + (list "unzip" "-qq" "-o" "-d" target)) + exit-code command-output) + (setq command-output + (with-temp-buffer + (setq exit-code (archive-zip-extract archive member)) + (buffer-string))) + (unless (zerop exit-code) + (message command-output) + (error "Extraction failed")))) + members)) + +;;;; Target + +(defun org-odt--target (text id) + (if (not id) text + (concat + (format "\n" id) + (format "\n" id) text + (format "\n" id)))) + +;;;; Textbox + +(defun org-odt--textbox (text width height style &optional + extra anchor-type) + (org-odt--frame + (format "\n%s\n" + (concat (format " fo:min-height=\"%0.2fcm\"" (or height .2)) + (and (not width) + (format " fo:min-width=\"%0.2fcm\"" (or width .2)))) + text) + width nil style extra anchor-type)) + + + +;;;; Table of Contents + +(defun org-odt-begin-toc (index-title depth) + (concat + (format " + + + %s +" depth index-title) + + (let ((levels (number-sequence 1 10))) + (mapconcat + (lambda (level) + (format + " + + + + + + +" level level)) levels "")) + + (format " + + + + + %s + + " index-title))) + +(defun org-odt-end-toc () + (format " + + +")) + +(defun* org-odt-format-toc-headline + (todo todo-type priority text tags + &key level section-number headline-label &allow-other-keys) + (setq text + (concat + ;; Section number. + (when section-number (concat section-number ". ")) + ;; Todo. + (when todo + (let ((style (if (member todo org-done-keywords) + "OrgDone" "OrgTodo"))) + (format "%s " + style todo))) + (when priority + (let* ((style (format "OrgPriority-%s" priority)) + (priority (format "[#%c]" priority))) + (format "%s " + style priority))) + ;; Title. + text + ;; Tags. + (when tags + (concat + (format " [%s]" + "OrgTags" + (mapconcat + (lambda (tag) + (format + "%s" + "OrgTag" tag)) tags " : ")))))) + (format "%s" + headline-label text)) + +(defun org-odt-toc (depth info) + (assert (wholenump depth)) + ;; When a headline is marked as a radio target, as in the example below: + ;; + ;; ** <<>> + ;; Some text. + ;; + ;; suppress generation of radio targets. i.e., Radio targets are to + ;; be marked as targets within /document body/ and *not* within + ;; /TOC/, as otherwise there will be duplicated anchors one in TOC + ;; and one in the document body. + ;; + ;; FIXME-1: Currently exported headings are memoized. `org-export.el' + ;; doesn't provide a way to disable memoization. So this doesn't + ;; work. + ;; + ;; FIXME-2: Are there any other objects that need to be suppressed + ;; within TOC? + (let* ((title (org-export-translate "Table of Contents" :utf-8 info)) + (headlines (org-export-collect-headlines + info (and (wholenump depth) depth))) + (backend (org-export-create-backend + :parent (org-export-backend-name + (plist-get info :back-end)) + :transcoders (mapcar + (lambda (type) (cons type (lambda (d c i) c))) + (list 'radio-target))))) + (when headlines + (concat + (org-odt-begin-toc title depth) + (mapconcat + (lambda (headline) + (let* ((entry (org-odt-format-headline--wrap + headline backend info 'org-odt-format-toc-headline)) + (level (org-export-get-relative-level headline info)) + (style (format "Contents_20_%d" level))) + (format "\n%s" + style entry))) + headlines "\n") + (org-odt-end-toc))))) + + +;;;; Document styles + +(defun org-odt-add-automatic-style (object-type &optional object-props) + "Create an automatic style of type OBJECT-TYPE with param OBJECT-PROPS. +OBJECT-PROPS is (typically) a plist created by passing +\"#+ATTR_ODT: \" option of the object in question to +`org-odt-parse-block-attributes'. + +Use `org-odt-object-counters' to generate an automatic +OBJECT-NAME and STYLE-NAME. If OBJECT-PROPS is non-nil, add a +new entry in `org-odt-automatic-styles'. Return (OBJECT-NAME +. STYLE-NAME)." + (assert (stringp object-type)) + (let* ((object (intern object-type)) + (seqvar object) + (seqno (1+ (or (plist-get org-odt-object-counters seqvar) 0))) + (object-name (format "%s%d" object-type seqno)) style-name) + (setq org-odt-object-counters + (plist-put org-odt-object-counters seqvar seqno)) + (when object-props + (setq style-name (format "Org%s" object-name)) + (setq org-odt-automatic-styles + (plist-put org-odt-automatic-styles object + (append (list (list style-name object-props)) + (plist-get org-odt-automatic-styles object))))) + (cons object-name style-name))) + +;;;; Checkbox + +(defun org-odt--checkbox (item) + "Return check-box string associated to ITEM." + (let ((checkbox (org-element-property :checkbox item))) + (if (not checkbox) "" + (format "%s" + "OrgCode" (case checkbox + (on "[✓] ") ; CHECK MARK + (off "[ ] ") + (trans "[-] ")))))) + +;;; Template + +(defun org-odt--build-date-styles (fmt style) + ;; In LibreOffice 3.4.6, there doesn't seem to be a convenient way + ;; to modify the date fields. A date could be modified by + ;; offsetting in days. That's about it. Also, date and time may + ;; have to be emitted as two fields - a date field and a time field + ;; - separately. + + ;; One can add Form Controls to date and time fields so that they + ;; can be easily modified. But then, the exported document will + ;; become tightly coupled with LibreOffice and may not function + ;; properly with other OpenDocument applications. + + ;; I have a strange feeling that Date styles are a bit flaky at the + ;; moment. + + ;; The feature is experimental. + (when (and fmt style) + (let* ((fmt-alist + '(("%A" . "") + ("%B" . "") + ("%H" . "") + ("%M" . "") + ("%S" . "") + ("%V" . "") + ("%Y" . "") + ("%a" . "") + ("%b" . "") + ("%d" . "") + ("%e" . "") + ("%h" . "") + ("%k" . "") + ("%m" . "") + ("%p" . "") + ("%y" . ""))) + (case-fold-search nil) + (re (mapconcat 'identity (mapcar 'car fmt-alist) "\\|")) + match rpl (start 0) (filler-beg 0) filler-end filler output) + (mapc + (lambda (pair) + (setq fmt (replace-regexp-in-string (car pair) (cdr pair) fmt t t))) + '(("\\(?:%[[:digit:]]*N\\)" . "") ; strip ns, us and ns + ("%C" . "Y") ; replace century with year + ("%D" . "%m/%d/%y") + ("%G" . "Y") ; year corresponding to iso week + ("%I" . "%H") ; hour on a 12-hour clock + ("%R" . "%H:%M") + ("%T" . "%H:%M:%S") + ("%U\\|%W" . "%V") ; week no. starting on Sun./Mon. + ("%Z" . "") ; time zone name + ("%c" . "%Y-%M-%d %a %H:%M" ) ; locale's date and time format + ("%g" . "%y") + ("%X" . "%x" ) ; locale's pref. time format + ("%j" . "") ; day of the year + ("%l" . "%k") ; like %I blank-padded + ("%s" . "") ; no. of secs since 1970-01-01 00:00:00 +0000 + ("%n" . "") + ("%r" . "%I:%M:%S %p") + ("%t" . "") + ("%u\\|%w" . "") ; numeric day of week - Mon (1-7), Sun(0-6) + ("%x" . "%Y-%M-%d %a") ; locale's pref. time format + ("%z" . "") ; time zone in numeric form + )) + (while (string-match re fmt start) + (setq match (match-string 0 fmt)) + (setq rpl (assoc-default match fmt-alist)) + (setq start (match-end 0)) + (setq filler-end (match-beginning 0)) + (setq filler (substring fmt (prog1 filler-beg + (setq filler-beg (match-end 0))) + filler-end)) + (setq filler (and (not (string= filler "")) + (format "%s" + (org-odt--encode-plain-text filler)))) + (setq output (concat output "\n" filler "\n" rpl))) + (setq filler (substring fmt filler-beg)) + (unless (string= filler "") + (setq output (concat output + (format "\n%s" + (org-odt--encode-plain-text filler))))) + (format "\n%s\n" + style + (concat " number:automatic-order=\"true\"" + " number:format-source=\"fixed\"") + output )))) + +(defun org-odt-template (contents info) + "Return complete document string after ODT conversion. +CONTENTS is the transcoded contents string. RAW-DATA is the +original parsed data. INFO is a plist holding export options." + ;; Write meta file. + (let ((title (org-export-data (plist-get info :title) info)) + (author (let ((author (plist-get info :author))) + (if (not author) "" (org-export-data author info)))) + (email (plist-get info :email)) + (keywords (plist-get info :keywords)) + (description (plist-get info :description))) + (write-region + (concat + " + + \n" + (format "%s\n" author) + (format "%s\n" author) + ;; Date, if required. + (when (plist-get info :with-date) + ;; Check if DATE is specified as an Org-timestamp. If yes, + ;; include it as meta information. Otherwise, just use + ;; today's date. + (let* ((date (let ((date (plist-get info :date))) + (and (not (cdr date)) + (eq (org-element-type (car date)) 'timestamp) + (car date))))) + (let ((iso-date (org-odt--format-timestamp date nil 'iso-date))) + (concat + (format "%s\n" iso-date) + (format "%s\n" + iso-date))))) + (format "%s\n" + (let ((creator-info (plist-get info :with-creator))) + (if (or (not creator-info) (eq creator-info 'comment)) "" + (plist-get info :creator)))) + (format "%s\n" keywords) + (format "%s\n" description) + (format "%s\n" title) + "\n" + " \n" "") + nil (concat org-odt-zip-dir "meta.xml")) + ;; Add meta.xml in to manifest. + (org-odt-create-manifest-file-entry "text/xml" "meta.xml")) + + ;; Update styles file. + ;; Copy styles.xml. Also dump htmlfontify styles, if there is any. + ;; Write styles file. + (let* ((styles-file (plist-get info :odt-styles-file)) + (styles-file (and styles-file (read (org-trim styles-file)))) + ;; Non-availability of styles.xml is not a critical + ;; error. For now, throw an error. + (styles-file (or styles-file + org-odt-styles-file + (expand-file-name "OrgOdtStyles.xml" + org-odt-styles-dir) + (error "org-odt: Missing styles file?")))) + (cond + ((listp styles-file) + (let ((archive (nth 0 styles-file)) + (members (nth 1 styles-file))) + (org-odt--zip-extract archive members org-odt-zip-dir) + (mapc + (lambda (member) + (when (org-file-image-p member) + (let* ((image-type (file-name-extension member)) + (media-type (format "image/%s" image-type))) + (org-odt-create-manifest-file-entry media-type member)))) + members))) + ((and (stringp styles-file) (file-exists-p styles-file)) + (let ((styles-file-type (file-name-extension styles-file))) + (cond + ((string= styles-file-type "xml") + (copy-file styles-file (concat org-odt-zip-dir "styles.xml") t)) + ((member styles-file-type '("odt" "ott")) + (org-odt--zip-extract styles-file "styles.xml" org-odt-zip-dir))))) + (t + (error (format "Invalid specification of styles.xml file: %S" + org-odt-styles-file)))) + + ;; create a manifest entry for styles.xml + (org-odt-create-manifest-file-entry "text/xml" "styles.xml") + + ;; FIXME: Who is opening an empty styles.xml before this point? + (with-current-buffer + (find-file-noselect (concat org-odt-zip-dir "styles.xml") t) + (revert-buffer t t) + + ;; Write custom styles for source blocks + ;; Save STYLES used for colorizing of source blocks. + ;; Update styles.xml with styles that were collected as part of + ;; `org-odt-hfy-face-to-css' callbacks. + (let ((styles (mapconcat (lambda (style) (format " %s\n" (cddr style))) + hfy-user-sheet-assoc ""))) + (when styles + (goto-char (point-min)) + (when (re-search-forward "" nil t) + (goto-char (match-beginning 0)) + (insert "\n\n" styles "\n")))) + + ;; Update styles.xml - take care of outline numbering + + ;; Don't make automatic backup of styles.xml file. This setting + ;; prevents the backed-up styles.xml file from being zipped in to + ;; odt file. This is more of a hackish fix. Better alternative + ;; would be to fix the zip command so that the output odt file + ;; includes only the needed files and excludes any auto-generated + ;; extra files like backups and auto-saves etc etc. Note that + ;; currently the zip command zips up the entire temp directory so + ;; that any auto-generated files created under the hood ends up in + ;; the resulting odt file. + (set (make-local-variable 'backup-inhibited) t) + + ;; Outline numbering is retained only upto LEVEL. + ;; To disable outline numbering pass a LEVEL of 0. + + (goto-char (point-min)) + (let ((regex + "]*\\)text:level=\"\\([^\"]*\\)\"\\([^>]*\\)>") + (replacement + "")) + (while (re-search-forward regex nil t) + (unless (let ((sec-num (plist-get info :section-numbers)) + (level (string-to-number (match-string 2)))) + (if (wholenump sec-num) (<= level sec-num) sec-num)) + (replace-match replacement t nil)))) + (save-buffer 0))) + ;; Update content.xml. + + (let* ( ;; `org-display-custom-times' should be accessed right + ;; within the context of the Org buffer. So obtain it's + ;; value before moving on to temp-buffer context down below. + (custom-time-fmts + (if org-display-custom-times + (cons (substring (car org-time-stamp-custom-formats) 1 -1) + (substring (cdr org-time-stamp-custom-formats) 1 -1)) + '("%Y-%M-%d %a" . "%Y-%M-%d %a %H:%M")))) + (with-temp-buffer + (insert-file-contents + (or org-odt-content-template-file + (expand-file-name "OrgOdtContentTemplate.xml" + org-odt-styles-dir))) + ;; Write automatic styles. + ;; - Position the cursor. + (goto-char (point-min)) + (re-search-forward " " nil t) + (goto-char (match-beginning 0)) + ;; - Dump automatic table styles. + (loop for (style-name props) in + (plist-get org-odt-automatic-styles 'Table) do + (when (setq props (or (plist-get props :rel-width) "96")) + (insert (format org-odt-table-style-format style-name props)))) + ;; - Dump date-styles. + (when org-odt-use-date-fields + (insert (org-odt--build-date-styles (car custom-time-fmts) + "OrgDate1") + (org-odt--build-date-styles (cdr custom-time-fmts) + "OrgDate2"))) + ;; Update display level. + ;; - Remove existing sequence decls. Also position the cursor. + (goto-char (point-min)) + (when (re-search-forward "" nil nil))) + ;; Update sequence decls according to user preference. + (insert + (format + "\n\n%s\n" + (mapconcat + (lambda (x) + (format + "" + org-odt-display-outline-level (nth 1 x))) + org-odt-category-map-alist "\n"))) + ;; Position the cursor to document body. + (goto-char (point-min)) + (re-search-forward "" nil nil) + (goto-char (match-beginning 0)) + + ;; Preamble - Title, Author, Date etc. + (insert + (let* ((title (org-export-data (plist-get info :title) info)) + (author (and (plist-get info :with-author) + (let ((auth (plist-get info :author))) + (and auth (org-export-data auth info))))) + (email (plist-get info :email)) + ;; Switch on or off above vars based on user settings + (author (and (plist-get info :with-author) (or author email))) + (email (and (plist-get info :with-email) email))) + (concat + ;; Title. + (when title + (concat + (format "\n%s" + "OrgTitle" (format "\n%s" title)) + ;; Separator. + "\n")) + (cond + ((and author (not email)) + ;; Author only. + (concat + (format "\n%s" + "OrgSubtitle" + (format "%s" author)) + ;; Separator. + "\n")) + ((and author email) + ;; Author and E-mail. + (concat + (format + "\n%s" + "OrgSubtitle" + (format + "%s" + (concat "mailto:" email) + (format "%s" author))) + ;; Separator. + "\n"))) + ;; Date, if required. + (when (plist-get info :with-date) + (let* ((date (plist-get info :date)) + ;; Check if DATE is specified as a timestamp. + (timestamp (and (not (cdr date)) + (eq (org-element-type (car date)) 'timestamp) + (car date)))) + (concat + (format "\n%s" + "OrgSubtitle" + (if (and org-odt-use-date-fields timestamp) + (org-odt--format-timestamp (car date)) + (org-export-data (plist-get info :date) info))) + ;; Separator + "")))))) + ;; Table of Contents + (let* ((with-toc (plist-get info :with-toc)) + (depth (and with-toc (if (wholenump with-toc) + with-toc + (plist-get info :headline-levels))))) + (when depth (insert (or (org-odt-toc depth info) "")))) + ;; Contents. + (insert contents) + ;; Return contents. + (buffer-substring-no-properties (point-min) (point-max))))) + + + +;;; Transcode Functions + +;;;; Bold + +(defun org-odt-bold (bold contents info) + "Transcode BOLD from Org to ODT. +CONTENTS is the text with bold markup. INFO is a plist holding +contextual information." + (format "%s" + "Bold" contents)) + + +;;;; Center Block + +(defun org-odt-center-block (center-block contents info) + "Transcode a CENTER-BLOCK element from Org to ODT. +CONTENTS holds the contents of the center block. INFO is a plist +holding contextual information." + contents) + + +;;;; Clock + +(defun org-odt-clock (clock contents info) + "Transcode a CLOCK element from Org to ODT. +CONTENTS is nil. INFO is a plist used as a communication +channel." + (let ((timestamp (org-element-property :value clock)) + (duration (org-element-property :duration clock))) + (format "\n%s" + (if (eq (org-element-type (org-export-get-next-element clock info)) + 'clock) "OrgClock" "OrgClockLastLine") + (concat + (format "%s" + "OrgClockKeyword" org-clock-string) + (org-odt-timestamp timestamp contents info) + (and duration (format " (%s)" duration)))))) + + +;;;; Code + +(defun org-odt-code (code contents info) + "Transcode a CODE object from Org to ODT. +CONTENTS is nil. INFO is a plist used as a communication +channel." + (format "%s" + "OrgCode" (org-odt--encode-plain-text + (org-element-property :value code)))) + + +;;;; Comment + +;; Comments are ignored. + + +;;;; Comment Block + +;; Comment Blocks are ignored. + + +;;;; Drawer + +(defun org-odt-drawer (drawer contents info) + "Transcode a DRAWER element from Org to ODT. +CONTENTS holds the contents of the block. INFO is a plist +holding contextual information." + (let* ((name (org-element-property :drawer-name drawer)) + (output (if (functionp org-odt-format-drawer-function) + (funcall org-odt-format-drawer-function + name contents) + ;; If there's no user defined function: simply + ;; display contents of the drawer. + contents))) + output)) + + +;;;; Dynamic Block + +(defun org-odt-dynamic-block (dynamic-block contents info) + "Transcode a DYNAMIC-BLOCK element from Org to ODT. +CONTENTS holds the contents of the block. INFO is a plist +holding contextual information. See `org-export-data'." + contents) + + +;;;; Entity + +(defun org-odt-entity (entity contents info) + "Transcode an ENTITY object from Org to ODT. +CONTENTS are the definition itself. INFO is a plist holding +contextual information." + (org-element-property :utf-8 entity)) + + +;;;; Example Block + +(defun org-odt-example-block (example-block contents info) + "Transcode a EXAMPLE-BLOCK element from Org to ODT. +CONTENTS is nil. INFO is a plist holding contextual information." + (org-odt-format-code example-block info)) + + +;;;; Export Snippet + +(defun org-odt-export-snippet (export-snippet contents info) + "Transcode a EXPORT-SNIPPET object from Org to ODT. +CONTENTS is nil. INFO is a plist holding contextual information." + (when (eq (org-export-snippet-backend export-snippet) 'odt) + (org-element-property :value export-snippet))) + + +;;;; Export Block + +(defun org-odt-export-block (export-block contents info) + "Transcode a EXPORT-BLOCK element from Org to ODT. +CONTENTS is nil. INFO is a plist holding contextual information." + (when (string= (org-element-property :type export-block) "ODT") + (org-remove-indentation (org-element-property :value export-block)))) + + +;;;; Fixed Width + +(defun org-odt-fixed-width (fixed-width contents info) + "Transcode a FIXED-WIDTH element from Org to ODT. +CONTENTS is nil. INFO is a plist holding contextual information." + (org-odt-do-format-code (org-element-property :value fixed-width))) + + +;;;; Footnote Definition + +;; Footnote Definitions are ignored. + + +;;;; Footnote Reference + +(defun org-odt-footnote-reference (footnote-reference contents info) + "Transcode a FOOTNOTE-REFERENCE element from Org to ODT. +CONTENTS is nil. INFO is a plist holding contextual information." + (let ((--format-footnote-definition + (function + (lambda (n def) + (setq n (format "%d" n)) + (let ((id (concat "fn" n)) + (note-class "footnote") + (par-style "Footnote")) + (format + "%s" + id note-class + (concat + (format "%s" n) + (format "%s" def))))))) + (--format-footnote-reference + (function + (lambda (n) + (setq n (format "%d" n)) + (let ((note-class "footnote") + (ref-format "text") + (ref-name (concat "fn" n))) + (format + "%s" + "OrgSuperscript" + (format "%s" + note-class ref-format ref-name n))))))) + (concat + ;; Insert separator between two footnotes in a row. + (let ((prev (org-export-get-previous-element footnote-reference info))) + (and (eq (org-element-type prev) 'footnote-reference) + (format "%s" + "OrgSuperscript" ","))) + ;; Trancode footnote reference. + (let ((n (org-export-get-footnote-number footnote-reference info))) + (cond + ((not (org-export-footnote-first-reference-p footnote-reference info)) + (funcall --format-footnote-reference n)) + ;; Inline definitions are secondary strings. + ;; Non-inline footnotes definitions are full Org data. + (t + (let* ((raw (org-export-get-footnote-definition + footnote-reference info)) + (def + (let ((def (org-trim + (org-export-data-with-backend + raw + (org-export-create-backend + :parent 'odt + :transcoders + '((paragraph . (lambda (p c i) + (org-odt--format-paragraph + p c "Footnote" + "OrgFootnoteCenter" + "OrgFootnoteQuotations"))))) + info)))) + (if (eq (org-element-type raw) 'org-data) def + (format "\n%s" + "Footnote" def))))) + (funcall --format-footnote-definition n def)))))))) + + +;;;; Headline + +(defun* org-odt-format-headline + (todo todo-type priority text tags + &key level section-number headline-label &allow-other-keys) + (concat + ;; Todo. + (when todo + (let ((style (if (member todo org-done-keywords) "OrgDone" "OrgTodo"))) + (format "%s " + style todo))) + (when priority + (let* ((style (format "OrgPriority-%s" priority)) + (priority (format "[#%c]" priority))) + (format "%s " + style priority))) + ;; Title. + text + ;; Tags. + (when tags + (concat + "" + (format "[%s]" + "OrgTags" (mapconcat + (lambda (tag) + (format + "%s" + "OrgTag" tag)) tags " : ")))))) + +(defun org-odt-format-headline--wrap (headline backend info + &optional format-function + &rest extra-keys) + "Transcode a HEADLINE element using BACKEND. +INFO is a plist holding contextual information." + (setq backend (or backend (plist-get info :back-end))) + (let* ((level (+ (org-export-get-relative-level headline info))) + (headline-number (org-export-get-headline-number headline info)) + (section-number (and (org-export-numbered-headline-p headline info) + (mapconcat 'number-to-string + headline-number "."))) + (todo (and (plist-get info :with-todo-keywords) + (let ((todo (org-element-property :todo-keyword headline))) + (and todo + (org-export-data-with-backend todo backend info))))) + (todo-type (and todo (org-element-property :todo-type headline))) + (priority (and (plist-get info :with-priority) + (org-element-property :priority headline))) + (text (org-export-data-with-backend + (org-element-property :title headline) backend info)) + (tags (and (plist-get info :with-tags) + (org-export-get-tags headline info))) + (headline-label (concat "sec-" (mapconcat 'number-to-string + headline-number "-"))) + (format-function (cond + ((functionp format-function) format-function) + ((functionp org-odt-format-headline-function) + (function* + (lambda (todo todo-type priority text tags + &allow-other-keys) + (funcall org-odt-format-headline-function + todo todo-type priority text tags)))) + (t 'org-odt-format-headline)))) + (apply format-function + todo todo-type priority text tags + :headline-label headline-label :level level + :section-number section-number extra-keys))) + +(defun org-odt-headline (headline contents info) + "Transcode a HEADLINE element from Org to ODT. +CONTENTS holds the contents of the headline. INFO is a plist +holding contextual information." + ;; Case 1: This is a footnote section: ignore it. + (unless (org-element-property :footnote-section-p headline) + (let* ((text (org-export-data (org-element-property :title headline) info)) + ;; Create the headline text. + (full-text (org-odt-format-headline--wrap headline nil info)) + ;; Get level relative to current parsed data. + (level (org-export-get-relative-level headline info)) + ;; Get canonical label for the headline. + (id (concat "sec-" (mapconcat 'number-to-string + (org-export-get-headline-number + headline info) "-"))) + ;; Get user-specified labels for the headline. + (extra-ids (list (org-element-property :CUSTOM_ID headline) + (org-element-property :ID headline))) + ;; Extra targets. + (extra-targets + (mapconcat (lambda (x) + (when x + (let ((x (if (org-uuidgen-p x) (concat "ID-" x) x))) + (org-odt--target + "" (org-export-solidify-link-text x))))) + extra-ids "")) + ;; Title. + (anchored-title (org-odt--target full-text id))) + (cond + ;; Case 2. This is a deep sub-tree: export it as a list item. + ;; Also export as items headlines for which no section + ;; format has been found. + ((org-export-low-level-p headline info) + ;; Build the real contents of the sub-tree. + (concat + (and (org-export-first-sibling-p headline info) + (format "\n" + ;; Choose style based on list type. + (if (org-export-numbered-headline-p headline info) + "OrgNumberedList" "OrgBulletedList") + ;; If top-level list, re-start numbering. Otherwise, + ;; continue numbering. + (format "text:continue-numbering=\"%s\"" + (let* ((parent (org-export-get-parent-headline + headline))) + (if (and parent + (org-export-low-level-p parent info)) + "true" "false"))))) + (let ((headline-has-table-p + (let ((section (assq 'section (org-element-contents headline)))) + (assq 'table (and section (org-element-contents section)))))) + (format "\n\n%s\n%s" + (concat + (format "\n%s" + "Text_20_body" + (concat extra-targets anchored-title)) + contents) + (if headline-has-table-p + "" + ""))) + (and (org-export-last-sibling-p headline info) + ""))) + ;; Case 3. Standard headline. Export it as a section. + (t + (concat + (format + "\n%s" + (format "Heading_20_%s" level) + level + (concat extra-targets anchored-title)) + contents)))))) + + +;;;; Horizontal Rule + +(defun org-odt-horizontal-rule (horizontal-rule contents info) + "Transcode an HORIZONTAL-RULE object from Org to ODT. +CONTENTS is nil. INFO is a plist holding contextual information." + (format "\n%s" + "Horizontal_20_Line" "")) + + +;;;; Inline Babel Call + +;; Inline Babel Calls are ignored. + + +;;;; Inline Src Block + +(defun org-odt--find-verb-separator (s) + "Return a character not used in string S. +This is used to choose a separator for constructs like \\verb." + (let ((ll "~,./?;':\"|!@#%^&-_=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ<>()[]{}")) + (loop for c across ll + when (not (string-match (regexp-quote (char-to-string c)) s)) + return (char-to-string c)))) + +(defun org-odt-inline-src-block (inline-src-block contents info) + "Transcode an INLINE-SRC-BLOCK element from Org to ODT. +CONTENTS holds the contents of the item. INFO is a plist holding +contextual information." + (let* ((org-lang (org-element-property :language inline-src-block)) + (code (org-element-property :value inline-src-block)) + (separator (org-odt--find-verb-separator code))) + (error "FIXME"))) + + +;;;; Inlinetask + +(defun org-odt-inlinetask (inlinetask contents info) + "Transcode an INLINETASK element from Org to ODT. +CONTENTS holds the contents of the block. INFO is a plist +holding contextual information." + (cond + ;; If `org-odt-format-inlinetask-function' is provided, call it + ;; with appropriate arguments. + ((functionp org-odt-format-inlinetask-function) + (let ((format-function + (function* + (lambda (todo todo-type priority text tags + &key contents &allow-other-keys) + (funcall org-odt-format-inlinetask-function + todo todo-type priority text tags contents))))) + (org-odt-format-headline--wrap + inlinetask nil info format-function :contents contents))) + ;; Otherwise, use a default template. + (t + (format "\n%s" + "Text_20_body" + (org-odt--textbox + (concat + (format "\n%s" + "OrgInlineTaskHeading" + (org-odt-format-headline--wrap inlinetask nil info)) + contents) + nil nil "OrgInlineTaskFrame" " style:rel-width=\"100%\""))))) + +;;;; Italic + +(defun org-odt-italic (italic contents info) + "Transcode ITALIC from Org to ODT. +CONTENTS is the text with italic markup. INFO is a plist holding +contextual information." + (format "%s" + "Emphasis" contents)) + + +;;;; Item + +(defun org-odt-item (item contents info) + "Transcode an ITEM element from Org to ODT. +CONTENTS holds the contents of the item. INFO is a plist holding +contextual information." + (let* ((plain-list (org-export-get-parent item)) + (type (org-element-property :type plain-list)) + (counter (org-element-property :counter item)) + (tag (let ((tag (org-element-property :tag item))) + (and tag + (concat (org-odt--checkbox item) + (org-export-data tag info)))))) + (case type + ((ordered unordered descriptive-1 descriptive-2) + (format "\n\n%s\n%s" + contents + (let* ((--element-has-a-table-p + (function + (lambda (element info) + (loop for el in (org-element-contents element) + thereis (eq (org-element-type el) 'table)))))) + (cond + ((funcall --element-has-a-table-p item info) + "") + (t ""))))) + (t (error "Unknown list type: %S" type))))) + +;;;; Keyword + +(defun org-odt-keyword (keyword contents info) + "Transcode a KEYWORD element from Org to ODT. +CONTENTS is nil. INFO is a plist holding contextual information." + (let ((key (org-element-property :key keyword)) + (value (org-element-property :value keyword))) + (cond + ((string= key "ODT") value) + ((string= key "INDEX") + ;; FIXME + (ignore)) + ((string= key "TOC") + (let ((value (downcase value))) + (cond + ((string-match "\\" value) + (let ((depth (or (and (string-match "[0-9]+" value) + (string-to-number (match-string 0 value))) + (plist-get info :with-toc)))) + (when (wholenump depth) (org-odt-toc depth info)))) + ((member value '("tables" "figures" "listings")) + ;; FIXME + (ignore)))))))) + + +;;;; Latex Environment + + +;; (eval-after-load 'ox-odt '(ad-deactivate 'org-format-latex-as-mathml)) +;; (defadvice org-format-latex-as-mathml ; FIXME +;; (after org-odt-protect-latex-fragment activate) +;; "Encode LaTeX fragment as XML. +;; Do this when translation to MathML fails." +;; (unless (> (length ad-return-value) 0) +;; (setq ad-return-value (org-odt--encode-plain-text (ad-get-arg 0))))) + +(defun org-odt-latex-environment (latex-environment contents info) + "Transcode a LATEX-ENVIRONMENT element from Org to ODT. +CONTENTS is nil. INFO is a plist holding contextual information." + (let* ((latex-frag (org-remove-indentation + (org-element-property :value latex-environment)))) + (org-odt-do-format-code latex-frag))) + + +;;;; Latex Fragment + +;; (when latex-frag ; FIXME +;; (setq href (org-propertize href :title "LaTeX Fragment" +;; :description latex-frag))) +;; handle verbatim +;; provide descriptions + +(defun org-odt-latex-fragment (latex-fragment contents info) + "Transcode a LATEX-FRAGMENT object from Org to ODT. +CONTENTS is nil. INFO is a plist holding contextual information." + (let* ((latex-frag (org-element-property :value latex-fragment)) + (processing-type (plist-get info :with-latex))) + (format "%s" + "OrgCode" (org-odt--encode-plain-text latex-frag t)))) + + +;;;; Line Break + +(defun org-odt-line-break (line-break contents info) + "Transcode a LINE-BREAK object from Org to ODT. +CONTENTS is nil. INFO is a plist holding contextual information." + "") + + +;;;; Link + +;;;; Links :: Label references + +(defun org-odt--enumerate (element info &optional predicate n) + (when predicate (assert (funcall predicate element info))) + (let* ((--numbered-parent-headline-at-<=-n + (function + (lambda (element n info) + (loop for x in (org-export-get-genealogy element) + thereis (and (eq (org-element-type x) 'headline) + (<= (org-export-get-relative-level x info) n) + (org-export-numbered-headline-p x info) + x))))) + (--enumerate + (function + (lambda (element scope info &optional predicate) + (let ((counter 0)) + (org-element-map (or scope (plist-get info :parse-tree)) + (org-element-type element) + (lambda (el) + (and (or (not predicate) (funcall predicate el info)) + (incf counter) + (eq element el) + counter)) + info 'first-match))))) + (scope (funcall --numbered-parent-headline-at-<=-n + element (or n org-odt-display-outline-level) info)) + (ordinal (funcall --enumerate element scope info predicate)) + (tag + (concat + ;; Section number. + (and scope + (mapconcat 'number-to-string + (org-export-get-headline-number scope info) ".")) + ;; Separator. + (and scope ".") + ;; Ordinal. + (number-to-string ordinal)))) + tag)) + +(defun org-odt-format-label (element info op) + "Return a label for ELEMENT. + +ELEMENT is a `link', `table', `src-block' or `paragraph' type +element. INFO is a plist used as a communication channel. OP is +either `definition' or `reference', depending on the purpose of +the generated string. + +Return value is a string if OP is set to `reference' or a cons +cell like CAPTION . SHORT-CAPTION) where CAPTION and +SHORT-CAPTION are strings." + (assert (memq (org-element-type element) '(link table src-block paragraph))) + (let* ((caption-from + (case (org-element-type element) + (link (org-export-get-parent-element element)) + (t element))) + ;; Get label and caption. + (label (org-element-property :name caption-from)) + (caption (org-export-get-caption caption-from)) + (short-caption (org-export-get-caption caption-from t)) + ;; Transcode captions. + (caption (and caption (org-export-data caption info))) + ;; Currently short caption are sneaked in as object names. + ;; + ;; The advantages are: + ;; + ;; - Table Of Contents: Currently, there is no support for + ;; building TOC for figures, listings and tables. See + ;; `org-odt-keyword'. User instead has to rely on + ;; external application for building such indices. Within + ;; LibreOffice, building an "Illustration Index" or "Index + ;; of Tables" will create a table with long captions (only) + ;; and building a table with "Object names" will create a + ;; table with short captions. + ;; + ;; - Easy navigation: In LibreOffice, object names are + ;; offered via the navigation bar. This way one can + ;; quickly locate and jump to object of his choice in the + ;; exported document. + ;; + ;; The main disadvantage is that there cannot be any markups + ;; within object names i.e., one cannot embolden, italicize + ;; or underline text within short caption. So suppress + ;; generation of ... and other + ;; markups by overriding the default translators. We + ;; probably shouldn't be suppressing translators for all + ;; elements in `org-element-all-objects', but for now this + ;; will do. + (short-caption + (let ((short-caption (or short-caption caption)) + (backend (org-export-create-backend + :parent (org-export-backend-name + (plist-get info :back-end)) + :transcoders + (mapcar (lambda (type) (cons type (lambda (o c i) c))) + org-element-all-objects)))) + (when short-caption + (org-export-data-with-backend short-caption backend info))))) + (when (or label caption) + (let* ((default-category + (case (org-element-type element) + (table "__Table__") + (src-block "__Listing__") + ((link paragraph) + (cond + ((org-odt--enumerable-latex-image-p element info) + "__DvipngImage__") + ((org-odt--enumerable-image-p element info) + "__Figure__") + ((org-odt--enumerable-formula-p element info) + "__MathFormula__") + (t (error "Don't know how to format label for link: %S" + element)))) + (t (error "Don't know how to format label for element type: %s" + (org-element-type element))))) + seqno) + (assert default-category) + (destructuring-bind (counter label-style category predicate) + (assoc-default default-category org-odt-category-map-alist) + ;; Compute sequence number of the element. + (setq seqno (org-odt--enumerate element info predicate)) + ;; Localize category string. + (setq category (org-export-translate category :utf-8 info)) + (case op + ;; Case 1: Handle Label definition. + (definition + ;; Assign an internal label, if user has not provided one + (setq label (org-export-solidify-link-text + (or label (format "%s-%s" default-category seqno)))) + (cons + (concat + ;; Sneak in a bookmark. The bookmark is used when the + ;; labeled element is referenced with a link that + ;; provides it's own description. + (format "\n" label) + ;; Label definition: Typically formatted as below: + ;; CATEGORY SEQ-NO: LONG CAPTION + ;; with translation for correct punctuation. + (format-spec + (org-export-translate + (cadr (assoc-string label-style org-odt-label-styles t)) + :utf-8 info) + `((?e . ,category) + (?n . ,(format + "%s" + label counter counter seqno)) + (?c . ,(or caption ""))))) + short-caption)) + ;; Case 2: Handle Label reference. + (reference + (assert label) + (setq label (org-export-solidify-link-text label)) + (let* ((fmt (cddr (assoc-string label-style org-odt-label-styles t))) + (fmt1 (car fmt)) + (fmt2 (cadr fmt))) + (format "%s" + fmt1 label (format-spec fmt2 `((?e . ,category) + (?n . ,seqno)))))) + (t (error "Unknown %S on label" op)))))))) + + +;;;; Links :: Inline Images + +(defun org-odt--copy-image-file (path) + "Returns the internal name of the file" + (let* ((image-type (file-name-extension path)) + (media-type (format "image/%s" image-type)) + (target-dir "Images/") + (target-file + (format "%s%04d.%s" target-dir + (incf org-odt-embedded-images-count) image-type))) + (message "Embedding %s as %s..." + (substring-no-properties path) target-file) + + (when (= 1 org-odt-embedded-images-count) + (make-directory (concat org-odt-zip-dir target-dir)) + (org-odt-create-manifest-file-entry "" target-dir)) + + (copy-file path (concat org-odt-zip-dir target-file) 'overwrite) + (org-odt-create-manifest-file-entry media-type target-file) + target-file)) + +(defun org-odt--image-size (file &optional user-width + user-height scale dpi embed-as) + (let* ((--pixels-to-cms + (function (lambda (pixels dpi) + (let ((cms-per-inch 2.54) + (inches (/ pixels dpi))) + (* cms-per-inch inches))))) + (--size-in-cms + (function + (lambda (size-in-pixels dpi) + (and size-in-pixels + (cons (funcall --pixels-to-cms (car size-in-pixels) dpi) + (funcall --pixels-to-cms (cdr size-in-pixels) dpi)))))) + (dpi (or dpi org-odt-pixels-per-inch)) + (anchor-type (or embed-as "paragraph")) + (user-width (and (not scale) user-width)) + (user-height (and (not scale) user-height)) + (size + (and + (not (and user-height user-width)) + (or + ;; Use Imagemagick. + (and (executable-find "identify") + (let ((size-in-pixels + (let ((dim (shell-command-to-string + (format "identify -format \"%%w:%%h\" \"%s\"" + file)))) + (when (string-match "\\([0-9]+\\):\\([0-9]+\\)" dim) + (cons (string-to-number (match-string 1 dim)) + (string-to-number (match-string 2 dim))))))) + (funcall --size-in-cms size-in-pixels dpi))) + ;; Use Emacs. + (let ((size-in-pixels + (ignore-errors ; Emacs could be in batch mode + (clear-image-cache) + (image-size (create-image file) 'pixels)))) + (funcall --size-in-cms size-in-pixels dpi)) + ;; Use hard-coded values. + (cdr (assoc-string anchor-type + org-odt-default-image-sizes-alist)) + ;; Error out. + (error "Cannot determine image size, aborting")))) + (width (car size)) (height (cdr size))) + (cond + (scale + (setq width (* width scale) height (* height scale))) + ((and user-height user-width) + (setq width user-width height user-height)) + (user-height + (setq width (* user-height (/ width height)) height user-height)) + (user-width + (setq height (* user-width (/ height width)) width user-width)) + (t (ignore))) + ;; ensure that an embedded image fits comfortably within a page + (let ((max-width (car org-odt-max-image-size)) + (max-height (cdr org-odt-max-image-size))) + (when (or (> width max-width) (> height max-height)) + (let* ((scale1 (/ max-width width)) + (scale2 (/ max-height height)) + (scale (min scale1 scale2))) + (setq width (* scale width) height (* scale height))))) + (cons width height))) + +(defun org-odt-link--inline-image (element info) + "Return ODT code for an inline image. +LINK is the link pointing to the inline image. INFO is a plist +used as a communication channel." + (assert (eq (org-element-type element) 'link)) + (let* ((src (let* ((type (org-element-property :type element)) + (raw-path (org-element-property :path element))) + (cond ((member type '("http" "https")) + (concat type ":" raw-path)) + ((file-name-absolute-p raw-path) + (expand-file-name raw-path)) + (t raw-path)))) + (src-expanded (if (file-name-absolute-p src) src + (expand-file-name src (file-name-directory + (plist-get info :input-file))))) + (href (format + "\n" + (org-odt--copy-image-file src-expanded))) + ;; Extract attributes from #+ATTR_ODT line. + (attr-from (case (org-element-type element) + (link (org-export-get-parent-element element)) + (t element))) + ;; Convert attributes to a plist. + (attr-plist (org-export-read-attribute :attr_odt attr-from)) + ;; Handle `:anchor', `:style' and `:attributes' properties. + (user-frame-anchor + (car (assoc-string (plist-get attr-plist :anchor) + '(("as-char") ("paragraph") ("page")) t))) + (user-frame-style + (and user-frame-anchor (plist-get attr-plist :style))) + (user-frame-attrs + (and user-frame-anchor (plist-get attr-plist :attributes))) + (user-frame-params + (list user-frame-style user-frame-attrs user-frame-anchor)) + ;; (embed-as (or embed-as user-frame-anchor "paragraph")) + ;; extrac + ;; + ;; Handle `:width', `:height' and `:scale' properties. Read + ;; them as numbers since we need them for computations. + (size (org-odt--image-size + src-expanded + (let ((width (plist-get attr-plist :width))) + (and width (read width))) + (let ((length (plist-get attr-plist :length))) + (and length (read length))) + (let ((scale (plist-get attr-plist :scale))) + (and scale (read scale))) + nil ; embed-as + "paragraph" ; FIXME + )) + (width (car size)) (height (cdr size)) + (standalone-link-p (org-odt--standalone-link-p element info)) + (embed-as (if standalone-link-p "paragraph" "as-char")) + (captions (org-odt-format-label element info 'definition)) + (caption (car captions)) (short-caption (cdr captions)) + (entity (concat (and caption "Captioned") embed-as "Image")) + ;; Check if this link was created by LaTeX-to-PNG converter. + (replaces (org-element-property + :replaces (if (not standalone-link-p) element + (org-export-get-parent-element element)))) + ;; If yes, note down the type of the element - LaTeX Fragment + ;; or LaTeX environment. It will go in to frame title. + (title (and replaces (capitalize + (symbol-name (org-element-type replaces))))) + + ;; If yes, note down it's contents. It will go in to frame + ;; description. This quite useful for debugging. + (desc (and replaces (org-element-property :value replaces)))) + (org-odt--render-image/formula entity href width height + captions user-frame-params title desc))) + + +;;;; Links :: Math formula + +(defun org-odt-link--inline-formula (element info) + (let* ((src (let* ((type (org-element-property :type element)) + (raw-path (org-element-property :path element))) + (cond + ((file-name-absolute-p raw-path) + (expand-file-name raw-path)) + (t raw-path)))) + (src-expanded (if (file-name-absolute-p src) src + (expand-file-name src (file-name-directory + (plist-get info :input-file))))) + (href + (format + "\n" + " xlink:show=\"embed\" xlink:actuate=\"onLoad\"" + (file-name-directory (org-odt--copy-formula-file src-expanded)))) + (standalone-link-p (org-odt--standalone-link-p element info)) + (embed-as (if standalone-link-p 'paragraph 'character)) + (captions (org-odt-format-label element info 'definition)) + (caption (car captions)) (short-caption (cdr captions)) + ;; Check if this link was created by LaTeX-to-MathML + ;; converter. + (replaces (org-element-property + :replaces (if (not standalone-link-p) element + (org-export-get-parent-element element)))) + ;; If yes, note down the type of the element - LaTeX Fragment + ;; or LaTeX environment. It will go in to frame title. + (title (and replaces (capitalize + (symbol-name (org-element-type replaces))))) + + ;; If yes, note down it's contents. It will go in to frame + ;; description. This quite useful for debugging. + (desc (and replaces (org-element-property :value replaces))) + width height) + (cond + ((eq embed-as 'character) + (org-odt--render-image/formula "InlineFormula" href width height + nil nil title desc)) + (t + (let* ((equation (org-odt--render-image/formula + "CaptionedDisplayFormula" href width height + captions nil title desc)) + (label + (let* ((org-odt-category-map-alist + '(("__MathFormula__" "Text" "math-label" "Equation" + org-odt--enumerable-formula-p)))) + (car (org-odt-format-label element info 'definition))))) + (concat equation "" label)))))) + +(defun org-odt--copy-formula-file (src-file) + "Returns the internal name of the file" + (let* ((target-dir (format "Formula-%04d/" + (incf org-odt-embedded-formulas-count))) + (target-file (concat target-dir "content.xml"))) + ;; Create a directory for holding formula file. Also enter it in + ;; to manifest. + (make-directory (concat org-odt-zip-dir target-dir)) + (org-odt-create-manifest-file-entry + "application/vnd.oasis.opendocument.formula" target-dir "1.2") + ;; Copy over the formula file from user directory to zip + ;; directory. + (message "Embedding %s as %s..." src-file target-file) + (let ((case-fold-search nil)) + (cond + ;; Case 1: Mathml. + ((string-match "\\.\\(mathml\\|mml\\)\\'" src-file) + (copy-file src-file (concat org-odt-zip-dir target-file) 'overwrite)) + ;; Case 2: OpenDocument formula. + ((string-match "\\.odf\\'" src-file) + (org-odt--zip-extract src-file "content.xml" + (concat org-odt-zip-dir target-dir))) + (t (error "%s is not a formula file" src-file)))) + ;; Enter the formula file in to manifest. + (org-odt-create-manifest-file-entry "text/xml" target-file) + target-file)) + +;;;; Targets + +(defun org-odt--render-image/formula (cfg-key href width height &optional + captions user-frame-params + &rest title-and-desc) + (let* ((frame-cfg-alist + ;; Each element of this alist is of the form (CFG-HANDLE + ;; INNER-FRAME-PARAMS OUTER-FRAME-PARAMS). + + ;; CFG-HANDLE is the key to the alist. + + ;; INNER-FRAME-PARAMS and OUTER-FRAME-PARAMS specify the + ;; frame params for INNER-FRAME and OUTER-FRAME + ;; respectively. See below. + + ;; Configurations that are meant to be applied to + ;; non-captioned image/formula specifies no + ;; OUTER-FRAME-PARAMS. + + ;; TERMINOLOGY + ;; =========== + ;; INNER-FRAME :: Frame that directly surrounds an + ;; image/formula. + + ;; OUTER-FRAME :: Frame that encloses the INNER-FRAME. This + ;; frame also contains the caption, if any. + + ;; FRAME-PARAMS :: List of the form (FRAME-STYLE-NAME + ;; FRAME-ATTRIBUTES FRAME-ANCHOR). Note + ;; that these are the last three arguments + ;; to `org-odt--frame'. + + ;; Note that an un-captioned image/formula requires just an + ;; INNER-FRAME, while a captioned image/formula requires + ;; both an INNER and an OUTER-FRAME. + '(("As-CharImage" ("OrgInlineImage" nil "as-char")) + ("ParagraphImage" ("OrgDisplayImage" nil "paragraph")) + ("PageImage" ("OrgPageImage" nil "page")) + ("CaptionedAs-CharImage" + ("OrgCaptionedImage" + " style:rel-width=\"100%\" style:rel-height=\"scale\"" "paragraph") + ("OrgInlineImage" nil "as-char")) + ("CaptionedParagraphImage" + ("OrgCaptionedImage" + " style:rel-width=\"100%\" style:rel-height=\"scale\"" "paragraph") + ("OrgImageCaptionFrame" nil "paragraph")) + ("CaptionedPageImage" + ("OrgCaptionedImage" + " style:rel-width=\"100%\" style:rel-height=\"scale\"" "paragraph") + ("OrgPageImageCaptionFrame" nil "page")) + ("InlineFormula" ("OrgInlineFormula" nil "as-char")) + ("DisplayFormula" ("OrgDisplayFormula" nil "as-char")) + ("CaptionedDisplayFormula" + ("OrgCaptionedFormula" nil "paragraph") + ("OrgFormulaCaptionFrame" nil "paragraph")))) + (caption (car captions)) (short-caption (cdr captions)) + ;; Retrieve inner and outer frame params, from configuration. + (frame-cfg (assoc-string cfg-key frame-cfg-alist t)) + (inner (nth 1 frame-cfg)) + (outer (nth 2 frame-cfg)) + ;; User-specified frame params (from #+ATTR_ODT spec) + (user user-frame-params) + (--merge-frame-params (function + (lambda (default user) + "Merge default and user frame params." + (if (not user) default + (assert (= (length default) 3)) + (assert (= (length user) 3)) + (loop for u in user + for d in default + collect (or u d))))))) + (cond + ;; Case 1: Image/Formula has no caption. + ;; There is only one frame, one that surrounds the image + ;; or formula. + ((not caption) + ;; Merge user frame params with that from configuration. + (setq inner (funcall --merge-frame-params inner user)) + (apply 'org-odt--frame href width height + (append inner title-and-desc))) + ;; Case 2: Image/Formula is captioned or labeled. + ;; There are two frames: The inner one surrounds the + ;; image or formula. The outer one contains the + ;; caption/sequence number. + (t + ;; Merge user frame params with outer frame params. + (setq outer (funcall --merge-frame-params outer user)) + ;; Short caption, if specified, goes as part of inner frame. + (setq inner (let ((frame-params (copy-sequence inner))) + (setcar (cdr frame-params) + (concat + (cadr frame-params) + (when short-caption + (format " draw:name=\"%s\" " short-caption)))) + frame-params)) + (apply 'org-odt--textbox + (format "\n%s" + "Illustration" + (concat + (apply 'org-odt--frame href width height + (append inner title-and-desc)) + caption)) + width height outer))))) + +(defun org-odt--enumerable-p (element info) + ;; Element should have a caption or label. + (or (org-element-property :caption element) + (org-element-property :name element))) + +(defun org-odt--enumerable-image-p (element info) + (org-odt--standalone-link-p + element info + ;; Paragraph should have a caption or label. It SHOULD NOT be a + ;; replacement element. (i.e., It SHOULD NOT be a result of LaTeX + ;; processing.) + (lambda (p) + (and (not (org-element-property :replaces p)) + (or (org-element-property :caption p) + (org-element-property :name p)))) + ;; Link should point to an image file. + (lambda (l) + (assert (eq (org-element-type l) 'link)) + (org-export-inline-image-p l org-odt-inline-image-rules)))) + +(defun org-odt--enumerable-latex-image-p (element info) + (org-odt--standalone-link-p + element info + ;; Paragraph should have a caption or label. It SHOULD also be a + ;; replacement element. (i.e., It SHOULD be a result of LaTeX + ;; processing.) + (lambda (p) + (and (org-element-property :replaces p) + (or (org-element-property :caption p) + (org-element-property :name p)))) + ;; Link should point to an image file. + (lambda (l) + (assert (eq (org-element-type l) 'link)) + (org-export-inline-image-p l org-odt-inline-image-rules)))) + +(defun org-odt--enumerable-formula-p (element info) + (org-odt--standalone-link-p + element info + ;; Paragraph should have a caption or label. + (lambda (p) + (or (org-element-property :caption p) + (org-element-property :name p))) + ;; Link should point to a MathML or ODF file. + (lambda (l) + (assert (eq (org-element-type l) 'link)) + (org-export-inline-image-p l org-odt-inline-formula-rules)))) + +(defun org-odt--standalone-link-p (element info &optional + paragraph-predicate + link-predicate) + "Test if ELEMENT is a standalone link for the purpose ODT export. +INFO is a plist holding contextual information. + +Return non-nil, if ELEMENT is of type paragraph satisfying +PARAGRAPH-PREDICATE and it's sole content, save for whitespaces, +is a link that satisfies LINK-PREDICATE. + +Return non-nil, if ELEMENT is of type link satisfying +LINK-PREDICATE and it's containing paragraph satisfies +PARAGRAPH-PREDICATE inaddtion to having no other content save for +leading and trailing whitespaces. + +Return nil, otherwise." + (let ((p (case (org-element-type element) + (paragraph element) + (link (and (or (not link-predicate) + (funcall link-predicate element)) + (org-export-get-parent element))) + (t nil)))) + (when (and p (eq (org-element-type p) 'paragraph)) + (when (or (not paragraph-predicate) + (funcall paragraph-predicate p)) + (let ((contents (org-element-contents p))) + (loop for x in contents + with inline-image-count = 0 + always (case (org-element-type x) + (plain-text + (not (org-string-nw-p x))) + (link + (and (or (not link-predicate) + (funcall link-predicate x)) + (= (incf inline-image-count) 1))) + (t nil)))))))) + +(defun org-odt-link--infer-description (destination info) + ;; DESTINATION is a HEADLINE, a "<>" or an element (like + ;; paragraph, verse-block etc) to which a "#+NAME: label" can be + ;; attached. Note that labels that are attached to captioned + ;; entities - inline images, math formulae and tables - get resolved + ;; as part of `org-odt-format-label' and `org-odt--enumerate'. + + ;; Create a cross-reference to DESTINATION but make best-efforts to + ;; create a *meaningful* description. Check item numbers, section + ;; number and section title in that order. + + ;; NOTE: Counterpart of `org-export-get-ordinal'. + ;; FIXME: Handle footnote-definition footnote-reference? + (let* ((genealogy (org-export-get-genealogy destination)) + (data (reverse genealogy)) + (label (case (org-element-type destination) + (headline + (format "sec-%s" (mapconcat 'number-to-string + (org-export-get-headline-number + destination info) "-"))) + (target + (org-element-property :value destination)) + (t (error "FIXME: Resolve %S" destination))))) + (or + (let* ( ;; Locate top-level list. + (top-level-list + (loop for x on data + when (eq (org-element-type (car x)) 'plain-list) + return x)) + ;; Get list item nos. + (item-numbers + (loop for (plain-list item . rest) on top-level-list by #'cddr + until (not (eq (org-element-type plain-list) 'plain-list)) + collect (when (eq (org-element-property :type + plain-list) + 'ordered) + (1+ (length (org-export-get-previous-element + item info t)))))) + ;; Locate top-most listified headline. + (listified-headlines + (loop for x on data + when (and (eq (org-element-type (car x)) 'headline) + (org-export-low-level-p (car x) info)) + return x)) + ;; Get listified headline numbers. + (listified-headline-nos + (loop for el in listified-headlines + when (eq (org-element-type el) 'headline) + collect (when (org-export-numbered-headline-p el info) + (1+ (length (org-export-get-previous-element + el info t))))))) + ;; Combine item numbers from both the listified headlines and + ;; regular list items. + + ;; Case 1: Check if all the parents of list item are numbered. + ;; If yes, link to the item proper. + (let ((item-numbers (append listified-headline-nos item-numbers))) + (when (and item-numbers (not (memq nil item-numbers))) + (format "%s" + (org-export-solidify-link-text label) + (mapconcat (lambda (n) (if (not n) " " + (concat (number-to-string n) "."))) + item-numbers ""))))) + ;; Case 2: Locate a regular and numbered headline in the + ;; hierarchy. Display it's section number. + (let ((headline (loop for el in (cons destination genealogy) + when (and (eq (org-element-type el) 'headline) + (not (org-export-low-level-p el info)) + (org-export-numbered-headline-p el info)) + return el))) + ;; We found one. + (when headline + (format "%s" + (org-export-solidify-link-text label) + (mapconcat 'number-to-string (org-export-get-headline-number + headline info) ".")))) + ;; Case 4: Locate a regular headline in the hierarchy. Display + ;; it's title. + (let ((headline (loop for el in (cons destination genealogy) + when (and (eq (org-element-type el) 'headline) + (not (org-export-low-level-p el info))) + return el))) + ;; We found one. + (when headline + (format "%s" + (org-export-solidify-link-text label) + (let ((title (org-element-property :title headline))) + (org-export-data title info))))) + (error "FIXME?")))) + +(defun org-odt-link (link desc info) + "Transcode a LINK object from Org to ODT. + +DESC is the description part of the link, or the empty string. +INFO is a plist holding contextual information. See +`org-export-data'." + (let* ((type (org-element-property :type link)) + (raw-path (org-element-property :path link)) + ;; Ensure DESC really exists, or set it to nil. + (desc (and (not (string= desc "")) desc)) + (imagep (org-export-inline-image-p + link org-odt-inline-image-rules)) + (path (cond + ((member type '("http" "https" "ftp" "mailto")) + (concat type ":" raw-path)) + ((string= type "file") + (if (file-name-absolute-p raw-path) + (concat "file://" (expand-file-name raw-path)) + (concat "file://" raw-path))) + (t raw-path))) + ;; Convert & to & for correct XML representation + (path (replace-regexp-in-string "&" "&" path)) + protocol) + (cond + ;; Image file. + ((and (not desc) (org-export-inline-image-p + link org-odt-inline-image-rules)) + (org-odt-link--inline-image link info)) + ;; Formula file. + ((and (not desc) (org-export-inline-image-p + link org-odt-inline-formula-rules)) + (org-odt-link--inline-formula link info)) + ;; Radio target: Transcode target's contents and use them as + ;; link's description. + ((string= type "radio") + (let ((destination (org-export-resolve-radio-link link info))) + (when destination + (let ((desc (org-export-data (org-element-contents destination) info)) + (href (org-export-solidify-link-text path))) + (format + "%s" + href desc))))) + ;; Links pointing to a headline: Find destination and build + ;; appropriate referencing command. + ((member type '("custom-id" "fuzzy" "id")) + (let ((destination (if (string= type "fuzzy") + (org-export-resolve-fuzzy-link link info) + (org-export-resolve-id-link link info)))) + (case (org-element-type destination) + ;; Case 1: Fuzzy link points nowhere. + ('nil + (format "%s" + "Emphasis" + (or desc + (org-export-data (org-element-property :raw-link link) + info)))) + ;; Case 2: Fuzzy link points to a headline. + (headline + ;; If there's a description, create a hyperlink. + ;; Otherwise, try to provide a meaningful description. + (if (not desc) (org-odt-link--infer-description destination info) + (let* ((headline-no + (org-export-get-headline-number destination info)) + (label + (format "sec-%s" + (mapconcat 'number-to-string headline-no "-")))) + (format + "%s" + label desc)))) + ;; Case 3: Fuzzy link points to a target. + (target + ;; If there's a description, create a hyperlink. + ;; Otherwise, try to provide a meaningful description. + (if (not desc) (org-odt-link--infer-description destination info) + (let ((label (org-element-property :value destination))) + (format "%s" + (org-export-solidify-link-text label) + desc)))) + ;; Case 4: Fuzzy link points to some element (e.g., an + ;; inline image, a math formula or a table). + (otherwise + (let ((label-reference + (ignore-errors (org-odt-format-label + destination info 'reference)))) + (cond ((not label-reference) + (org-odt-link--infer-description destination info)) + ;; LINK has no description. Create + ;; a cross-reference showing entity's sequence + ;; number. + ((not desc) label-reference) + ;; LINK has description. Insert a hyperlink with + ;; user-provided description. + (t + (let ((label (org-element-property :name destination))) + (format "%s" + (org-export-solidify-link-text label) + desc))))))))) + ;; Coderef: replace link with the reference name or the + ;; equivalent line number. + ((string= type "coderef") + (let* ((line-no (format "%d" (org-export-resolve-coderef path info))) + (href (concat "coderef-" path))) + (format + (org-export-get-coderef-format path desc) + (format + "%s" + href line-no)))) + ;; Link type is handled by a special function. + ((functionp (setq protocol (nth 2 (assoc type org-link-protocols)))) + (funcall protocol (org-link-unescape path) desc 'odt)) + ;; External link with a description part. + ((and path desc) + (let ((link-contents (org-element-contents link))) + ;; Check if description is a link to an inline image. + (if (and (not (cdr link-contents)) + (let ((desc-element (car link-contents))) + (and (eq (org-element-type desc-element) 'link) + (org-export-inline-image-p + desc-element org-odt-inline-image-rules)))) + ;; Format link as a clickable image. + (format "\n\n%s\n" + path desc) + ;; Otherwise, format it as a regular link. + (format "%s" + path desc)))) + ;; External link without a description part. + (path + (format "%s" + path path)) + ;; No path, only description. Try to do something useful. + (t (format "%s" + "Emphasis" desc))))) + + +;;;; Paragraph + +(defun org-odt--format-paragraph (paragraph contents default center quote) + "Format paragraph according to given styles. +PARAGRAPH is a paragraph type element. CONTENTS is the +transcoded contents of that paragraph, as a string. DEFAULT, +CENTER and QUOTE are, respectively, style to use when paragraph +belongs to no special environment, a center block, or a quote +block." + (let* ((parent (org-export-get-parent paragraph)) + (parent-type (org-element-type parent)) + (style (case parent-type + (quote-block quote) + (center-block center) + (t default)))) + ;; If this paragraph is a leading paragraph in an item and the + ;; item has a checkbox, splice the checkbox and paragraph contents + ;; together. + (when (and (eq (org-element-type parent) 'item) + (eq paragraph (car (org-element-contents parent)))) + (setq contents (concat (org-odt--checkbox parent) contents))) + (format "\n%s" style contents))) + +(defun org-odt-paragraph (paragraph contents info) + "Transcode a PARAGRAPH element from Org to ODT. +CONTENTS is the contents of the paragraph, as a string. INFO is +the plist used as a communication channel." + (org-odt--format-paragraph + paragraph contents + (or (org-element-property :style paragraph) "Text_20_body") + "OrgCenter" + "Quotations")) + + +;;;; Plain List + +(defun org-odt-plain-list (plain-list contents info) + "Transcode a PLAIN-LIST element from Org to ODT. +CONTENTS is the contents of the list. INFO is a plist holding +contextual information." + (format "\n\n%s" + ;; Choose style based on list type. + (case (org-element-property :type plain-list) + (ordered "OrgNumberedList") + (unordered "OrgBulletedList") + (descriptive-1 "OrgDescriptionList") + (descriptive-2 "OrgDescriptionList")) + ;; If top-level list, re-start numbering. Otherwise, + ;; continue numbering. + (format "text:continue-numbering=\"%s\"" + (let* ((parent (org-export-get-parent plain-list))) + (if (and parent (eq (org-element-type parent) 'item)) + "true" "false"))) + contents)) + +;;;; Plain Text + +(defun org-odt--encode-tabs-and-spaces (line) + (replace-regexp-in-string + "\\([\t]\\|\\([ ]+\\)\\)" + (lambda (s) + (cond + ((string= s "\t") "") + (t (let ((n (length s))) + (cond + ((= n 1) " ") + ((> n 1) (concat " " (format "" (1- n)))) + (t "")))))) + line)) + +(defun org-odt--encode-plain-text (text &optional no-whitespace-filling) + (mapc + (lambda (pair) + (setq text (replace-regexp-in-string (car pair) (cdr pair) text t t))) + '(("&" . "&") ("<" . "<") (">" . ">"))) + (if no-whitespace-filling text + (org-odt--encode-tabs-and-spaces text))) + +(defun org-odt-plain-text (text info) + "Transcode a TEXT string from Org to ODT. +TEXT is the string to transcode. INFO is a plist holding +contextual information." + (let ((output text)) + ;; Protect &, < and >. + (setq output (org-odt--encode-plain-text output t)) + ;; Handle smart quotes. Be sure to provide original string since + ;; OUTPUT may have been modified. + (when (plist-get info :with-smart-quotes) + (setq output (org-export-activate-smart-quotes output :utf-8 info text))) + ;; Convert special strings. + (when (plist-get info :with-special-strings) + (mapc + (lambda (pair) + (setq output + (replace-regexp-in-string (car pair) (cdr pair) output t nil))) + org-odt-special-string-regexps)) + ;; Handle break preservation if required. + (when (plist-get info :preserve-breaks) + (setq output (replace-regexp-in-string + "\\(\\\\\\\\\\)?[ \t]*\n" "" output t))) + ;; Return value. + output)) + + +;;;; Planning + +(defun org-odt-planning (planning contents info) + "Transcode a PLANNING element from Org to ODT. +CONTENTS is nil. INFO is a plist used as a communication +channel." + (format "\n%s" + "OrgPlanning" + (concat + (let ((closed (org-element-property :closed planning))) + (when closed + (concat + (format "%s" + "OrgClosedKeyword" org-closed-string) + (org-odt-timestamp closed contents info)))) + (let ((deadline (org-element-property :deadline planning))) + (when deadline + (concat + (format "%s" + "OrgDeadlineKeyword" org-deadline-string) + (org-odt-timestamp deadline contents info)))) + (let ((scheduled (org-element-property :scheduled planning))) + (when scheduled + (concat + (format "%s" + "OrgScheduledKeyword" org-deadline-string) + (org-odt-timestamp scheduled contents info))))))) + + +;;;; Property Drawer + +(defun org-odt-property-drawer (property-drawer contents info) + "Transcode a PROPERTY-DRAWER element from Org to ODT. +CONTENTS is nil. INFO is a plist holding contextual +information." + ;; The property drawer isn't exported but we want separating blank + ;; lines nonetheless. + "") + + +;;;; Quote Block + +(defun org-odt-quote-block (quote-block contents info) + "Transcode a QUOTE-BLOCK element from Org to ODT. +CONTENTS holds the contents of the block. INFO is a plist +holding contextual information." + contents) + + +;;;; Quote Section + +(defun org-odt-quote-section (quote-section contents info) + "Transcode a QUOTE-SECTION element from Org to ODT. +CONTENTS is nil. INFO is a plist holding contextual information." + (let ((value (org-remove-indentation + (org-element-property :value quote-section)))) + (when value (org-odt-do-format-code value)))) + + +;;;; Section + +(defun org-odt-format-section (text style &optional name) + (let ((default-name (car (org-odt-add-automatic-style "Section")))) + (format "\n\n%s\n" + style + (format "text:name=\"%s\"" (or name default-name)) + text))) + + +(defun org-odt-section (section contents info) ; FIXME + "Transcode a SECTION element from Org to ODT. +CONTENTS holds the contents of the section. INFO is a plist +holding contextual information." + contents) + +;;;; Radio Target + +(defun org-odt-radio-target (radio-target text info) + "Transcode a RADIO-TARGET object from Org to ODT. +TEXT is the text of the target. INFO is a plist holding +contextual information." + (org-odt--target + text (org-export-solidify-link-text + (org-element-property :value radio-target)))) + + +;;;; Special Block + +(defun org-odt-special-block (special-block contents info) + "Transcode a SPECIAL-BLOCK element from Org to ODT. +CONTENTS holds the contents of the block. INFO is a plist +holding contextual information." + (let ((type (downcase (org-element-property :type special-block))) + (attributes (org-export-read-attribute :attr_odt special-block))) + (cond + ;; Annotation. + ((string= type "annotation") + (let* ((author (or (plist-get attributes :author) + (let ((author (plist-get info :author))) + (and author (org-export-data author info))))) + (date (or (plist-get attributes :date) + ;; FIXME: Is `car' right thing to do below? + (car (plist-get info :date))))) + (format "\n%s" + (format "\n%s\n" + (concat + (and author + (format "%s" author)) + (and date + (format "%s" + (org-odt--format-timestamp date nil 'iso-date))) + contents))))) + ;; Textbox. + ((string= type "textbox") + (let ((width (plist-get attributes :width)) + (height (plist-get attributes :height)) + (style (plist-get attributes :style)) + (extra (plist-get attributes :extra)) + (anchor (plist-get attributes :anchor))) + (format "\n%s" + "Text_20_body" (org-odt--textbox contents width height + style extra anchor)))) + (t contents)))) + + +;;;; Src Block + +(defun org-odt-hfy-face-to-css (fn) + "Create custom style for face FN. +When FN is the default face, use it's foreground and background +properties to create \"OrgSrcBlock\" paragraph style. Otherwise +use it's color attribute to create a character style whose name +is obtained from FN. Currently all attributes of FN other than +color are ignored. + +The style name for a face FN is derived using the following +operations on the face name in that order - de-dash, CamelCase +and prefix with \"OrgSrc\". For example, +`font-lock-function-name-face' is associated with +\"OrgSrcFontLockFunctionNameFace\"." + (let* ((css-list (hfy-face-to-style fn)) + (style-name ((lambda (fn) + (concat "OrgSrc" + (mapconcat + 'capitalize (split-string + (hfy-face-or-def-to-name fn) "-") + ""))) fn)) + (color-val (cdr (assoc "color" css-list))) + (background-color-val (cdr (assoc "background" css-list))) + (style (and org-odt-create-custom-styles-for-srcblocks + (cond + ((eq fn 'default) + (format org-odt-src-block-paragraph-format + background-color-val color-val)) + (t + (format + " + + + " style-name color-val)))))) + (cons style-name style))) + +(defun org-odt-htmlfontify-string (line) + (let* ((hfy-html-quote-regex "\\([<\"&> ]\\)") + (hfy-html-quote-map '(("\"" """) + ("<" "<") + ("&" "&") + (">" ">") + (" " "") + (" " ""))) + (hfy-face-to-css 'org-odt-hfy-face-to-css) + (hfy-optimisations-1 (copy-sequence hfy-optimisations)) + (hfy-optimisations (add-to-list 'hfy-optimisations-1 + 'body-text-only)) + (hfy-begin-span-handler + (lambda (style text-block text-id text-begins-block-p) + (insert (format "" style)))) + (hfy-end-span-handler (lambda nil (insert "")))) + (org-no-warnings (htmlfontify-string line)))) + +(defun org-odt-do-format-code + (code &optional lang refs retain-labels num-start) + (let* ((lang (or (assoc-default lang org-src-lang-modes) lang)) + (lang-mode (and lang (intern (format "%s-mode" lang)))) + (code-lines (org-split-string code "\n")) + (code-length (length code-lines)) + (use-htmlfontify-p (and (functionp lang-mode) + org-odt-fontify-srcblocks + (require 'htmlfontify nil t) + (fboundp 'htmlfontify-string))) + (code (if (not use-htmlfontify-p) code + (with-temp-buffer + (insert code) + (funcall lang-mode) + (font-lock-fontify-buffer) + (buffer-string)))) + (fontifier (if use-htmlfontify-p 'org-odt-htmlfontify-string + 'org-odt--encode-plain-text)) + (par-style (if use-htmlfontify-p "OrgSrcBlock" + "OrgFixedWidthBlock")) + (i 0)) + (assert (= code-length (length (org-split-string code "\n")))) + (setq code + (org-export-format-code + code + (lambda (loc line-num ref) + (setq par-style + (concat par-style (and (= (incf i) code-length) "LastLine"))) + + (setq loc (concat loc (and ref retain-labels (format " (%s)" ref)))) + (setq loc (funcall fontifier loc)) + (when ref + (setq loc (org-odt--target loc (concat "coderef-" ref)))) + (assert par-style) + (setq loc (format "\n%s" + par-style loc)) + (if (not line-num) loc + (format "\n%s\n" loc))) + num-start refs)) + (cond + ((not num-start) code) + ((= num-start 0) + (format + "\n%s" + " text:continue-numbering=\"false\"" code)) + (t + (format + "\n%s" + " text:continue-numbering=\"true\"" code))))) + +(defun org-odt-format-code (element info) + (let* ((lang (org-element-property :language element)) + ;; Extract code and references. + (code-info (org-export-unravel-code element)) + (code (car code-info)) + (refs (cdr code-info)) + ;; Does the src block contain labels? + (retain-labels (org-element-property :retain-labels element)) + ;; Does it have line numbers? + (num-start (case (org-element-property :number-lines element) + (continued (org-export-get-loc element info)) + (new 0)))) + (org-odt-do-format-code code lang refs retain-labels num-start))) + +(defun org-odt-src-block (src-block contents info) + "Transcode a SRC-BLOCK element from Org to ODT. +CONTENTS holds the contents of the item. INFO is a plist holding +contextual information." + (let* ((lang (org-element-property :language src-block)) + (attributes (org-export-read-attribute :attr_odt src-block)) + (captions (org-odt-format-label src-block info 'definition)) + (caption (car captions)) (short-caption (cdr captions))) + (concat + (and caption + (format "\n%s" + "Listing" caption)) + (let ((--src-block (org-odt-format-code src-block info))) + (if (not (plist-get attributes :textbox)) --src-block + (format "\n%s" + "Text_20_body" + (org-odt--textbox --src-block nil nil nil))))))) + + +;;;; Statistics Cookie + +(defun org-odt-statistics-cookie (statistics-cookie contents info) + "Transcode a STATISTICS-COOKIE object from Org to ODT. +CONTENTS is nil. INFO is a plist holding contextual information." + (let ((cookie-value (org-element-property :value statistics-cookie))) + (format "%s" + "OrgCode" cookie-value))) + + +;;;; Strike-Through + +(defun org-odt-strike-through (strike-through contents info) + "Transcode STRIKE-THROUGH from Org to ODT. +CONTENTS is the text with strike-through markup. INFO is a plist +holding contextual information." + (format "%s" + "Strikethrough" contents)) + + +;;;; Subscript + +(defun org-odt-subscript (subscript contents info) + "Transcode a SUBSCRIPT object from Org to ODT. +CONTENTS is the contents of the object. INFO is a plist holding +contextual information." + (format "%s" + "OrgSubscript" contents)) + + +;;;; Superscript + +(defun org-odt-superscript (superscript contents info) + "Transcode a SUPERSCRIPT object from Org to ODT. +CONTENTS is the contents of the object. INFO is a plist holding +contextual information." + (format "%s" + "OrgSuperscript" contents)) + + +;;;; Table Cell + +(defun org-odt-table-style-spec (element info) + (let* ((table (org-export-get-parent-table element)) + (table-attributes (org-export-read-attribute :attr_odt table)) + (table-style (plist-get table-attributes :style))) + (assoc table-style org-odt-table-styles))) + +(defun org-odt-get-table-cell-styles (table-cell info) + "Retrieve styles applicable to a table cell. +R and C are (zero-based) row and column numbers of the table +cell. STYLE-SPEC is an entry in `org-odt-table-styles' +applicable to the current table. It is `nil' if the table is not +associated with any style attributes. + +Return a cons of (TABLE-CELL-STYLE-NAME . PARAGRAPH-STYLE-NAME). + +When STYLE-SPEC is nil, style the table cell the conventional way +- choose cell borders based on row and column groupings and +choose paragraph alignment based on `org-col-cookies' text +property. See also +`org-odt-get-paragraph-style-cookie-for-table-cell'. + +When STYLE-SPEC is non-nil, ignore the above cookie and return +styles congruent with the ODF-1.2 specification." + (let* ((table-cell-address (org-export-table-cell-address table-cell info)) + (r (car table-cell-address)) (c (cdr table-cell-address)) + (style-spec (org-odt-table-style-spec table-cell info)) + (table-dimensions (org-export-table-dimensions + (org-export-get-parent-table table-cell) + info))) + (when style-spec + ;; LibreOffice - particularly the Writer - honors neither table + ;; templates nor custom table-cell styles. Inorder to retain + ;; inter-operability with LibreOffice, only automatic styles are + ;; used for styling of table-cells. The current implementation is + ;; congruent with ODF-1.2 specification and hence is + ;; future-compatible. + + ;; Additional Note: LibreOffice's AutoFormat facility for tables - + ;; which recognizes as many as 16 different cell types - is much + ;; richer. Unfortunately it is NOT amenable to easy configuration + ;; by hand. + (let* ((template-name (nth 1 style-spec)) + (cell-style-selectors (nth 2 style-spec)) + (cell-type + (cond + ((and (cdr (assoc 'use-first-column-styles cell-style-selectors)) + (= c 0)) "FirstColumn") + ((and (cdr (assoc 'use-last-column-styles cell-style-selectors)) + (= (1+ c) (cdr table-dimensions))) + "LastColumn") + ((and (cdr (assoc 'use-first-row-styles cell-style-selectors)) + (= r 0)) "FirstRow") + ((and (cdr (assoc 'use-last-row-styles cell-style-selectors)) + (= (1+ r) (car table-dimensions))) + "LastRow") + ((and (cdr (assoc 'use-banding-rows-styles cell-style-selectors)) + (= (% r 2) 1)) "EvenRow") + ((and (cdr (assoc 'use-banding-rows-styles cell-style-selectors)) + (= (% r 2) 0)) "OddRow") + ((and (cdr (assoc 'use-banding-columns-styles cell-style-selectors)) + (= (% c 2) 1)) "EvenColumn") + ((and (cdr (assoc 'use-banding-columns-styles cell-style-selectors)) + (= (% c 2) 0)) "OddColumn") + (t "")))) + (concat template-name cell-type))))) + +(defun org-odt-table-cell (table-cell contents info) + "Transcode a TABLE-CELL element from Org to ODT. +CONTENTS is nil. INFO is a plist used as a communication +channel." + (let* ((table-cell-address (org-export-table-cell-address table-cell info)) + (r (car table-cell-address)) + (c (cdr table-cell-address)) + (horiz-span (or (org-export-table-cell-width table-cell info) 0)) + (table-row (org-export-get-parent table-cell)) + (custom-style-prefix (org-odt-get-table-cell-styles + table-cell info)) + (paragraph-style + (or + (and custom-style-prefix + (format "%sTableParagraph" custom-style-prefix)) + (concat + (cond + ((and (= 1 (org-export-table-row-group table-row info)) + (org-export-table-has-header-p + (org-export-get-parent-table table-row) info)) + "OrgTableHeading") + ((let* ((table (org-export-get-parent-table table-cell)) + (table-attrs (org-export-read-attribute :attr_odt table)) + (table-header-columns + (let ((cols (plist-get table-attrs :header-columns))) + (and cols (read cols))))) + (<= c (cond ((wholenump table-header-columns) + (- table-header-columns 1)) + (table-header-columns 0) + (t -1)))) + "OrgTableHeading") + (t "OrgTableContents")) + (capitalize (symbol-name (org-export-table-cell-alignment + table-cell info)))))) + (cell-style-name + (or + (and custom-style-prefix (format "%sTableCell" + custom-style-prefix)) + (concat + "OrgTblCell" + (when (or (org-export-table-row-starts-rowgroup-p table-row info) + (zerop r)) "T") + (when (org-export-table-row-ends-rowgroup-p table-row info) "B") + (when (and (org-export-table-cell-starts-colgroup-p table-cell info) + (not (zerop c)) ) "L")))) + (cell-attributes + (concat + (format " table:style-name=\"%s\"" cell-style-name) + (and (> horiz-span 0) + (format " table:number-columns-spanned=\"%d\"" + (1+ horiz-span)))))) + (unless contents (setq contents "")) + (concat + (assert paragraph-style) + (format "\n\n%s\n" + cell-attributes + (let ((table-cell-contents (org-element-contents table-cell))) + (if (memq (org-element-type (car table-cell-contents)) + org-element-all-elements) + contents + (format "\n%s" + paragraph-style contents)))) + (let (s) + (dotimes (i horiz-span s) + (setq s (concat s "\n")))) + "\n"))) + + +;;;; Table Row + +(defun org-odt-table-row (table-row contents info) + "Transcode a TABLE-ROW element from Org to ODT. +CONTENTS is the contents of the row. INFO is a plist used as a +communication channel." + ;; Rules are ignored since table separators are deduced from + ;; borders of the current row. + (when (eq (org-element-property :type table-row) 'standard) + (let* ((rowgroup-tags + (if (and (= 1 (org-export-table-row-group table-row info)) + (org-export-table-has-header-p + (org-export-get-parent-table table-row) info)) + ;; If the row belongs to the first rowgroup and the + ;; table has more than one row groups, then this row + ;; belongs to the header row group. + '("\n" . "\n") + ;; Otherwise, it belongs to non-header row group. + '("\n" . "\n")))) + (concat + ;; Does this row begin a rowgroup? + (when (org-export-table-row-starts-rowgroup-p table-row info) + (car rowgroup-tags)) + ;; Actual table row + (format "\n\n%s\n" contents) + ;; Does this row end a rowgroup? + (when (org-export-table-row-ends-rowgroup-p table-row info) + (cdr rowgroup-tags)))))) + + +;;;; Table + +(defun org-odt-table-first-row-data-cells (table info) + (let ((table-row + (org-element-map table 'table-row + (lambda (row) + (unless (eq (org-element-property :type row) 'rule) row)) + info 'first-match)) + (special-column-p (org-export-table-has-special-column-p table))) + (if (not special-column-p) (org-element-contents table-row) + (cdr (org-element-contents table-row))))) + +(defun org-odt--table (table contents info) + "Transcode a TABLE element from Org to ODT. +CONTENTS is the contents of the table. INFO is a plist holding +contextual information." + (case (org-element-property :type table) + ;; Case 1: table.el doesn't support export to OD format. Strip + ;; such tables from export. + (table.el + (prog1 nil + (message + (concat + "(ox-odt): Found table.el-type table in the source Org file." + " table.el doesn't support export to ODT format." + " Stripping the table from export.")))) + ;; Case 2: Native Org tables. + (otherwise + (let* ((captions (org-odt-format-label table info 'definition)) + (caption (car captions)) (short-caption (cdr captions)) + (attributes (org-export-read-attribute :attr_odt table)) + (custom-table-style (nth 1 (org-odt-table-style-spec table info))) + (table-column-specs + (function + (lambda (table info) + (let* ((table-style (or custom-table-style "OrgTable")) + (column-style (format "%sColumn" table-style))) + (mapconcat + (lambda (table-cell) + (let ((width (1+ (or (org-export-table-cell-width + table-cell info) 0))) + (s (format + "\n" + column-style)) + out) + (dotimes (i width out) (setq out (concat s out))))) + (org-odt-table-first-row-data-cells table info) "\n")))))) + (concat + ;; caption. + (when caption + (format "\n%s" + "Table" caption)) + ;; begin table. + (let* ((automatic-name + (org-odt-add-automatic-style "Table" attributes))) + (format + "\n" + (or custom-table-style (cdr automatic-name) "OrgTable") + (concat (when short-caption + (format " table:name=\"%s\"" short-caption))))) + ;; column specification. + (funcall table-column-specs table info) + ;; actual contents. + "\n" contents + ;; end table. + ""))))) + +(defun org-odt-table (table contents info) + "Transcode a TABLE element from Org to ODT. +CONTENTS is the contents of the table. INFO is a plist holding +contextual information. + +Use `org-odt--table' to typeset the table. Handle details +pertaining to indentation here." + (let* ((--element-preceded-by-table-p + (function + (lambda (element info) + (loop for el in (org-export-get-previous-element element info t) + thereis (eq (org-element-type el) 'table))))) + (--walk-list-genealogy-and-collect-tags + (function + (lambda (table info) + (let* ((genealogy (org-export-get-genealogy table)) + (list-genealogy + (when (eq (org-element-type (car genealogy)) 'item) + (loop for el in genealogy + when (memq (org-element-type el) + '(item plain-list)) + collect el))) + (llh-genealogy + (apply 'nconc + (loop for el in genealogy + when (and (eq (org-element-type el) 'headline) + (org-export-low-level-p el info)) + collect + (list el + (assq 'headline + (org-element-contents + (org-export-get-parent el))))))) + parent-list) + (nconc + ;; Handle list genealogy. + (loop for el in list-genealogy collect + (case (org-element-type el) + (plain-list + (setq parent-list el) + (cons "" + (format "\n" + (case (org-element-property :type el) + (ordered "OrgNumberedList") + (unordered "OrgBulletedList") + (descriptive-1 "OrgDescriptionList") + (descriptive-2 "OrgDescriptionList")) + "text:continue-numbering=\"true\""))) + (item + (cond + ((not parent-list) + (if (funcall --element-preceded-by-table-p table info) + '("" . "") + '("" . ""))) + ((funcall --element-preceded-by-table-p + parent-list info) + '("" . "")) + (t '("" . "")))))) + ;; Handle low-level headlines. + (loop for el in llh-genealogy + with step = 'item collect + (case step + (plain-list + (setq step 'item) ; Flip-flop + (setq parent-list el) + (cons "" + (format "\n" + (if (org-export-numbered-headline-p + el info) + "OrgNumberedList" + "OrgBulletedList") + "text:continue-numbering=\"true\""))) + (item + (setq step 'plain-list) ; Flip-flop + (cond + ((not parent-list) + (if (funcall --element-preceded-by-table-p table info) + '("" . "") + '("" . ""))) + ((let ((section? (org-export-get-previous-element + parent-list info))) + (and section? + (eq (org-element-type section?) 'section) + (assq 'table (org-element-contents section?)))) + '("" . "")) + (t + '("" . ""))))))))))) + (close-open-tags (funcall --walk-list-genealogy-and-collect-tags + table info))) + ;; OpenDocument schema does not permit table to occur within a + ;; list item. + + ;; One solution - the easiest and lightweight, in terms of + ;; implementation - is to put the table in an indented text box + ;; and make the text box part of the list-item. Unfortunately if + ;; the table is big and spans multiple pages, the text box could + ;; overflow. In this case, the following attribute will come + ;; handy. + + ;; ,---- From OpenDocument-v1.1.pdf + ;; | 15.27.28 Overflow behavior + ;; | + ;; | For text boxes contained within text document, the + ;; | style:overflow-behavior property specifies the behavior of text + ;; | boxes where the containing text does not fit into the text + ;; | box. + ;; | + ;; | If the attribute's value is clip, the text that does not fit + ;; | into the text box is not displayed. + ;; | + ;; | If the attribute value is auto-create-new-frame, a new frame + ;; | will be created on the next page, with the same position and + ;; | dimensions of the original frame. + ;; | + ;; | If the style:overflow-behavior property's value is + ;; | auto-create-new-frame and the text box has a minimum width or + ;; | height specified, then the text box will grow until the page + ;; | bounds are reached before a new frame is created. + ;; `---- + + ;; Unfortunately, LibreOffice-3.4.6 doesn't honor + ;; auto-create-new-frame property and always resorts to clipping + ;; the text box. This results in table being truncated. + + ;; So we solve the problem the hard (and fun) way using list + ;; continuations. + + ;; The problem only becomes more interesting if you take in to + ;; account the following facts: + ;; + ;; - Description lists are simulated as plain lists. + ;; - Low-level headlines can be listified. + ;; - In Org-mode, a table can occur not only as a regular list + ;; item, but also within description lists and low-level + ;; headlines. + + ;; See `org-odt-translate-description-lists' and + ;; `org-odt-translate-low-level-headlines' for how this is + ;; tackled. + + (concat "\n" + ;; Discontinue the list. + (mapconcat 'car close-open-tags "\n") + ;; Put the table in an indented section. + (let* ((table (org-odt--table table contents info)) + (level (/ (length (mapcar 'car close-open-tags)) 2)) + (style (format "OrgIndentedSection-Level-%d" level))) + (when table (org-odt-format-section table style))) + ;; Continue the list. + (mapconcat 'cdr (nreverse close-open-tags) "\n")))) + + +;;;; Target + +(defun org-odt-target (target contents info) + "Transcode a TARGET object from Org to ODT. +CONTENTS is nil. INFO is a plist holding contextual +information." + (let ((value (org-element-property :value target))) + (org-odt--target "" (org-export-solidify-link-text value)))) + + +;;;; Timestamp + +(defun org-odt-timestamp (timestamp contents info) + "Transcode a TIMESTAMP object from Org to ODT. +CONTENTS is nil. INFO is a plist used as a communication +channel." + (let* ((raw-value (org-element-property :raw-value timestamp)) + (type (org-element-property :type timestamp))) + (if (not org-odt-use-date-fields) + (let ((value (org-odt-plain-text + (org-timestamp-translate timestamp) info))) + (case (org-element-property :type timestamp) + ((active active-range) + (format "%s" + "OrgActiveTimestamp" value)) + ((inactive inactive-range) + (format "%s" + "OrgInactiveTimestamp" value)) + (otherwise value))) + (case type + (active + (format "%s" + "OrgActiveTimestamp" + (format "<%s>" (org-odt--format-timestamp timestamp)))) + (inactive + (format "%s" + "OrgInactiveTimestamp" + (format "[%s]" (org-odt--format-timestamp timestamp)))) + (active-range + (format "%s" + "OrgActiveTimestamp" + (format "<%s>–<%s>" + (org-odt--format-timestamp timestamp) + (org-odt--format-timestamp timestamp 'end)))) + (inactive-range + (format "%s" + "OrgInactiveTimestamp" + (format "[%s]–[%s]" + (org-odt--format-timestamp timestamp) + (org-odt--format-timestamp timestamp 'end)))) + (otherwise + (format "%s" + "OrgDiaryTimestamp" + (org-odt-plain-text (org-timestamp-translate timestamp) + info))))))) + + +;;;; Underline + +(defun org-odt-underline (underline contents info) + "Transcode UNDERLINE from Org to ODT. +CONTENTS is the text with underline markup. INFO is a plist +holding contextual information." + (format "%s" + "Underline" contents)) + + +;;;; Verbatim + +(defun org-odt-verbatim (verbatim contents info) + "Transcode a VERBATIM object from Org to ODT. +CONTENTS is nil. INFO is a plist used as a communication +channel." + (format "%s" + "OrgCode" (org-odt--encode-plain-text + (org-element-property :value verbatim)))) + + +;;;; Verse Block + +(defun org-odt-verse-block (verse-block contents info) + "Transcode a VERSE-BLOCK element from Org to ODT. +CONTENTS is verse block contents. INFO is a plist holding +contextual information." + ;; Add line breaks to each line of verse. + (setq contents (replace-regexp-in-string + "\\(\\)?[ \t]*\n" + "" contents)) + ;; Replace tabs and spaces. + (setq contents (org-odt--encode-tabs-and-spaces contents)) + ;; Surround it in a verse environment. + (format "\n%s" + "OrgVerse" contents)) + + + +;;; Filters + +;;;; LaTeX fragments + +(defun org-odt--translate-latex-fragments (tree backend info) + (let ((processing-type (plist-get info :with-latex)) + (count 0)) + ;; Normalize processing-type to one of dvipng, mathml or verbatim. + ;; If the desired converter is not available, force verbatim + ;; processing. + (case processing-type + ((t mathml) + (if (and (fboundp 'org-format-latex-mathml-available-p) + (org-format-latex-mathml-available-p)) + (setq processing-type 'mathml) + (message "LaTeX to MathML converter not available.") + (setq processing-type 'verbatim))) + ((dvipng imagemagick) + (unless (and (org-check-external-command "latex" "" t) + (org-check-external-command + (if (eq processing-type 'dvipng) "dvipng" "convert") "" t)) + (message "LaTeX to PNG converter not available.") + (setq processing-type 'verbatim))) + (otherwise + (message "Unknown LaTeX option. Forcing verbatim.") + (setq processing-type 'verbatim))) + + ;; Store normalized value for later use. + (when (plist-get info :with-latex) + (plist-put info :with-latex processing-type)) + (message "Formatting LaTeX using %s" processing-type) + + ;; Convert `latex-fragment's and `latex-environment's. + (when (memq processing-type '(mathml dvipng imagemagick)) + (org-element-map tree '(latex-fragment latex-environment) + (lambda (latex-*) + (incf count) + (let* ((latex-frag (org-element-property :value latex-*)) + (input-file (plist-get info :input-file)) + (cache-dir (file-name-directory input-file)) + (cache-subdir (concat + (case processing-type + ((dvipng imagemagick) "ltxpng/") + (mathml "ltxmathml/")) + (file-name-sans-extension + (file-name-nondirectory input-file)))) + (display-msg + (case processing-type + ((dvipng imagemagick) (format "Creating LaTeX Image %d..." count)) + (mathml (format "Creating MathML snippet %d..." count)))) + ;; Get an Org-style link to PNG image or the MathML + ;; file. + (org-link + (let ((link (with-temp-buffer + (insert latex-frag) + (org-format-latex cache-subdir cache-dir + nil display-msg + nil nil processing-type) + (buffer-substring-no-properties + (point-min) (point-max))))) + (if (not (string-match "file:\\([^]]*\\)" link)) + (prog1 nil (message "LaTeX Conversion failed.")) + link)))) + (when org-link + ;; Conversion succeeded. Parse above Org-style link to a + ;; `link' object. + (let* ((link (car (org-element-map (with-temp-buffer + (org-mode) + (insert org-link) + (org-element-parse-buffer)) + 'link 'identity)))) + ;; Orphan the link. + (org-element-put-property link :parent nil) + (let* ( + (replacement + (case (org-element-type latex-*) + ;; Case 1: LaTeX environment. + ;; Mimic a "standalone image or formula" by + ;; enclosing the `link' in a `paragraph'. + ;; Copy over original attributes, captions to + ;; the enclosing paragraph. + (latex-environment + (org-element-adopt-elements + (list 'paragraph + (list :style "OrgFormula" + :name (org-element-property :name + latex-*) + :caption (org-element-property :caption + latex-*))) + link)) + ;; Case 2: LaTeX fragment. + ;; No special action. + (latex-fragment link)))) + ;; Note down the object that link replaces. + (org-element-put-property replacement :replaces + (list (org-element-type latex-*) + (list :value latex-frag))) + ;; Replace now. + (org-element-set-element latex-* replacement)))))) + info))) + tree) + + +;;;; Description lists + +;; This translator is necessary to handle indented tables in a uniform +;; manner. See comment in `org-odt--table'. + +(defun org-odt--translate-description-lists (tree backend info) + ;; OpenDocument has no notion of a description list. So simulate it + ;; using plain lists. Description lists in the exported document + ;; are typeset in the same manner as they are in a typical HTML + ;; document. + ;; + ;; Specifically, a description list like this: + ;; + ;; ,---- + ;; | - term-1 :: definition-1 + ;; | - term-2 :: definition-2 + ;; `---- + ;; + ;; gets translated in to the following form: + ;; + ;; ,---- + ;; | - term-1 + ;; | - definition-1 + ;; | - term-2 + ;; | - definition-2 + ;; `---- + ;; + ;; Further effect is achieved by fixing the OD styles as below: + ;; + ;; 1. Set the :type property of the simulated lists to + ;; `descriptive-1' and `descriptive-2'. Map these to list-styles + ;; that has *no* bullets whatsoever. + ;; + ;; 2. The paragraph containing the definition term is styled to be + ;; in bold. + ;; + (org-element-map tree 'plain-list + (lambda (el) + (when (equal (org-element-property :type el) 'descriptive) + (org-element-set-element + el + (apply 'org-element-adopt-elements + (list 'plain-list (list :type 'descriptive-1)) + (mapcar + (lambda (item) + (org-element-adopt-elements + (list 'item (list :checkbox (org-element-property + :checkbox item))) + (list 'paragraph (list :style "Text_20_body_20_bold") + (or (org-element-property :tag item) "(no term)")) + (org-element-adopt-elements + (list 'plain-list (list :type 'descriptive-2)) + (apply 'org-element-adopt-elements + (list 'item nil) + (org-element-contents item))))) + (org-element-contents el))))) + nil) + info) + tree) + +;;;; List tables + +;; Lists that are marked with attribute `:list-table' are called as +;; list tables. They will be rendered as a table within the exported +;; document. + +;; Consider an example. The following list table +;; +;; #+attr_odt :list-table t +;; - Row 1 +;; - 1.1 +;; - 1.2 +;; - 1.3 +;; - Row 2 +;; - 2.1 +;; - 2.2 +;; - 2.3 +;; +;; will be exported as though it were an Org table like the one show +;; below. +;; +;; | Row 1 | 1.1 | 1.2 | 1.3 | +;; | Row 2 | 2.1 | 2.2 | 2.3 | +;; +;; Note that org-tables are NOT multi-line and each line is mapped to +;; a unique row in the exported document. So if an exported table +;; needs to contain a single paragraph (with copious text) it needs to +;; be typed up in a single line. Editing such long lines using the +;; table editor will be a cumbersome task. Furthermore inclusion of +;; multi-paragraph text in a table cell is well-nigh impossible. +;; +;; A LIST-TABLE circumvents above problems. +;; +;; Note that in the example above the list items could be paragraphs +;; themselves and the list can be arbitrarily deep. +;; +;; Inspired by following thread: +;; https://lists.gnu.org/archive/html/emacs-orgmode/2011-03/msg01101.html + +;; Translate lists to tables + +(defun org-odt--translate-list-tables (tree backend info) + (org-element-map tree 'plain-list + (lambda (l1-list) + (when (org-export-read-attribute :attr_odt l1-list :list-table) + ;; Replace list with table. + (org-element-set-element + l1-list + ;; Build replacement table. + (apply 'org-element-adopt-elements + (list 'table '(:type org :attr_odt (":style \"GriddedTable\""))) + (org-element-map l1-list 'item + (lambda (l1-item) + (let* ((l1-item-contents (org-element-contents l1-item)) + l1-item-leading-text l2-list) + ;; Remove Level-2 list from the Level-item. It + ;; will be subsequently attached as table-cells. + (let ((cur l1-item-contents) prev) + (while (and cur (not (eq (org-element-type (car cur)) + 'plain-list))) + (setq prev cur) + (setq cur (cdr cur))) + (when prev + (setcdr prev nil) + (setq l2-list (car cur))) + (setq l1-item-leading-text l1-item-contents)) + ;; Level-1 items start a table row. + (apply 'org-element-adopt-elements + (list 'table-row (list :type 'standard)) + ;; Leading text of level-1 item define + ;; the first table-cell. + (apply 'org-element-adopt-elements + (list 'table-cell nil) + l1-item-leading-text) + ;; Level-2 items define subsequent + ;; table-cells of the row. + (org-element-map l2-list 'item + (lambda (l2-item) + (apply 'org-element-adopt-elements + (list 'table-cell nil) + (org-element-contents l2-item))) + info nil 'item)))) + info nil 'item)))) + nil) + info) + tree) + + +;;; Interactive functions + +(defun org-odt-create-manifest-file-entry (&rest args) + (push args org-odt-manifest-file-entries)) + +(defun org-odt-write-manifest-file () + (make-directory (concat org-odt-zip-dir "META-INF")) + (let ((manifest-file (concat org-odt-zip-dir "META-INF/manifest.xml"))) + (with-current-buffer + (let ((nxml-auto-insert-xml-declaration-flag nil)) + (find-file-noselect manifest-file t)) + (insert + " + \n") + (mapc + (lambda (file-entry) + (let* ((version (nth 2 file-entry)) + (extra (if (not version) "" + (format " manifest:version=\"%s\"" version)))) + (insert + (format org-odt-manifest-file-entry-tag + (nth 0 file-entry) (nth 1 file-entry) extra)))) + org-odt-manifest-file-entries) + (insert "\n")))) + +(defmacro org-odt--export-wrap (out-file &rest body) + `(let* ((--out-file ,out-file) + (out-file-type (file-name-extension --out-file)) + (org-odt-xml-files '("META-INF/manifest.xml" "content.xml" + "meta.xml" "styles.xml")) + ;; Initialize temporary workarea. All files that end up in + ;; the exported document get parked/created here. + (org-odt-zip-dir (file-name-as-directory + (make-temp-file (format "%s-" out-file-type) t))) + (org-odt-manifest-file-entries nil) + (--cleanup-xml-buffers + (function + (lambda nil + ;; Kill all XML buffers. + (mapc (lambda (file) + (let ((buf (find-buffer-visiting + (concat org-odt-zip-dir file)))) + (when buf + (with-current-buffer buf + (set-buffer-modified-p nil) + (kill-buffer buf))))) + org-odt-xml-files) + ;; Delete temporary directory and also other embedded + ;; files that get copied there. + (delete-directory org-odt-zip-dir t))))) + (condition-case err + (progn + (unless (executable-find "zip") + ;; Not at all OSes ship with zip by default + (error "Executable \"zip\" needed for creating OpenDocument files")) + ;; Do export. This creates a bunch of xml files ready to be + ;; saved and zipped. + (progn ,@body) + ;; Create a manifest entry for content.xml. + (org-odt-create-manifest-file-entry "text/xml" "content.xml") + ;; Write mimetype file + (let* ((mimetypes + '(("odt" . "application/vnd.oasis.opendocument.text") + ("odf" . "application/vnd.oasis.opendocument.formula"))) + (mimetype (cdr (assoc-string out-file-type mimetypes t)))) + (unless mimetype + (error "Unknown OpenDocument backend %S" out-file-type)) + (write-region mimetype nil (concat org-odt-zip-dir "mimetype")) + (org-odt-create-manifest-file-entry mimetype "/" "1.2")) + ;; Write out the manifest entries before zipping + (org-odt-write-manifest-file) + ;; Save all XML files. + (mapc (lambda (file) + (let ((buf (find-buffer-visiting + (concat org-odt-zip-dir file)))) + (when buf + (with-current-buffer buf + ;; Prettify output if needed. + (when org-odt-prettify-xml + (indent-region (point-min) (point-max))) + (save-buffer 0))))) + org-odt-xml-files) + ;; Run zip. + (let* ((target --out-file) + (target-name (file-name-nondirectory target)) + (cmds `(("zip" "-mX0" ,target-name "mimetype") + ("zip" "-rmTq" ,target-name ".")))) + ;; If a file with same name as the desired output file + ;; exists, remove it. + (when (file-exists-p target) + (delete-file target)) + ;; Zip up the xml files. + (let ((coding-system-for-write 'no-conversion) exitcode err-string) + (message "Creating ODT file...") + ;; Switch temporarily to content.xml. This way Zip + ;; process will inherit `org-odt-zip-dir' as the current + ;; directory. + (with-current-buffer + (find-file-noselect (concat org-odt-zip-dir "content.xml") t) + (mapc + (lambda (cmd) + (message "Running %s" (mapconcat 'identity cmd " ")) + (setq err-string + (with-output-to-string + (setq exitcode + (apply 'call-process (car cmd) + nil standard-output nil (cdr cmd))))) + (or (zerop exitcode) + (error (concat "Unable to create OpenDocument file." + (format " Zip failed with error (%s)" + err-string))))) + cmds))) + ;; Move the zip file from temporary work directory to + ;; user-mandated location. + (rename-file (concat org-odt-zip-dir target-name) target) + (message "Created %s" (expand-file-name target)) + ;; Cleanup work directory and work files. + (funcall --cleanup-xml-buffers) + ;; Open the OpenDocument file in archive-mode for + ;; examination. + (find-file-noselect target t) + ;; Return exported file. + (cond + ;; Case 1: Conversion desired on exported file. Run the + ;; converter on the OpenDocument file. Return the + ;; converted file. + (org-odt-preferred-output-format + (or (org-odt-convert target org-odt-preferred-output-format) + target)) + ;; Case 2: No further conversion. Return exported + ;; OpenDocument file. + (t target)))) + (error + ;; Cleanup work directory and work files. + (funcall --cleanup-xml-buffers) + (message "OpenDocument export failed: %s" + (error-message-string err)))))) + + +;;;; Export to OpenDocument formula + +;;;###autoload +(defun org-odt-export-as-odf (latex-frag &optional odf-file) + "Export LATEX-FRAG as OpenDocument formula file ODF-FILE. +Use `org-create-math-formula' to convert LATEX-FRAG first to +MathML. When invoked as an interactive command, use +`org-latex-regexps' to infer LATEX-FRAG from currently active +region. If no LaTeX fragments are found, prompt for it. Push +MathML source to kill ring depending on the value of +`org-export-copy-to-kill-ring'." + (interactive + `(,(let (frag) + (setq frag (and (setq frag (and (region-active-p) + (buffer-substring (region-beginning) + (region-end)))) + (loop for e in org-latex-regexps + thereis (when (string-match (nth 1 e) frag) + (match-string (nth 2 e) frag))))) + (read-string "LaTeX Fragment: " frag nil frag)) + ,(let ((odf-filename (expand-file-name + (concat + (file-name-sans-extension + (or (file-name-nondirectory buffer-file-name))) + "." "odf") + (file-name-directory buffer-file-name)))) + (read-file-name "ODF filename: " nil odf-filename nil + (file-name-nondirectory odf-filename))))) + (let ((filename (or odf-file + (expand-file-name + (concat + (file-name-sans-extension + (or (file-name-nondirectory buffer-file-name))) + "." "odf") + (file-name-directory buffer-file-name))))) + (org-odt--export-wrap + filename + (let* ((buffer (progn + (require 'nxml-mode) + (let ((nxml-auto-insert-xml-declaration-flag nil)) + (find-file-noselect (concat org-odt-zip-dir + "content.xml") t)))) + (coding-system-for-write 'utf-8) + (save-buffer-coding-system 'utf-8)) + (set-buffer buffer) + (set-buffer-file-coding-system coding-system-for-write) + (let ((mathml (org-create-math-formula latex-frag))) + (unless mathml (error "No Math formula created")) + (insert mathml) + ;; Add MathML to kill ring, if needed. + (when (org-export--copy-to-kill-ring-p) + (org-kill-new (buffer-string)))))))) + +;;;###autoload +(defun org-odt-export-as-odf-and-open () + "Export LaTeX fragment as OpenDocument formula and immediately open it. +Use `org-odt-export-as-odf' to read LaTeX fragment and OpenDocument +formula file." + (interactive) + (org-open-file (call-interactively 'org-odt-export-as-odf) 'system)) + + +;;;; Export to OpenDocument Text + +;;;###autoload +(defun org-odt-export-to-odt (&optional async subtreep visible-only ext-plist) + "Export current buffer to a ODT file. + +If narrowing is active in the current buffer, only export its +narrowed part. + +If a region is active, export that region. + +A non-nil optional argument ASYNC means the process should happen +asynchronously. The resulting file should be accessible through +the `org-export-stack' interface. + +When optional argument SUBTREEP is non-nil, export the sub-tree +at point, extracting information from the headline properties +first. + +When optional argument VISIBLE-ONLY is non-nil, don't export +contents of hidden elements. + +EXT-PLIST, when provided, is a property list with external +parameters overriding Org default settings, but still inferior to +file-local settings. + +Return output file's name." + (interactive) + (let ((outfile (org-export-output-file-name ".odt" subtreep))) + (if async + (org-export-async-start (lambda (f) (org-export-add-to-stack f 'odt)) + `(expand-file-name + (org-odt--export-wrap + ,outfile + (let* ((org-odt-embedded-images-count 0) + (org-odt-embedded-formulas-count 0) + (org-odt-automatic-styles nil) + (org-odt-object-counters nil) + ;; Let `htmlfontify' know that we are interested in + ;; collecting styles. + (hfy-user-sheet-assoc nil)) + ;; Initialize content.xml and kick-off the export + ;; process. + (let ((out-buf + (progn + (require 'nxml-mode) + (let ((nxml-auto-insert-xml-declaration-flag nil)) + (find-file-noselect + (concat org-odt-zip-dir "content.xml") t)))) + (output (org-export-as + 'odt ,subtreep ,visible-only nil ,ext-plist))) + (with-current-buffer out-buf + (erase-buffer) + (insert output))))))) + (org-odt--export-wrap + outfile + (let* ((org-odt-embedded-images-count 0) + (org-odt-embedded-formulas-count 0) + (org-odt-automatic-styles nil) + (org-odt-object-counters nil) + ;; Let `htmlfontify' know that we are interested in collecting + ;; styles. + (hfy-user-sheet-assoc nil)) + ;; Initialize content.xml and kick-off the export process. + (let ((output (org-export-as 'odt subtreep visible-only nil ext-plist)) + (out-buf (progn + (require 'nxml-mode) + (let ((nxml-auto-insert-xml-declaration-flag nil)) + (find-file-noselect + (concat org-odt-zip-dir "content.xml") t))))) + (with-current-buffer out-buf (erase-buffer) (insert output)))))))) + + +;;;; Convert between OpenDocument and other formats + +(defun org-odt-reachable-p (in-fmt out-fmt) + "Return non-nil if IN-FMT can be converted to OUT-FMT." + (catch 'done + (let ((reachable-formats (org-odt-do-reachable-formats in-fmt))) + (dolist (e reachable-formats) + (let ((out-fmt-spec (assoc out-fmt (cdr e)))) + (when out-fmt-spec + (throw 'done (cons (car e) out-fmt-spec)))))))) + +(defun org-odt-do-convert (in-file out-fmt &optional prefix-arg) + "Workhorse routine for `org-odt-convert'." + (require 'browse-url) + (let* ((in-file (expand-file-name (or in-file buffer-file-name))) + (dummy (or (file-readable-p in-file) + (error "Cannot read %s" in-file))) + (in-fmt (file-name-extension in-file)) + (out-fmt (or out-fmt (error "Output format unspecified"))) + (how (or (org-odt-reachable-p in-fmt out-fmt) + (error "Cannot convert from %s format to %s format?" + in-fmt out-fmt))) + (convert-process (car how)) + (out-file (concat (file-name-sans-extension in-file) "." + (nth 1 (or (cdr how) out-fmt)))) + (extra-options (or (nth 2 (cdr how)) "")) + (out-dir (file-name-directory in-file)) + (cmd (format-spec convert-process + `((?i . ,(shell-quote-argument in-file)) + (?I . ,(browse-url-file-url in-file)) + (?f . ,out-fmt) + (?o . ,out-file) + (?O . ,(browse-url-file-url out-file)) + (?d . , (shell-quote-argument out-dir)) + (?D . ,(browse-url-file-url out-dir)) + (?x . ,extra-options))))) + (when (file-exists-p out-file) + (delete-file out-file)) + + (message "Executing %s" cmd) + (let ((cmd-output (shell-command-to-string cmd))) + (message "%s" cmd-output)) + + (cond + ((file-exists-p out-file) + (message "Exported to %s" out-file) + (when prefix-arg + (message "Opening %s..." out-file) + (org-open-file out-file 'system)) + out-file) + (t + (message "Export to %s failed" out-file) + nil)))) + +(defun org-odt-do-reachable-formats (in-fmt) + "Return verbose info about formats to which IN-FMT can be converted. +Return a list where each element is of the +form (CONVERTER-PROCESS . OUTPUT-FMT-ALIST). See +`org-odt-convert-processes' for CONVERTER-PROCESS and see +`org-odt-convert-capabilities' for OUTPUT-FMT-ALIST." + (let* ((converter + (and org-odt-convert-process + (cadr (assoc-string org-odt-convert-process + org-odt-convert-processes t)))) + (capabilities + (and org-odt-convert-process + (cadr (assoc-string org-odt-convert-process + org-odt-convert-processes t)) + org-odt-convert-capabilities)) + reachable-formats) + (when converter + (dolist (c capabilities) + (when (member in-fmt (nth 1 c)) + (push (cons converter (nth 2 c)) reachable-formats)))) + reachable-formats)) + +(defun org-odt-reachable-formats (in-fmt) + "Return list of formats to which IN-FMT can be converted. +The list of the form (OUTPUT-FMT-1 OUTPUT-FMT-2 ...)." + (let (l) + (mapc (lambda (e) (add-to-list 'l e)) + (apply 'append (mapcar + (lambda (e) (mapcar 'car (cdr e))) + (org-odt-do-reachable-formats in-fmt)))) + l)) + +(defun org-odt-convert-read-params () + "Return IN-FILE and OUT-FMT params for `org-odt-do-convert'. +This is a helper routine for interactive use." + (let* ((input (if (featurep 'ido) 'ido-completing-read 'completing-read)) + (in-file (read-file-name "File to be converted: " + nil buffer-file-name t)) + (in-fmt (file-name-extension in-file)) + (out-fmt-choices (org-odt-reachable-formats in-fmt)) + (out-fmt + (or (and out-fmt-choices + (funcall input "Output format: " + out-fmt-choices nil nil nil)) + (error + "No known converter or no known output formats for %s files" + in-fmt)))) + (list in-file out-fmt))) + +;;;###autoload +(defun org-odt-convert (&optional in-file out-fmt prefix-arg) + "Convert IN-FILE to format OUT-FMT using a command line converter. +IN-FILE is the file to be converted. If unspecified, it defaults +to variable `buffer-file-name'. OUT-FMT is the desired output +format. Use `org-odt-convert-process' as the converter. +If PREFIX-ARG is non-nil then the newly converted file is opened +using `org-open-file'." + (interactive + (append (org-odt-convert-read-params) current-prefix-arg)) + (org-odt-do-convert in-file out-fmt prefix-arg)) + +;;; Library Initializations + +(mapc + (lambda (desc) + ;; Let Emacs open all OpenDocument files in archive mode + (add-to-list 'auto-mode-alist + (cons (concat "\\." (car desc) "\\'") 'archive-mode))) + org-odt-file-extensions) + +(provide 'ox-odt) + +;; Local variables: +;; generated-autoload-file: "org-loaddefs.el" +;; End: + +;;; ox-odt.el ends here diff --git a/lisp/org/ox-org.el b/lisp/org/ox-org.el new file mode 100644 index 00000000000..41798b3e123 --- /dev/null +++ b/lisp/org/ox-org.el @@ -0,0 +1,255 @@ +;;; ox-org.el --- Org Back-End for Org Export Engine + +;; Copyright (C) 2013 Free Software Foundation, Inc. + +;; Author: Nicolas Goaziou +;; Keywords: org, wp + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;; This library implements an Org back-end for Org exporter. +;; +;; It introduces two interactive functions, `org-org-export-as-org' +;; and `org-org-export-to-org', which export, respectively, to +;; a temporary buffer and to a file. +;; +;; A publishing function is also provided: `org-org-publish-to-org'. + +;;; Code: +(require 'ox) +(declare-function htmlize-buffer "htmlize" (&optional buffer)) + +(defgroup org-export-org nil + "Options for exporting Org mode files to Org." + :tag "Org Export Org" + :group 'org-export + :version "24.4" + :package-version '(Org . "8.0")) + +(define-obsolete-variable-alias + 'org-export-htmlized-org-css-url 'org-org-htmlized-css-url "24.4") +(defcustom org-org-htmlized-css-url nil + "URL pointing to the CSS defining colors for htmlized Emacs buffers. +Normally when creating an htmlized version of an Org buffer, +htmlize will create the CSS to define the font colors. However, +this does not work when converting in batch mode, and it also can +look bad if different people with different fontification setup +work on the same website. When this variable is non-nil, +creating an htmlized version of an Org buffer using +`org-org-export-as-org' will include a link to this URL if the +setting of `org-html-htmlize-output-type' is 'css." + :group 'org-export-org + :type '(choice + (const :tag "Don't include external stylesheet link" nil) + (string :tag "URL or local href"))) + +(org-export-define-backend 'org + '((babel-call . org-org-identity) + (bold . org-org-identity) + (center-block . org-org-identity) + (clock . org-org-identity) + (code . org-org-identity) + (comment . (lambda (&rest args) "")) + (comment-block . (lambda (&rest args) "")) + (diary-sexp . org-org-identity) + (drawer . org-org-identity) + (dynamic-block . org-org-identity) + (entity . org-org-identity) + (example-block . org-org-identity) + (fixed-width . org-org-identity) + (footnote-definition . org-org-identity) + (footnote-reference . org-org-identity) + (headline . org-org-headline) + (horizontal-rule . org-org-identity) + (inline-babel-call . org-org-identity) + (inline-src-block . org-org-identity) + (inlinetask . org-org-identity) + (italic . org-org-identity) + (item . org-org-identity) + (keyword . org-org-keyword) + (latex-environment . org-org-identity) + (latex-fragment . org-org-identity) + (line-break . org-org-identity) + (link . org-org-identity) + (node-property . org-org-identity) + (paragraph . org-org-identity) + (plain-list . org-org-identity) + (planning . org-org-identity) + (property-drawer . org-org-identity) + (quote-block . org-org-identity) + (quote-section . org-org-identity) + (radio-target . org-org-identity) + (section . org-org-identity) + (special-block . org-org-identity) + (src-block . org-org-identity) + (statistics-cookie . org-org-identity) + (strike-through . org-org-identity) + (subscript . org-org-identity) + (superscript . org-org-identity) + (table . org-org-identity) + (table-cell . org-org-identity) + (table-row . org-org-identity) + (target . org-org-identity) + (timestamp . org-org-identity) + (underline . org-org-identity) + (verbatim . org-org-identity) + (verse-block . org-org-identity)) + :menu-entry + '(?O "Export to Org" + ((?O "As Org buffer" org-org-export-as-org) + (?o "As Org file" org-org-export-to-org) + (?v "As Org file and open" + (lambda (a s v b) + (if a (org-org-export-to-org t s v b) + (org-open-file (org-org-export-to-org nil s v b)))))))) + +(defun org-org-identity (blob contents info) + "Transcode BLOB element or object back into Org syntax. +CONTENTS is its contents, as a string or nil. INFO is ignored." + (org-export-expand blob contents t)) + +(defun org-org-headline (headline contents info) + "Transcode HEADLINE element back into Org syntax. +CONTENTS is its contents, as a string or nil. INFO is ignored." + (unless (plist-get info :with-todo-keywords) + (org-element-put-property headline :todo-keyword nil)) + (unless (plist-get info :with-tags) + (org-element-put-property headline :tags nil)) + (unless (plist-get info :with-priority) + (org-element-put-property headline :priority nil)) + (org-element-put-property headline :level + (org-export-get-relative-level headline info)) + (org-element-headline-interpreter headline contents)) + +(defun org-org-keyword (keyword contents info) + "Transcode KEYWORD element back into Org syntax. +CONTENTS is nil. INFO is ignored. This function ignores +keywords targeted at other export back-ends." + (unless (member (org-element-property :key keyword) + (mapcar + (lambda (block-cons) + (and (eq (cdr block-cons) 'org-element-export-block-parser) + (car block-cons))) + org-element-block-name-alist)) + (org-element-keyword-interpreter keyword nil))) + +;;;###autoload +(defun org-org-export-as-org (&optional async subtreep visible-only ext-plist) + "Export current buffer to an Org buffer. + +If narrowing is active in the current buffer, only export its +narrowed part. + +If a region is active, export that region. + +A non-nil optional argument ASYNC means the process should happen +asynchronously. The resulting buffer should be accessible +through the `org-export-stack' interface. + +When optional argument SUBTREEP is non-nil, export the sub-tree +at point, extracting information from the headline properties +first. + +When optional argument VISIBLE-ONLY is non-nil, don't export +contents of hidden elements. + +EXT-PLIST, when provided, is a property list with external +parameters overriding Org default settings, but still inferior to +file-local settings. + +Export is done in a buffer named \"*Org ORG Export*\", which will +be displayed when `org-export-show-temporary-export-buffer' is +non-nil." + (interactive) + (org-export-to-buffer 'org "*Org ORG Export*" + async subtreep visible-only nil ext-plist (lambda () (org-mode)))) + +;;;###autoload +(defun org-org-export-to-org (&optional async subtreep visible-only ext-plist) + "Export current buffer to an org file. + +If narrowing is active in the current buffer, only export its +narrowed part. + +If a region is active, export that region. + +A non-nil optional argument ASYNC means the process should happen +asynchronously. The resulting file should be accessible through +the `org-export-stack' interface. + +When optional argument SUBTREEP is non-nil, export the sub-tree +at point, extracting information from the headline properties +first. + +When optional argument VISIBLE-ONLY is non-nil, don't export +contents of hidden elements. + +EXT-PLIST, when provided, is a property list with external +parameters overriding Org default settings, but still inferior to +file-local settings. + +Return output file name." + (interactive) + (let ((outfile (org-export-output-file-name ".org" subtreep))) + (org-export-to-file 'org outfile + async subtreep visible-only nil ext-plist))) + +;;;###autoload +(defun org-org-publish-to-org (plist filename pub-dir) + "Publish an org file to org. + +FILENAME is the filename of the Org file to be published. PLIST +is the property list for the given project. PUB-DIR is the +publishing directory. + +Return output file name." + (org-publish-org-to 'org filename ".org" plist pub-dir) + (when (plist-get plist :htmlized-source) + (require 'htmlize) + (require 'ox-html) + (let* ((org-inhibit-startup t) + (htmlize-output-type 'css) + (html-ext (concat "." (or (plist-get plist :html-extension) + org-html-extension "html"))) + (visitingp (find-buffer-visiting filename)) + (work-buffer (or visitingp (find-file filename))) + newbuf) + (font-lock-fontify-buffer) + (show-all) + (org-show-block-all) + (setq newbuf (htmlize-buffer)) + (with-current-buffer newbuf + (when org-org-htmlized-css-url + (goto-char (point-min)) + (and (re-search-forward + ".*" nil t) + (replace-match + (format + "" + org-org-htmlized-css-url) t t))) + (write-file (concat pub-dir (file-name-nondirectory filename) html-ext))) + (kill-buffer newbuf) + (unless visitingp (kill-buffer work-buffer))) + (set-buffer-modified-p nil))) + + +(provide 'ox-org) + +;; Local variables: +;; generated-autoload-file: "org-loaddefs.el" +;; End: + +;;; ox-org.el ends here diff --git a/lisp/org/ox-publish.el b/lisp/org/ox-publish.el new file mode 100644 index 00000000000..67a57fa38ff --- /dev/null +++ b/lisp/org/ox-publish.el @@ -0,0 +1,1238 @@ +;;; ox-publish.el --- Publish Related Org Mode Files as a Website +;; Copyright (C) 2006-2013 Free Software Foundation, Inc. + +;; Author: David O'Toole +;; Maintainer: Carsten Dominik +;; Keywords: hypermedia, outlines, wp + +;; This file is part of GNU Emacs. +;; +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;; This program allow configurable publishing of related sets of +;; Org mode files as a complete website. +;; +;; ox-publish.el can do the following: +;; +;; + Publish all one's Org files to a given export back-end +;; + Upload HTML, images, attachments and other files to a web server +;; + Exclude selected private pages from publishing +;; + Publish a clickable sitemap of pages +;; + Manage local timestamps for publishing only changed files +;; + Accept plugin functions to extend range of publishable content +;; +;; Documentation for publishing is in the manual. + +;;; Code: + +(eval-when-compile (require 'cl)) +(require 'format-spec) +(require 'ox) + + + +;;; Variables + +(defvar org-publish-temp-files nil + "Temporary list of files to be published.") + +;; Here, so you find the variable right before it's used the first time: +(defvar org-publish-cache nil + "This will cache timestamps and titles for files in publishing projects. +Blocks could hash sha1 values here.") + +(defgroup org-publish nil + "Options for publishing a set of Org-mode and related files." + :tag "Org Publishing" + :group 'org) + +(defcustom org-publish-project-alist nil + "Association list to control publishing behavior. +Each element of the alist is a publishing 'project.' The CAR of +each element is a string, uniquely identifying the project. The +CDR of each element is in one of the following forms: + +1. A well-formed property list with an even number of elements, + alternating keys and values, specifying parameters for the + publishing process. + + \(:property value :property value ... ) + +2. A meta-project definition, specifying of a list of + sub-projects: + + \(:components (\"project-1\" \"project-2\" ...)) + +When the CDR of an element of org-publish-project-alist is in +this second form, the elements of the list after `:components' +are taken to be components of the project, which group together +files requiring different publishing options. When you publish +such a project with \\[org-publish], the components all publish. + +When a property is given a value in `org-publish-project-alist', +its setting overrides the value of the corresponding user +variable (if any) during publishing. However, options set within +a file override everything. + +Most properties are optional, but some should always be set: + + `:base-directory' + + Directory containing publishing source files. + + `:base-extension' + + Extension (without the dot!) of source files. This can be + a regular expression. If not given, \"org\" will be used as + default extension. + + `:publishing-directory' + + Directory (possibly remote) where output files will be + published. + +The `:exclude' property may be used to prevent certain files from +being published. Its value may be a string or regexp matching +file names you don't want to be published. + +The `:include' property may be used to include extra files. Its +value may be a list of filenames to include. The filenames are +considered relative to the base directory. + +When both `:include' and `:exclude' properties are given values, +the exclusion step happens first. + +One special property controls which back-end function to use for +publishing files in the project. This can be used to extend the +set of file types publishable by `org-publish', as well as the +set of output formats. + + `:publishing-function' + + Function to publish file. Each back-end may define its + own (i.e. `org-latex-publish-to-pdf', + `org-html-publish-to-html'). May be a list of functions, in + which case each function in the list is invoked in turn. + +Another property allows you to insert code that prepares +a project for publishing. For example, you could call GNU Make +on a certain makefile, to ensure published files are built up to +date. + + `:preparation-function' + + Function to be called before publishing this project. This + may also be a list of functions. + + `:completion-function' + + Function to be called after publishing this project. This + may also be a list of functions. + +Some properties control details of the Org publishing process, +and are equivalent to the corresponding user variables listed in +the right column. Back-end specific properties may also be +included. See the back-end documentation for more information. + + :author `user-full-name' + :creator `org-export-creator-string' + :email `user-mail-address' + :exclude-tags `org-export-exclude-tags' + :headline-levels `org-export-headline-levels' + :language `org-export-default-language' + :preserve-breaks `org-export-preserve-breaks' + :section-numbers `org-export-with-section-numbers' + :select-tags `org-export-select-tags' + :time-stamp-file `org-export-time-stamp-file' + :with-archived-trees `org-export-with-archived-trees' + :with-author `org-export-with-author' + :with-creator `org-export-with-creator' + :with-date `org-export-with-date' + :with-drawers `org-export-with-drawers' + :with-email `org-export-with-email' + :with-emphasize `org-export-with-emphasize' + :with-entities `org-export-with-entities' + :with-fixed-width `org-export-with-fixed-width' + :with-footnotes `org-export-with-footnotes' + :with-inlinetasks `org-export-with-inlinetasks' + :with-latex `org-export-with-latex' + :with-priority `org-export-with-priority' + :with-smart-quotes `org-export-with-smart-quotes' + :with-special-strings `org-export-with-special-strings' + :with-statistics-cookies' `org-export-with-statistics-cookies' + :with-sub-superscript `org-export-with-sub-superscripts' + :with-toc `org-export-with-toc' + :with-tables `org-export-with-tables' + :with-tags `org-export-with-tags' + :with-tasks `org-export-with-tasks' + :with-timestamps `org-export-with-timestamps' + :with-planning `org-export-with-planning' + :with-todo-keywords `org-export-with-todo-keywords' + +The following properties may be used to control publishing of +a site-map of files or summary page for a given project. + + `:auto-sitemap' + + Whether to publish a site-map during + `org-publish-current-project' or `org-publish-all'. + + `:sitemap-filename' + + Filename for output of sitemap. Defaults to \"sitemap.org\". + + `:sitemap-title' + + Title of site-map page. Defaults to name of file. + + `:sitemap-function' + + Plugin function to use for generation of site-map. Defaults + to `org-publish-org-sitemap', which generates a plain list of + links to all files in the project. + + `:sitemap-style' + + Can be `list' (site-map is just an itemized list of the + titles of the files involved) or `tree' (the directory + structure of the source files is reflected in the site-map). + Defaults to `tree'. + + `:sitemap-sans-extension' + + Remove extension from site-map's file-names. Useful to have + cool URIs (see http://www.w3.org/Provider/Style/URI). + Defaults to nil. + +If you create a site-map file, adjust the sorting like this: + + `:sitemap-sort-folders' + + Where folders should appear in the site-map. Set this to + `first' (default) or `last' to display folders first or last, + respectively. Any other value will mix files and folders. + + `:sitemap-sort-files' + + The site map is normally sorted alphabetically. You can + change this behaviour setting this to `anti-chronologically', + `chronologically', or nil. + + `:sitemap-ignore-case' + + Should sorting be case-sensitive? Default nil. + +The following property control the creation of a concept index. + + `:makeindex' + + Create a concept index. The file containing the index has to + be called \"theindex.org\". If it doesn't exist in the + project, it will be generated. Contents of the index are + stored in the file \"theindex.inc\", which can be included in + \"theindex.org\". + +Other properties affecting publication. + + `:body-only' + + Set this to t to publish only the body of the documents." + :group 'org-export-publish + :type 'alist) + +(defcustom org-publish-use-timestamps-flag t + "Non-nil means use timestamp checking to publish only changed files. +When nil, do no timestamp checking and always publish all files." + :group 'org-export-publish + :type 'boolean) + +(defcustom org-publish-timestamp-directory + (convert-standard-filename "~/.org-timestamps/") + "Name of directory in which to store publishing timestamps." + :group 'org-export-publish + :type 'directory) + +(defcustom org-publish-list-skipped-files t + "Non-nil means show message about files *not* published." + :group 'org-export-publish + :type 'boolean) + +(defcustom org-publish-sitemap-sort-files 'alphabetically + "Method to sort files in site-maps. +Possible values are `alphabetically', `chronologically', +`anti-chronologically' and nil. + +If `alphabetically', files will be sorted alphabetically. If +`chronologically', files will be sorted with older modification +time first. If `anti-chronologically', files will be sorted with +newer modification time first. nil won't sort files. + +You can overwrite this default per project in your +`org-publish-project-alist', using `:sitemap-sort-files'." + :group 'org-export-publish + :type 'symbol) + +(defcustom org-publish-sitemap-sort-folders 'first + "A symbol, denoting if folders are sorted first in sitemaps. +Possible values are `first', `last', and nil. +If `first', folders will be sorted before files. +If `last', folders are sorted to the end after the files. +Any other value will not mix files and folders. + +You can overwrite this default per project in your +`org-publish-project-alist', using `:sitemap-sort-folders'." + :group 'org-export-publish + :type 'symbol) + +(defcustom org-publish-sitemap-sort-ignore-case nil + "Non-nil when site-map sorting should ignore case. + +You can overwrite this default per project in your +`org-publish-project-alist', using `:sitemap-ignore-case'." + :group 'org-export-publish + :type 'boolean) + +(defcustom org-publish-sitemap-date-format "%Y-%m-%d" + "Format for printing a date in the sitemap. +See `format-time-string' for allowed formatters." + :group 'org-export-publish + :type 'string) + +(defcustom org-publish-sitemap-file-entry-format "%t" + "Format string for site-map file entry. +You could use brackets to delimit on what part the link will be. + +%t is the title. +%a is the author. +%d is the date formatted using `org-publish-sitemap-date-format'." + :group 'org-export-publish + :type 'string) + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Timestamp-related functions + +(defun org-publish-timestamp-filename (filename &optional pub-dir pub-func) + "Return path to timestamp file for filename FILENAME." + (setq filename (concat filename "::" (or pub-dir "") "::" + (format "%s" (or pub-func "")))) + (concat "X" (if (fboundp 'sha1) (sha1 filename) (md5 filename)))) + +(defun org-publish-needed-p + (filename &optional pub-dir pub-func true-pub-dir base-dir) + "Non-nil if FILENAME should be published in PUB-DIR using PUB-FUNC. +TRUE-PUB-DIR is where the file will truly end up. Currently we +are not using this - maybe it can eventually be used to check if +the file is present at the target location, and how old it is. +Right now we cannot do this, because we do not know under what +file name the file will be stored - the publishing function can +still decide about that independently." + (let ((rtn (if (not org-publish-use-timestamps-flag) t + (org-publish-cache-file-needs-publishing + filename pub-dir pub-func base-dir)))) + (if rtn (message "Publishing file %s using `%s'" filename pub-func) + (when org-publish-list-skipped-files + (message "Skipping unmodified file %s" filename))) + rtn)) + +(defun org-publish-update-timestamp + (filename &optional pub-dir pub-func base-dir) + "Update publishing timestamp for file FILENAME. +If there is no timestamp, create one." + (let ((key (org-publish-timestamp-filename filename pub-dir pub-func)) + (stamp (org-publish-cache-ctime-of-src filename))) + (org-publish-cache-set key stamp))) + +(defun org-publish-remove-all-timestamps () + "Remove all files in the timestamp directory." + (let ((dir org-publish-timestamp-directory) + files) + (when (and (file-exists-p dir) (file-directory-p dir)) + (mapc 'delete-file (directory-files dir 'full "[^.]\\'")) + (org-publish-reset-cache)))) + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Getting project information out of `org-publish-project-alist' + +(defun org-publish-expand-projects (projects-alist) + "Expand projects in PROJECTS-ALIST. +This splices all the components into the list." + (let ((rest projects-alist) rtn p components) + (while (setq p (pop rest)) + (if (setq components (plist-get (cdr p) :components)) + (setq rest (append + (mapcar (lambda (x) (assoc x org-publish-project-alist)) + components) + rest)) + (push p rtn))) + (nreverse (delete-dups (delq nil rtn))))) + +(defvar org-publish-sitemap-sort-files) +(defvar org-publish-sitemap-sort-folders) +(defvar org-publish-sitemap-ignore-case) +(defvar org-publish-sitemap-requested) +(defvar org-publish-sitemap-date-format) +(defvar org-publish-sitemap-file-entry-format) +(defun org-publish-compare-directory-files (a b) + "Predicate for `sort', that sorts folders and files for sitemap." + (let ((retval t)) + (when (or org-publish-sitemap-sort-files org-publish-sitemap-sort-folders) + ;; First we sort files: + (when org-publish-sitemap-sort-files + (case org-publish-sitemap-sort-files + (alphabetically + (let* ((adir (file-directory-p a)) + (aorg (and (string-match "\\.org$" a) (not adir))) + (bdir (file-directory-p b)) + (borg (and (string-match "\\.org$" b) (not bdir))) + (A (if aorg (concat (file-name-directory a) + (org-publish-find-title a)) a)) + (B (if borg (concat (file-name-directory b) + (org-publish-find-title b)) b))) + (setq retval (if org-publish-sitemap-ignore-case + (not (string-lessp (upcase B) (upcase A))) + (not (string-lessp B A)))))) + ((anti-chronologically chronologically) + (let* ((adate (org-publish-find-date a)) + (bdate (org-publish-find-date b)) + (A (+ (lsh (car adate) 16) (cadr adate))) + (B (+ (lsh (car bdate) 16) (cadr bdate)))) + (setq retval + (if (eq org-publish-sitemap-sort-files 'chronologically) (<= A B) + (>= A B))))))) + ;; Directory-wise wins: + (when org-publish-sitemap-sort-folders + ;; a is directory, b not: + (cond + ((and (file-directory-p a) (not (file-directory-p b))) + (setq retval (equal org-publish-sitemap-sort-folders 'first))) + ;; a is not a directory, but b is: + ((and (not (file-directory-p a)) (file-directory-p b)) + (setq retval (equal org-publish-sitemap-sort-folders 'last)))))) + retval)) + +(defun org-publish-get-base-files-1 + (base-dir &optional recurse match skip-file skip-dir) + "Set `org-publish-temp-files' with files from BASE-DIR directory. +If RECURSE is non-nil, check BASE-DIR recursively. If MATCH is +non-nil, restrict this list to the files matching the regexp +MATCH. If SKIP-FILE is non-nil, skip file matching the regexp +SKIP-FILE. If SKIP-DIR is non-nil, don't check directories +matching the regexp SKIP-DIR when recursing through BASE-DIR." + (mapc (lambda (f) + (let ((fd-p (file-directory-p f)) + (fnd (file-name-nondirectory f))) + (if (and fd-p recurse + (not (string-match "^\\.+$" fnd)) + (if skip-dir (not (string-match skip-dir fnd)) t)) + (org-publish-get-base-files-1 + f recurse match skip-file skip-dir) + (unless (or fd-p ;; this is a directory + (and skip-file (string-match skip-file fnd)) + (not (file-exists-p (file-truename f))) + (not (string-match match fnd))) + + (pushnew f org-publish-temp-files))))) + (let ((all-files (if (not recurse) (directory-files base-dir t match) + ;; If RECURSE is non-nil, we want all files + ;; matching MATCH and sub-directories. + (org-remove-if-not + (lambda (file) + (or (file-directory-p file) + (and match (string-match match file)))) + (directory-files base-dir t))))) + (if (not org-publish-sitemap-requested) all-files + (sort all-files 'org-publish-compare-directory-files))))) + +(defun org-publish-get-base-files (project &optional exclude-regexp) + "Return a list of all files in PROJECT. +If EXCLUDE-REGEXP is set, this will be used to filter out +matching filenames." + (let* ((project-plist (cdr project)) + (base-dir (file-name-as-directory + (plist-get project-plist :base-directory))) + (include-list (plist-get project-plist :include)) + (recurse (plist-get project-plist :recursive)) + (extension (or (plist-get project-plist :base-extension) "org")) + ;; sitemap-... variables are dynamically scoped for + ;; org-publish-compare-directory-files: + (org-publish-sitemap-requested + (plist-get project-plist :auto-sitemap)) + (sitemap-filename + (or (plist-get project-plist :sitemap-filename) "sitemap.org")) + (org-publish-sitemap-sort-folders + (if (plist-member project-plist :sitemap-sort-folders) + (plist-get project-plist :sitemap-sort-folders) + org-publish-sitemap-sort-folders)) + (org-publish-sitemap-sort-files + (cond ((plist-member project-plist :sitemap-sort-files) + (plist-get project-plist :sitemap-sort-files)) + ;; For backward compatibility: + ((plist-member project-plist :sitemap-alphabetically) + (if (plist-get project-plist :sitemap-alphabetically) + 'alphabetically nil)) + (t org-publish-sitemap-sort-files))) + (org-publish-sitemap-ignore-case + (if (plist-member project-plist :sitemap-ignore-case) + (plist-get project-plist :sitemap-ignore-case) + org-publish-sitemap-sort-ignore-case)) + (match (if (eq extension 'any) "^[^\\.]" + (concat "^[^\\.].*\\.\\(" extension "\\)$")))) + ;; Make sure `org-publish-sitemap-sort-folders' has an accepted + ;; value. + (unless (memq org-publish-sitemap-sort-folders '(first last)) + (setq org-publish-sitemap-sort-folders nil)) + + (setq org-publish-temp-files nil) + (if org-publish-sitemap-requested + (pushnew (expand-file-name (concat base-dir sitemap-filename)) + org-publish-temp-files)) + (org-publish-get-base-files-1 base-dir recurse match + ;; FIXME distinguish exclude regexp + ;; for skip-file and skip-dir? + exclude-regexp exclude-regexp) + (mapc (lambda (f) + (pushnew + (expand-file-name (concat base-dir f)) + org-publish-temp-files)) + include-list) + org-publish-temp-files)) + +(defun org-publish-get-project-from-filename (filename &optional up) + "Return the project that FILENAME belongs to." + (let* ((filename (expand-file-name filename)) + project-name) + + (catch 'p-found + (dolist (prj org-publish-project-alist) + (unless (plist-get (cdr prj) :components) + ;; [[info:org:Selecting%20files]] shows how this is supposed to work: + (let* ((r (plist-get (cdr prj) :recursive)) + (b (expand-file-name (file-name-as-directory + (plist-get (cdr prj) :base-directory)))) + (x (or (plist-get (cdr prj) :base-extension) "org")) + (e (plist-get (cdr prj) :exclude)) + (i (plist-get (cdr prj) :include)) + (xm (concat "^" b (if r ".+" "[^/]+") "\\.\\(" x "\\)$"))) + (when + (or (and i + (member filename + (mapcar (lambda (file) + (expand-file-name file b)) + i))) + (and (not (and e (string-match e filename))) + (string-match xm filename))) + (setq project-name (car prj)) + (throw 'p-found project-name)))))) + (when up + (dolist (prj org-publish-project-alist) + (if (member project-name (plist-get (cdr prj) :components)) + (setq project-name (car prj))))) + (assoc project-name org-publish-project-alist))) + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Tools for publishing functions in back-ends + +(defun org-publish-org-to (backend filename extension plist &optional pub-dir) + "Publish an Org file to a specified back-end. + +BACKEND is a symbol representing the back-end used for +transcoding. FILENAME is the filename of the Org file to be +published. EXTENSION is the extension used for the output +string, with the leading dot. PLIST is the property list for the +given project. + +Optional argument PUB-DIR, when non-nil is the publishing +directory. + +Return output file name." + (unless (or (not pub-dir) (file-exists-p pub-dir)) (make-directory pub-dir t)) + ;; Check if a buffer visiting FILENAME is already open. + (let* ((org-inhibit-startup t) + (visitingp (find-buffer-visiting filename)) + (work-buffer (or visitingp (find-file-noselect filename)))) + (prog1 (with-current-buffer work-buffer + (let ((output-file + (org-export-output-file-name extension nil pub-dir)) + (body-p (plist-get plist :body-only))) + (org-export-to-file backend output-file + nil nil nil body-p + ;; Add `org-publish-collect-numbering' and + ;; `org-publish-collect-index' to final output + ;; filters. The latter isn't dependent on + ;; `:makeindex', since we want to keep it up-to-date + ;; in cache anyway. + (org-combine-plists + plist + `(:filter-final-output + ,(cons 'org-publish-collect-numbering + (cons 'org-publish-collect-index + (plist-get plist :filter-final-output)))))))) + ;; Remove opened buffer in the process. + (unless visitingp (kill-buffer work-buffer))))) + +(defun org-publish-attachment (plist filename pub-dir) + "Publish a file with no transformation of any kind. + +FILENAME is the filename of the Org file to be published. PLIST +is the property list for the given project. PUB-DIR is the +publishing directory. + +Return output file name." + (unless (file-directory-p pub-dir) + (make-directory pub-dir t)) + (or (equal (expand-file-name (file-name-directory filename)) + (file-name-as-directory (expand-file-name pub-dir))) + (copy-file filename + (expand-file-name (file-name-nondirectory filename) pub-dir) + t))) + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Publishing files, sets of files, and indices + +(defun org-publish-file (filename &optional project no-cache) + "Publish file FILENAME from PROJECT. +If NO-CACHE is not nil, do not initialize org-publish-cache and +write it to disk. This is needed, since this function is used to +publish single files, when entire projects are published. +See `org-publish-projects'." + (let* ((project + (or project + (or (org-publish-get-project-from-filename filename) + (error "File %s not part of any known project" + (abbreviate-file-name filename))))) + (project-plist (cdr project)) + (ftname (expand-file-name filename)) + (publishing-function + (or (plist-get project-plist :publishing-function) + (error "No publishing function chosen"))) + (base-dir + (file-name-as-directory + (expand-file-name + (or (plist-get project-plist :base-directory) + (error "Project %s does not have :base-directory defined" + (car project)))))) + (pub-dir + (file-name-as-directory + (file-truename + (or (eval (plist-get project-plist :publishing-directory)) + (error "Project %s does not have :publishing-directory defined" + (car project)))))) + tmp-pub-dir) + + (unless no-cache (org-publish-initialize-cache (car project))) + + (setq tmp-pub-dir + (file-name-directory + (concat pub-dir + (and (string-match (regexp-quote base-dir) ftname) + (substring ftname (match-end 0)))))) + (if (listp publishing-function) + ;; allow chain of publishing functions + (mapc (lambda (f) + (when (org-publish-needed-p + filename pub-dir f tmp-pub-dir base-dir) + (funcall f project-plist filename tmp-pub-dir) + (org-publish-update-timestamp filename pub-dir f base-dir))) + publishing-function) + (when (org-publish-needed-p + filename pub-dir publishing-function tmp-pub-dir base-dir) + (funcall publishing-function project-plist filename tmp-pub-dir) + (org-publish-update-timestamp + filename pub-dir publishing-function base-dir))) + (unless no-cache (org-publish-write-cache-file)))) + +(defun org-publish-projects (projects) + "Publish all files belonging to the PROJECTS alist. +If `:auto-sitemap' is set, publish the sitemap too. If +`:makeindex' is set, also produce a file theindex.org." + (mapc + (lambda (project) + ;; Each project uses its own cache file: + (org-publish-initialize-cache (car project)) + (let* ((project-plist (cdr project)) + (exclude-regexp (plist-get project-plist :exclude)) + (sitemap-p (plist-get project-plist :auto-sitemap)) + (sitemap-filename (or (plist-get project-plist :sitemap-filename) + "sitemap.org")) + (sitemap-function (or (plist-get project-plist :sitemap-function) + 'org-publish-org-sitemap)) + (org-publish-sitemap-date-format + (or (plist-get project-plist :sitemap-date-format) + org-publish-sitemap-date-format)) + (org-publish-sitemap-file-entry-format + (or (plist-get project-plist :sitemap-file-entry-format) + org-publish-sitemap-file-entry-format)) + (preparation-function + (plist-get project-plist :preparation-function)) + (completion-function (plist-get project-plist :completion-function)) + (files (org-publish-get-base-files project exclude-regexp)) + (theindex + (expand-file-name "theindex.org" + (plist-get project-plist :base-directory)))) + (when preparation-function (run-hooks 'preparation-function)) + (if sitemap-p (funcall sitemap-function project sitemap-filename)) + ;; Publish all files from PROJECT excepted "theindex.org". Its + ;; publishing will be deferred until "theindex.inc" is + ;; populated. + (dolist (file files) + (unless (equal file theindex) + (org-publish-file file project t))) + ;; Populate "theindex.inc", if needed, and publish + ;; "theindex.org". + (when (plist-get project-plist :makeindex) + (org-publish-index-generate-theindex + project (plist-get project-plist :base-directory)) + (org-publish-file theindex project t)) + (when completion-function (run-hooks 'completion-function)) + (org-publish-write-cache-file))) + (org-publish-expand-projects projects))) + +(defun org-publish-org-sitemap (project &optional sitemap-filename) + "Create a sitemap of pages in set defined by PROJECT. +Optionally set the filename of the sitemap with SITEMAP-FILENAME. +Default for SITEMAP-FILENAME is 'sitemap.org'." + (let* ((project-plist (cdr project)) + (dir (file-name-as-directory + (plist-get project-plist :base-directory))) + (localdir (file-name-directory dir)) + (indent-str (make-string 2 ?\ )) + (exclude-regexp (plist-get project-plist :exclude)) + (files (nreverse + (org-publish-get-base-files project exclude-regexp))) + (sitemap-filename (concat dir (or sitemap-filename "sitemap.org"))) + (sitemap-title (or (plist-get project-plist :sitemap-title) + (concat "Sitemap for project " (car project)))) + (sitemap-style (or (plist-get project-plist :sitemap-style) + 'tree)) + (sitemap-sans-extension + (plist-get project-plist :sitemap-sans-extension)) + (visiting (find-buffer-visiting sitemap-filename)) + (ifn (file-name-nondirectory sitemap-filename)) + file sitemap-buffer) + (with-current-buffer + (let ((org-inhibit-startup t)) + (setq sitemap-buffer + (or visiting (find-file sitemap-filename)))) + (erase-buffer) + (insert (concat "#+TITLE: " sitemap-title "\n\n")) + (while (setq file (pop files)) + (let ((fn (file-name-nondirectory file)) + (link (file-relative-name file dir)) + (oldlocal localdir)) + (when sitemap-sans-extension + (setq link (file-name-sans-extension link))) + ;; sitemap shouldn't list itself + (unless (equal (file-truename sitemap-filename) + (file-truename file)) + (if (eq sitemap-style 'list) + (message "Generating list-style sitemap for %s" sitemap-title) + (message "Generating tree-style sitemap for %s" sitemap-title) + (setq localdir (concat (file-name-as-directory dir) + (file-name-directory link))) + (unless (string= localdir oldlocal) + (if (string= localdir dir) + (setq indent-str (make-string 2 ?\ )) + (let ((subdirs + (split-string + (directory-file-name + (file-name-directory + (file-relative-name localdir dir))) "/")) + (subdir "") + (old-subdirs (split-string + (file-relative-name oldlocal dir) "/"))) + (setq indent-str (make-string 2 ?\ )) + (while (string= (car old-subdirs) (car subdirs)) + (setq indent-str (concat indent-str (make-string 2 ?\ ))) + (pop old-subdirs) + (pop subdirs)) + (dolist (d subdirs) + (setq subdir (concat subdir d "/")) + (insert (concat indent-str " + " d "\n")) + (setq indent-str (make-string + (+ (length indent-str) 2) ?\ ))))))) + ;; This is common to 'flat and 'tree + (let ((entry + (org-publish-format-file-entry + org-publish-sitemap-file-entry-format file project-plist)) + (regexp "\\(.*\\)\\[\\([^][]+\\)\\]\\(.*\\)")) + (cond ((string-match-p regexp entry) + (string-match regexp entry) + (insert (concat indent-str " + " (match-string 1 entry) + "[[file:" link "][" + (match-string 2 entry) + "]]" (match-string 3 entry) "\n"))) + (t + (insert (concat indent-str " + [[file:" link "][" + entry + "]]\n")))))))) + (save-buffer)) + (or visiting (kill-buffer sitemap-buffer)))) + +(defun org-publish-format-file-entry (fmt file project-plist) + (format-spec + fmt + `((?t . ,(org-publish-find-title file t)) + (?d . ,(format-time-string org-publish-sitemap-date-format + (org-publish-find-date file))) + (?a . ,(or (plist-get project-plist :author) user-full-name))))) + +(defun org-publish-find-title (file &optional reset) + "Find the title of FILE in project." + (or + (and (not reset) (org-publish-cache-get-file-property file :title nil t)) + (let* ((org-inhibit-startup t) + (visiting (find-buffer-visiting file)) + (buffer (or visiting (find-file-noselect file)))) + (with-current-buffer buffer + (org-mode) + (let ((title + (let ((property (plist-get (org-export-get-environment) :title))) + (if property (org-element-interpret-data property) + (file-name-nondirectory (file-name-sans-extension file)))))) + (unless visiting (kill-buffer buffer)) + (org-publish-cache-set-file-property file :title title) + title))))) + +(defun org-publish-find-date (file) + "Find the date of FILE in project. +This function assumes FILE is either a directory or an Org file. +If FILE is an Org file and provides a DATE keyword use it. In +any other case use the file system's modification time. Return +time in `current-time' format." + (if (file-directory-p file) (nth 5 (file-attributes file)) + (let* ((visiting (find-buffer-visiting file)) + (file-buf (or visiting (find-file-noselect file nil))) + (date (plist-get + (with-current-buffer file-buf + (let ((org-inhibit-startup t)) (org-mode)) + (org-export-get-environment)) + :date))) + (unless visiting (kill-buffer file-buf)) + ;; DATE is either a timestamp object or a secondary string. If it + ;; is a timestamp or if the secondary string contains a timestamp, + ;; convert it to internal format. Otherwise, use FILE + ;; modification time. + (cond ((eq (org-element-type date) 'timestamp) + (org-time-string-to-time (org-element-interpret-data date))) + ((let ((ts (and (consp date) (assq 'timestamp date)))) + (and ts + (let ((value (org-element-interpret-data ts))) + (and (org-string-nw-p value) + (org-time-string-to-time value)))))) + ((file-exists-p file) (nth 5 (file-attributes file))) + (t (error "No such file: \"%s\"" file)))))) + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Interactive publishing functions + +;;;###autoload +(defalias 'org-publish-project 'org-publish) + +;;;###autoload +(defun org-publish (project &optional force async) + "Publish PROJECT. + +PROJECT is either a project name, as a string, or a project +alist (see `org-publish-project-alist' variable). + +When optional argument FORCE is non-nil, force publishing all +files in PROJECT. With a non-nil optional argument ASYNC, +publishing will be done asynchronously, in another process." + (interactive + (list + (assoc (org-icompleting-read + "Publish project: " + org-publish-project-alist nil t) + org-publish-project-alist) + current-prefix-arg)) + (let ((project-alist (if (not (stringp project)) (list project) + ;; If this function is called in batch mode, + ;; project is still a string here. + (list (assoc project org-publish-project-alist))))) + (if async + (org-export-async-start 'ignore + `(let ((org-publish-use-timestamps-flag + (if ',force nil ,org-publish-use-timestamps-flag))) + (org-publish-projects ',project-alist))) + (save-window-excursion + (let* ((org-publish-use-timestamps-flag + (if force nil org-publish-use-timestamps-flag))) + (org-publish-projects project-alist)))))) + +;;;###autoload +(defun org-publish-all (&optional force async) + "Publish all projects. +With prefix argument FORCE, remove all files in the timestamp +directory and force publishing all projects. With a non-nil +optional argument ASYNC, publishing will be done asynchronously, +in another process." + (interactive "P") + (if async + (org-export-async-start 'ignore + `(progn + (when ',force (org-publish-remove-all-timestamps)) + (let ((org-publish-use-timestamps-flag + (if ',force nil ,org-publish-use-timestamps-flag))) + (org-publish-projects ',org-publish-project-alist)))) + (when force (org-publish-remove-all-timestamps)) + (save-window-excursion + (let ((org-publish-use-timestamps-flag + (if force nil org-publish-use-timestamps-flag))) + (org-publish-projects org-publish-project-alist))))) + + +;;;###autoload +(defun org-publish-current-file (&optional force async) + "Publish the current file. +With prefix argument FORCE, force publish the file. When +optional argument ASYNC is non-nil, publishing will be done +asynchronously, in another process." + (interactive "P") + (let ((file (buffer-file-name (buffer-base-buffer)))) + (if async + (org-export-async-start 'ignore + `(let ((org-publish-use-timestamps-flag + (if ',force nil ,org-publish-use-timestamps-flag))) + (org-publish-file ,file))) + (save-window-excursion + (let ((org-publish-use-timestamps-flag + (if force nil org-publish-use-timestamps-flag))) + (org-publish-file file)))))) + +;;;###autoload +(defun org-publish-current-project (&optional force async) + "Publish the project associated with the current file. +With a prefix argument, force publishing of all files in +the project." + (interactive "P") + (save-window-excursion + (let ((project (org-publish-get-project-from-filename + (buffer-file-name (buffer-base-buffer)) 'up))) + (if project (org-publish project force async) + (error "File %s is not part of any known project" + (buffer-file-name (buffer-base-buffer))))))) + + + +;;; Index generation + +(defun org-publish-collect-index (output backend info) + "Update index for a file in cache. + +OUTPUT is the output from transcoding current file. BACKEND is +the back-end that was used for transcoding. INFO is a plist +containing publishing and export options. + +The index relative to current file is stored as an alist. An +association has the following shape: (TERM FILE-NAME PARENT), +where TERM is the indexed term, as a string, FILE-NAME is the +original full path of the file where the term in encountered, and +PARENT is a reference to the headline, if any, containing the +original index keyword. When non-nil, this reference is a cons +cell. Its CAR is a symbol among `id', `custom-id' and `name' and +its CDR is a string." + (let ((file (plist-get info :input-file))) + (org-publish-cache-set-file-property + file :index + (delete-dups + (org-element-map (plist-get info :parse-tree) 'keyword + (lambda (k) + (when (equal (org-element-property :key k) "INDEX") + (let ((parent (org-export-get-parent-headline k))) + (list (org-element-property :value k) + file + (cond + ((not parent) nil) + ((let ((id (org-element-property :ID parent))) + (and id (cons 'id id)))) + ((let ((id (org-element-property :CUSTOM_ID parent))) + (and id (cons 'custom-id id)))) + (t (cons 'name + ;; Remove statistics cookie. + (replace-regexp-in-string + "\\[[0-9]+%\\]\\|\\[[0-9]+/[0-9]+\\]" "" + (org-element-property :raw-value parent))))))))) + info)))) + ;; Return output unchanged. + output) + +(defun org-publish-index-generate-theindex (project directory) + "Retrieve full index from cache and build \"theindex.org\". +PROJECT is the project the index relates to. DIRECTORY is the +publishing directory." + (let ((all-files (org-publish-get-base-files + project (plist-get (cdr project) :exclude))) + full-index) + ;; Compile full index and sort it alphabetically. + (dolist (file all-files + (setq full-index + (sort (nreverse full-index) + (lambda (a b) (string< (downcase (car a)) + (downcase (car b))))))) + (let ((index (org-publish-cache-get-file-property file :index))) + (dolist (term index) + (unless (member term full-index) (push term full-index))))) + ;; Write "theindex.inc" in DIRECTORY. + (with-temp-file (expand-file-name "theindex.inc" directory) + (let ((current-letter nil) (last-entry nil)) + (dolist (idx full-index) + (let* ((entry (org-split-string (car idx) "!")) + (letter (upcase (substring (car entry) 0 1))) + ;; Transform file into a path relative to publishing + ;; directory. + (file (file-relative-name + (nth 1 idx) + (plist-get (cdr project) :base-directory)))) + ;; Check if another letter has to be inserted. + (unless (string= letter current-letter) + (insert (format "* %s\n" letter))) + ;; Compute the first difference between last entry and + ;; current one: it tells the level at which new items + ;; should be added. + (let* ((rank (if (equal entry last-entry) (1- (length entry)) + (loop for n from 0 to (length entry) + unless (equal (nth n entry) (nth n last-entry)) + return n))) + (len (length (nthcdr rank entry)))) + ;; For each term after the first difference, create + ;; a new sub-list with the term as body. Moreover, + ;; linkify the last term. + (dotimes (n len) + (insert + (concat + (make-string (* (+ rank n) 2) ? ) " - " + (if (not (= (1- len) n)) (nth (+ rank n) entry) + ;; Last term: Link it to TARGET, if possible. + (let ((target (nth 2 idx))) + (format + "[[%s][%s]]" + ;; Destination. + (case (car target) + ('nil (format "file:%s" file)) + (id (format "id:%s" (cdr target))) + (custom-id (format "file:%s::#%s" file (cdr target))) + (otherwise (format "file:%s::*%s" file (cdr target)))) + ;; Description. + (car (last entry))))) + "\n")))) + (setq current-letter letter last-entry entry)))) + ;; Create "theindex.org", if it doesn't exist yet, and provide + ;; a default index file. + (let ((index.org (expand-file-name "theindex.org" directory))) + (unless (file-exists-p index.org) + (with-temp-file index.org + (insert "#+TITLE: Index\n\n#+INCLUDE: \"theindex.inc\"\n\n"))))))) + + + +;;; External Fuzzy Links Resolution +;; +;; This part implements tools to resolve [[file.org::*Some headline]] +;; links, where "file.org" belongs to the current project. + +(defun org-publish-collect-numbering (output backend info) + (org-publish-cache-set-file-property + (plist-get info :input-file) :numbering + (mapcar (lambda (entry) + (cons (org-split-string + (replace-regexp-in-string + "\\[[0-9]+%\\]\\|\\[[0-9]+/[0-9]+\\]" "" + (org-element-property :raw-value (car entry)))) + (cdr entry))) + (plist-get info :headline-numbering))) + ;; Return output unchanged. + output) + +(defun org-publish-resolve-external-fuzzy-link (file fuzzy) + "Return numbering for headline matching FUZZY search in FILE. + +Return value is a list of numbers, or nil. This function allows +to resolve external fuzzy links like: + + [[file.org::*fuzzy][description]" + (when org-publish-cache + (cdr (assoc (org-split-string + (if (eq (aref fuzzy 0) ?*) (substring fuzzy 1) fuzzy)) + (org-publish-cache-get-file-property + (expand-file-name file) :numbering nil t))))) + + + +;;; Caching functions + +(defun org-publish-write-cache-file (&optional free-cache) + "Write `org-publish-cache' to file. +If FREE-CACHE, empty the cache." + (unless org-publish-cache + (error "`org-publish-write-cache-file' called, but no cache present")) + + (let ((cache-file (org-publish-cache-get ":cache-file:"))) + (unless cache-file + (error "Cannot find cache-file name in `org-publish-write-cache-file'")) + (with-temp-file cache-file + (let (print-level print-length) + (insert "(setq org-publish-cache (make-hash-table :test 'equal :weakness nil :size 100))\n") + (maphash (lambda (k v) + (insert + (format (concat "(puthash %S " + (if (or (listp v) (symbolp v)) + "'" "") + "%S org-publish-cache)\n") k v))) + org-publish-cache))) + (when free-cache (org-publish-reset-cache)))) + +(defun org-publish-initialize-cache (project-name) + "Initialize the projects cache if not initialized yet and return it." + + (unless project-name + (error "Cannot initialize `org-publish-cache' without projects name in `org-publish-initialize-cache'")) + + (unless (file-exists-p org-publish-timestamp-directory) + (make-directory org-publish-timestamp-directory t)) + (unless (file-directory-p org-publish-timestamp-directory) + (error "Org publish timestamp: %s is not a directory" + org-publish-timestamp-directory)) + + (unless (and org-publish-cache + (string= (org-publish-cache-get ":project:") project-name)) + (let* ((cache-file + (concat + (expand-file-name org-publish-timestamp-directory) + project-name ".cache")) + (cexists (file-exists-p cache-file))) + + (when org-publish-cache (org-publish-reset-cache)) + + (if cexists (load-file cache-file) + (setq org-publish-cache + (make-hash-table :test 'equal :weakness nil :size 100)) + (org-publish-cache-set ":project:" project-name) + (org-publish-cache-set ":cache-file:" cache-file)) + (unless cexists (org-publish-write-cache-file nil)))) + org-publish-cache) + +(defun org-publish-reset-cache () + "Empty org-publish-cache and reset it nil." + (message "%s" "Resetting org-publish-cache") + (when (hash-table-p org-publish-cache) + (clrhash org-publish-cache)) + (setq org-publish-cache nil)) + +(defun org-publish-cache-file-needs-publishing + (filename &optional pub-dir pub-func base-dir) + "Check the timestamp of the last publishing of FILENAME. +Return non-nil if the file needs publishing. Also check if +any included files have been more recently published, so that +the file including them will be republished as well." + (unless org-publish-cache + (error + "`org-publish-cache-file-needs-publishing' called, but no cache present")) + (let* ((case-fold-search t) + (key (org-publish-timestamp-filename filename pub-dir pub-func)) + (pstamp (org-publish-cache-get key)) + (org-inhibit-startup t) + (visiting (find-buffer-visiting filename)) + included-files-ctime buf) + + (when (equal (file-name-extension filename) "org") + (setq buf (find-file (expand-file-name filename))) + (with-current-buffer buf + (goto-char (point-min)) + (while (re-search-forward + "^#\\+INCLUDE:[ \t]+\"\\([^\t\n\r\"]*\\)\"[ \t]*.*$" nil t) + (let* ((included-file (expand-file-name (match-string 1)))) + (add-to-list 'included-files-ctime + (org-publish-cache-ctime-of-src included-file) t)))) + (unless visiting (kill-buffer buf))) + (if (null pstamp) t + (let ((ctime (org-publish-cache-ctime-of-src filename))) + (or (< pstamp ctime) + (when included-files-ctime + (not (null (delq nil (mapcar (lambda(ct) (< ctime ct)) + included-files-ctime)))))))))) + +(defun org-publish-cache-set-file-property + (filename property value &optional project-name) + "Set the VALUE for a PROPERTY of file FILENAME in publishing cache to VALUE. +Use cache file of PROJECT-NAME. If the entry does not exist, it +will be created. Return VALUE." + ;; Evtl. load the requested cache file: + (if project-name (org-publish-initialize-cache project-name)) + (let ((pl (org-publish-cache-get filename))) + (if pl (progn (plist-put pl property value) value) + (org-publish-cache-get-file-property + filename property value nil project-name)))) + +(defun org-publish-cache-get-file-property + (filename property &optional default no-create project-name) + "Return the value for a PROPERTY of file FILENAME in publishing cache. +Use cache file of PROJECT-NAME. Return the value of that PROPERTY +or DEFAULT, if the value does not yet exist. If the entry will +be created, unless NO-CREATE is not nil." + ;; Evtl. load the requested cache file: + (if project-name (org-publish-initialize-cache project-name)) + (let ((pl (org-publish-cache-get filename)) retval) + (if pl + (if (plist-member pl property) + (setq retval (plist-get pl property)) + (setq retval default)) + ;; no pl yet: + (unless no-create + (org-publish-cache-set filename (list property default))) + (setq retval default)) + retval)) + +(defun org-publish-cache-get (key) + "Return the value stored in `org-publish-cache' for key KEY. +Returns nil, if no value or nil is found, or the cache does not +exist." + (unless org-publish-cache + (error "`org-publish-cache-get' called, but no cache present")) + (gethash key org-publish-cache)) + +(defun org-publish-cache-set (key value) + "Store KEY VALUE pair in `org-publish-cache'. +Returns value on success, else nil." + (unless org-publish-cache + (error "`org-publish-cache-set' called, but no cache present")) + (puthash key value org-publish-cache)) + +(defun org-publish-cache-ctime-of-src (file) + "Get the ctime of FILE as an integer." + (let ((attr (file-attributes + (expand-file-name (or (file-symlink-p file) file) + (file-name-directory file))))) + (+ (lsh (car (nth 5 attr)) 16) + (cadr (nth 5 attr))))) + + +(provide 'ox-publish) + +;; Local variables: +;; generated-autoload-file: "org-loaddefs.el" +;; End: + +;;; ox-publish.el ends here diff --git a/lisp/org/ox-texinfo.el b/lisp/org/ox-texinfo.el new file mode 100644 index 00000000000..5967978456b --- /dev/null +++ b/lisp/org/ox-texinfo.el @@ -0,0 +1,1891 @@ +;;; ox-texinfo.el --- Texinfo Back-End for Org Export Engine + +;; Copyright (C) 2012, 2013 Jonathan Leech-Pepin +;; Author: Jonathan Leech-Pepin +;; Keywords: outlines, hypermedia, calendar, wp + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: +;; +;; This library implements a Texinfo back-end for Org generic +;; exporter. +;; +;; To test it, run +;; +;; M-: (org-export-to-buffer 'texinfo "*Test Texinfo*") RET +;; +;; in an Org mode buffer then switch to the buffer to see the Texinfo +;; export. See ox.el for more details on how this exporter works. +;; + +;; It introduces nine new buffer keywords: "TEXINFO_CLASS", +;; "TEXINFO_FILENAME", "TEXINFO_HEADER", "TEXINFO_POST_HEADER", +;; "TEXINFO_DIR_CATEGORY", "TEXINFO_DIR_TITLE", "TEXINFO_DIR_DESC" +;; "SUBTITLE" and "SUBAUTHOR". + +;; +;; It introduces 1 new headline property keywords: +;; "TEXINFO_MENU_TITLE" for optional menu titles. +;; +;; To include inline code snippets (for example for generating @kbd{} +;; and @key{} commands), the following export-snippet keys are +;; accepted: +;; +;; texinfo +;; info +;; +;; You can add them for export snippets via any of the below: +;; +;; (add-to-list 'org-export-snippet-translation-alist +;; '("info" . "texinfo")) +;; + +;;; Code: + +(eval-when-compile (require 'cl)) +(require 'ox) + +(defvar orgtbl-exp-regexp) + + + +;;; Define Back-End + +(org-export-define-backend 'texinfo + '((bold . org-texinfo-bold) + (center-block . org-texinfo-center-block) + (clock . org-texinfo-clock) + (code . org-texinfo-code) + (comment . org-texinfo-comment) + (comment-block . org-texinfo-comment-block) + (drawer . org-texinfo-drawer) + (dynamic-block . org-texinfo-dynamic-block) + (entity . org-texinfo-entity) + (example-block . org-texinfo-example-block) + (export-block . org-texinfo-export-block) + (export-snippet . org-texinfo-export-snippet) + (fixed-width . org-texinfo-fixed-width) + (footnote-definition . org-texinfo-footnote-definition) + (footnote-reference . org-texinfo-footnote-reference) + (headline . org-texinfo-headline) + (inline-src-block . org-texinfo-inline-src-block) + (inlinetask . org-texinfo-inlinetask) + (italic . org-texinfo-italic) + (item . org-texinfo-item) + (keyword . org-texinfo-keyword) + (line-break . org-texinfo-line-break) + (link . org-texinfo-link) + (paragraph . org-texinfo-paragraph) + (plain-list . org-texinfo-plain-list) + (plain-text . org-texinfo-plain-text) + (planning . org-texinfo-planning) + (property-drawer . org-texinfo-property-drawer) + (quote-block . org-texinfo-quote-block) + (quote-section . org-texinfo-quote-section) + (radio-target . org-texinfo-radio-target) + (section . org-texinfo-section) + (special-block . org-texinfo-special-block) + (src-block . org-texinfo-src-block) + (statistics-cookie . org-texinfo-statistics-cookie) + (subscript . org-texinfo-subscript) + (superscript . org-texinfo-superscript) + (table . org-texinfo-table) + (table-cell . org-texinfo-table-cell) + (table-row . org-texinfo-table-row) + (target . org-texinfo-target) + (template . org-texinfo-template) + (timestamp . org-texinfo-timestamp) + (verbatim . org-texinfo-verbatim) + (verse-block . org-texinfo-verse-block)) + :export-block "TEXINFO" + :filters-alist + '((:filter-headline . org-texinfo-filter-section-blank-lines) + (:filter-section . org-texinfo-filter-section-blank-lines)) + :menu-entry + '(?i "Export to Texinfo" + ((?t "As TEXI file" org-texinfo-export-to-texinfo) + (?i "As INFO file" org-texinfo-export-to-info))) + :options-alist + '((:texinfo-filename "TEXINFO_FILENAME" nil org-texinfo-filename t) + (:texinfo-class "TEXINFO_CLASS" nil org-texinfo-default-class t) + (:texinfo-header "TEXINFO_HEADER" nil nil newline) + (:texinfo-post-header "TEXINFO_POST_HEADER" nil nil newline) + (:subtitle "SUBTITLE" nil nil newline) + (:subauthor "SUBAUTHOR" nil nil newline) + (:texinfo-dircat "TEXINFO_DIR_CATEGORY" nil nil t) + (:texinfo-dirtitle "TEXINFO_DIR_TITLE" nil nil t) + (:texinfo-dirdesc "TEXINFO_DIR_DESC" nil nil t))) + + + +;;; User Configurable Variables + +(defgroup org-export-texinfo nil + "Options for exporting Org mode files to Texinfo." + :tag "Org Export Texinfo" + :version "24.4" + :package-version '(Org . "8.0") + :group 'org-export) + +;;; Preamble + +(defcustom org-texinfo-filename nil + "Default filename for Texinfo output." + :group 'org-export-texinfo + :type '(string :tag "Export Filename")) + +(defcustom org-texinfo-coding-system nil + "Default document encoding for Texinfo output. + +If `nil' it will default to `buffer-file-coding-system'." + :group 'org-export-texinfo + :type 'coding-system) + +(defcustom org-texinfo-default-class "info" + "The default Texinfo class." + :group 'org-export-texinfo + :type '(string :tag "Texinfo class")) + +(defcustom org-texinfo-classes + '(("info" + "\\input texinfo @c -*- texinfo -*-" + ("@chapter %s" . "@unnumbered %s") + ("@section %s" . "@unnumberedsec %s") + ("@subsection %s" . "@unnumberedsubsec %s") + ("@subsubsection %s" . "@unnumberedsubsubsec %s"))) + "Alist of Texinfo classes and associated header and structure. +If #+Texinfo_CLASS is set in the buffer, use its value and the +associated information. Here is the structure of each cell: + + \(class-name + header-string + \(numbered-section . unnumbered-section\) + ...\) + +The sectioning structure +------------------------ + +The sectioning structure of the class is given by the elements +following the header string. For each sectioning level, a number +of strings is specified. A %s formatter is mandatory in each +section string and will be replaced by the title of the section. + +Instead of a list of sectioning commands, you can also specify +a function name. That function will be called with two +parameters, the \(reduced) level of the headline, and a predicate +non-nil when the headline should be numbered. It must return +a format string in which the section title will be added." + :group 'org-export-texinfo + :type '(repeat + (list (string :tag "Texinfo class") + (string :tag "Texinfo header") + (repeat :tag "Levels" :inline t + (choice + (cons :tag "Heading" + (string :tag " numbered") + (string :tag "unnumbered")) + (function :tag "Hook computing sectioning")))))) + +;;; Headline + +(defcustom org-texinfo-format-headline-function nil + "Function to format headline text. + +This function will be called with 5 arguments: +TODO the todo keyword (string or nil). +TODO-TYPE the type of todo (symbol: `todo', `done', nil) +PRIORITY the priority of the headline (integer or nil) +TEXT the main headline text (string). +TAGS the tags as a list of strings (list of strings or nil). + +The function result will be used in the section format string. + +As an example, one could set the variable to the following, in +order to reproduce the default set-up: + +\(defun org-texinfo-format-headline (todo todo-type priority text tags) + \"Default format function for a headline.\" + \(concat (when todo + \(format \"\\\\textbf{\\\\textsc{\\\\textsf{%s}}} \" todo)) + \(when priority + \(format \"\\\\framebox{\\\\#%c} \" priority)) + text + \(when tags + \(format \"\\\\hfill{}\\\\textsc{%s}\" + \(mapconcat 'identity tags \":\"))))" + :group 'org-export-texinfo + :type 'function) + +;;; Node listing (menu) + +(defcustom org-texinfo-node-description-column 32 + "Column at which to start the description in the node + listings. + +If a node title is greater than this length, the description will +be placed after the end of the title." + :group 'org-export-texinfo + :type 'integer) + +;;; Footnotes +;; +;; Footnotes are inserted directly + +;;; Timestamps + +(defcustom org-texinfo-active-timestamp-format "@emph{%s}" + "A printf format string to be applied to active timestamps." + :group 'org-export-texinfo + :type 'string) + +(defcustom org-texinfo-inactive-timestamp-format "@emph{%s}" + "A printf format string to be applied to inactive timestamps." + :group 'org-export-texinfo + :type 'string) + +(defcustom org-texinfo-diary-timestamp-format "@emph{%s}" + "A printf format string to be applied to diary timestamps." + :group 'org-export-texinfo + :type 'string) + +;;; Links + +(defcustom org-texinfo-link-with-unknown-path-format "@indicateurl{%s}" + "Format string for links with unknown path type." + :group 'org-export-texinfo + :type 'string) + +;;; Tables + +(defcustom org-texinfo-tables-verbatim nil + "When non-nil, tables are exported verbatim." + :group 'org-export-texinfo + :type 'boolean) + +(defcustom org-texinfo-table-scientific-notation "%s\\,(%s)" + "Format string to display numbers in scientific notation. +The format should have \"%s\" twice, for mantissa and exponent +\(i.e. \"%s\\\\times10^{%s}\"). + +When nil, no transformation is made." + :group 'org-export-texinfo + :type '(choice + (string :tag "Format string") + (const :tag "No formatting"))) + +(defcustom org-texinfo-def-table-markup "@samp" + "Default setting for @table environments.") + +;;; Text markup + +(defcustom org-texinfo-text-markup-alist '((bold . "@strong{%s}") + (code . code) + (italic . "@emph{%s}") + (verbatim . verb) + (comment . "@c %s")) + "Alist of Texinfo expressions to convert text markup. + +The key must be a symbol among `bold', `italic' and `comment'. +The value is a formatting string to wrap fontified text with. + +Value can also be set to the following symbols: `verb' and +`code'. For the former, Org will use \"@verb\" to +create a format string and select a delimiter character that +isn't in the string. For the latter, Org will use \"@code\" +to typeset and try to protect special characters. + +If no association can be found for a given markup, text will be +returned as-is." + :group 'org-export-texinfo + :type 'alist + :options '(bold code italic verbatim comment)) + +;;; Drawers + +(defcustom org-texinfo-format-drawer-function nil + "Function called to format a drawer in Texinfo code. + +The function must accept two parameters: + NAME the drawer name, like \"LOGBOOK\" + CONTENTS the contents of the drawer. + +The function should return the string to be exported. + +For example, the variable could be set to the following function +in order to mimic default behaviour: + +\(defun org-texinfo-format-drawer-default \(name contents\) + \"Format a drawer element for Texinfo export.\" + contents\)" + :group 'org-export-texinfo + :type 'function) + +;;; Inlinetasks + +(defcustom org-texinfo-format-inlinetask-function nil + "Function called to format an inlinetask in Texinfo code. + +The function must accept six parameters: + TODO the todo keyword, as a string + TODO-TYPE the todo type, a symbol among `todo', `done' and nil. + PRIORITY the inlinetask priority, as a string + NAME the inlinetask name, as a string. + TAGS the inlinetask tags, as a list of strings. + CONTENTS the contents of the inlinetask, as a string. + +The function should return the string to be exported. + +For example, the variable could be set to the following function +in order to mimic default behaviour: + +\(defun org-texinfo-format-inlinetask \(todo type priority name tags contents\) +\"Format an inline task element for Texinfo export.\" + \(let ((full-title + \(concat + \(when todo + \(format \"@strong{%s} \" todo)) + \(when priority (format \"#%c \" priority)) + title + \(when tags + \(format \":%s:\" + \(mapconcat 'identity tags \":\"))))) + \(format (concat \"@center %s\n\n\" + \"%s\" + \"\n\")) + full-title contents))" + :group 'org-export-texinfo + :type 'function) + +;;; Src blocks +;; +;; Src Blocks are example blocks, except for LISP + +;;; Compilation + +(defcustom org-texinfo-info-process + '("makeinfo %f") + "Commands to process a Texinfo file to an INFO file. +This is list of strings, each of them will be given to the shell +as a command. %f in the command will be replaced by the full +file name, %b by the file base name \(i.e without extension) and +%o by the base directory of the file." + :group 'org-export-texinfo + :type '(repeat :tag "Shell command sequence" + (string :tag "Shell command"))) + +(defcustom org-texinfo-logfiles-extensions + '("aux" "toc" "cp" "fn" "ky" "pg" "tp" "vr") + "The list of file extensions to consider as Texinfo logfiles. +The logfiles will be remove if `org-texinfo-remove-logfiles' is +non-nil." + :group 'org-export-texinfo + :type '(repeat (string :tag "Extension"))) + +(defcustom org-texinfo-remove-logfiles t + "Non-nil means remove the logfiles produced by compiling a Texinfo file. +By default, logfiles are files with these extensions: .aux, .toc, +.cp, .fn, .ky, .pg and .tp. To define the set of logfiles to remove, +set `org-texinfo-logfiles-extensions'." + :group 'org-export-latex + :type 'boolean) + + +;;; Constants +(defconst org-texinfo-max-toc-depth 4 + "Maximum depth for creation of detailed menu listings. Beyond + this depth Texinfo will not recognize the nodes and will cause + errors. Left as a constant in case this value ever changes.") + +(defconst org-texinfo-supported-coding-systems + '("US-ASCII" "UTF-8" "ISO-8859-15" "ISO-8859-1" "ISO-8859-2" "koi8-r" "koi8-u") + "List of coding systems supported by Texinfo, as strings. +Specified coding system will be matched against these strings. +If two strings share the same prefix (e.g. \"ISO-8859-1\" and +\"ISO-8859-15\"), the most specific one has to be listed first.") + + +;;; Internal Functions + +(defun org-texinfo-filter-section-blank-lines (headline back-end info) + "Filter controlling number of blank lines after a section." + (let ((blanks (make-string 2 ?\n))) + (replace-regexp-in-string "\n\\(?:\n[ \t]*\\)*\\'" blanks headline))) + +(defun org-texinfo--find-verb-separator (s) + "Return a character not used in string S. +This is used to choose a separator for constructs like \\verb." + (let ((ll "~,./?;':\"|!@#%^&-_=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ<>()[]{}")) + (loop for c across ll + when (not (string-match (regexp-quote (char-to-string c)) s)) + return (char-to-string c)))) + +(defun org-texinfo--make-option-string (options) + "Return a comma separated string of keywords and values. +OPTIONS is an alist where the key is the options keyword as +a string, and the value a list containing the keyword value, or +nil." + (mapconcat (lambda (pair) + (concat (first pair) + (when (> (length (second pair)) 0) + (concat "=" (second pair))))) + options + ",")) + +(defun org-texinfo--text-markup (text markup) + "Format TEXT depending on MARKUP text markup. +See `org-texinfo-text-markup-alist' for details." + (let ((fmt (cdr (assq markup org-texinfo-text-markup-alist)))) + (cond + ;; No format string: Return raw text. + ((not fmt) text) + ((eq 'verb fmt) + (let ((separator (org-texinfo--find-verb-separator text))) + (concat "@verb{" separator text separator "}"))) + ((eq 'code fmt) + (let ((start 0) + (rtn "") + char) + (while (string-match "[@{}]" text) + (setq char (match-string 0 text)) + (if (> (match-beginning 0) 0) + (setq rtn (concat rtn (substring text 0 (match-beginning 0))))) + (setq text (substring text (1+ (match-beginning 0)))) + (setq char (concat "@" char) + rtn (concat rtn char))) + (setq text (concat rtn text) + fmt "@code{%s}") + (format fmt text))) + ;; Else use format string. + (t (format fmt text))))) + +(defun org-texinfo--get-node (headline info) + "Return node entry associated to HEADLINE. +INFO is a plist used as a communication channel." + (let ((menu-title (org-export-get-alt-title headline info))) + (org-texinfo--sanitize-menu + (replace-regexp-in-string + "%" "%%" + (if menu-title (org-export-data menu-title info) + (org-texinfo--sanitize-headline + (org-element-property :title headline) info)))))) + +;;; Headline sanitizing + +(defun org-texinfo--sanitize-headline (headline info) + "Remove all formatting from the text of a headline for use in + node and menu listing." + (mapconcat 'identity + (org-texinfo--sanitize-headline-contents headline info) " ")) + +(defun org-texinfo--sanitize-headline-contents (headline info) + "Retrieve the content of the headline. + +Any content that can contain further formatting is checked +recursively, to ensure that nested content is also properly +retrieved." + (loop for contents in headline append + (cond + ;; already a string + ((stringp contents) + (list (replace-regexp-in-string " $" "" contents))) + ;; Is exported as-is (value) + ((org-element-map contents '(verbatim code) + (lambda (value) (org-element-property :value value)) info)) + ;; Has content and recurse into the content + ((org-element-contents contents) + (org-texinfo--sanitize-headline-contents + (org-element-contents contents) info))))) + +;;; Menu sanitizing + +(defun org-texinfo--sanitize-menu (title) + "Remove invalid characters from TITLE for use in menus and +nodes. + +Based on Texinfo specifications, the following must be removed: +@ { } ( ) : . ," + (replace-regexp-in-string "[@{}():,.]" "" title)) + +;;; Content sanitizing + +(defun org-texinfo--sanitize-content (text) + "Ensure characters are properly escaped when used in headlines or blocks. + +Escape characters are: @ { }" + (replace-regexp-in-string "\\\([@{}]\\\)" "@\\1" text)) + +;;; Menu creation + +(defun org-texinfo--build-menu (tree level info &optional detailed) + "Create the @menu/@end menu information from TREE at headline +level LEVEL. + +TREE contains the parse-tree to work with, either of the entire +document or of a specific parent headline. LEVEL indicates what +level of headlines to look at when generating the menu. INFO is +a plist containing contextual information. + +Detailed determines whether to build a single level of menu, or +recurse into all children as well." + (let ((menu (org-texinfo--generate-menu-list tree level info)) + output text-menu) + (cond + (detailed + ;; Looping is done within the menu generation. + (setq text-menu (org-texinfo--generate-detailed menu level info))) + (t + (setq text-menu (org-texinfo--generate-menu-items menu info)))) + (when text-menu + (setq output (org-texinfo--format-menu text-menu)) + (mapconcat 'identity output "\n")))) + +(defun org-texinfo--generate-detailed (menu level info) + "Generate a detailed listing of all subheadings within MENU starting at LEVEL. + +MENU is the parse-tree to work with. LEVEL is the starting level +for the menu headlines and from which recursion occurs. INFO is +a plist containing contextual information." + (when level + (let ((max-depth (min org-texinfo-max-toc-depth + (plist-get info :headline-levels)))) + (when (> max-depth level) + (loop for headline in menu append + (let* ((title (org-texinfo--menu-headlines headline info)) + ;; Create list of menu entries for the next level + (sublist (org-texinfo--generate-menu-list + headline (1+ level) info)) + ;; Generate the menu items for that level. If + ;; there are none omit that heading completely, + ;; otherwise join the title to it's related entries. + (submenu (if (org-texinfo--generate-menu-items sublist info) + (append (list title) + (org-texinfo--generate-menu-items sublist info)) + 'nil)) + ;; Start the process over the next level down. + (recursion (org-texinfo--generate-detailed sublist (1+ level) info))) + (setq recursion (append submenu recursion)) + recursion)))))) + +(defun org-texinfo--generate-menu-list (tree level info) + "Generate the list of headlines that are within a given level +of the tree for further formatting. + +TREE is the parse-tree containing the headlines. LEVEL is the +headline level to generate a list of. INFO is a plist holding +contextual information." + (org-element-map tree 'headline + (lambda (head) + (and (= (org-export-get-relative-level head info) level) + ;; Do not take note of footnotes or copying headlines. + (not (org-element-property :COPYING head)) + (not (org-element-property :footnote-section-p head)) + ;; Collect headline. + head)) + info)) + +(defun org-texinfo--generate-menu-items (items info) + "Generate a list of headline information from the listing ITEMS. + +ITEMS is a list of the headlines to be converted into entries. +INFO is a plist containing contextual information. + +Returns a list containing the following information from each +headline: length, title, description. This is used to format the +menu using `org-texinfo--format-menu'." + (loop for headline in items collect + (let* ((menu-title (org-texinfo--sanitize-menu + (org-export-data + (org-export-get-alt-title headline info) + info))) + (title (org-texinfo--sanitize-menu + (org-texinfo--sanitize-headline + (org-element-property :title headline) info))) + (descr (org-export-data + (org-element-property :DESCRIPTION headline) + info)) + (menu-entry (if (string= "" menu-title) title menu-title)) + (len (length menu-entry)) + (output (list len menu-entry descr))) + output))) + +(defun org-texinfo--menu-headlines (headline info) + "Retrieve the title from HEADLINE. + +INFO is a plist holding contextual information. + +Return the headline as a list of (length title description) with +length of -1 and nil description. This is used in +`org-texinfo--format-menu' to identify headlines as opposed to +entries." + (let ((title (org-export-data + (org-element-property :title headline) info))) + (list -1 title 'nil))) + +(defun org-texinfo--format-menu (text-menu) + "Format the TEXT-MENU items to be properly printed in the menu. + +Each entry in the menu should be provided as (length title +description). + +Headlines in the detailed menu are given length -1 to ensure they +are never confused with other entries. They also have no +description. + +Other menu items are output as: + Title:: description + +With the spacing between :: and description based on the length +of the longest menu entry." + + (let (output) + (setq output + (mapcar (lambda (name) + (let* ((title (nth 1 name)) + (desc (nth 2 name)) + (length (nth 0 name)) + (column (max + ;;6 is "* " ":: " for inserted text + length + (- + org-texinfo-node-description-column + 6))) + (spacing (- column length) + )) + (if (> length -1) + (concat "* " title ":: " + (make-string spacing ?\s) + (if desc + (concat desc))) + (concat "\n" title "\n")))) + text-menu)) + output)) + +;;; Template + +(defun org-texinfo-template (contents info) + "Return complete document string after Texinfo conversion. +CONTENTS is the transcoded contents string. INFO is a plist +holding export options." + (let* ((title (org-export-data (plist-get info :title) info)) + (info-filename (or (plist-get info :texinfo-filename) + (file-name-nondirectory + (org-export-output-file-name ".info")))) + (author (org-export-data (plist-get info :author) info)) + (lang (org-export-data (plist-get info :language) info)) + (texinfo-header (plist-get info :texinfo-header)) + (texinfo-post-header (plist-get info :texinfo-post-header)) + (subtitle (plist-get info :subtitle)) + (subauthor (plist-get info :subauthor)) + (class (plist-get info :texinfo-class)) + (header (nth 1 (assoc class org-texinfo-classes))) + (copying + (org-element-map (plist-get info :parse-tree) 'headline + (lambda (hl) (and (org-element-property :COPYING hl) hl)) info t)) + (dircat (plist-get info :texinfo-dircat)) + (dirtitle (plist-get info :texinfo-dirtitle)) + (dirdesc (plist-get info :texinfo-dirdesc)) + ;; Spacing to align description (column 32 - 3 for `* ' and + ;; `.' in text. + (dirspacing (- 29 (length dirtitle))) + (menu (org-texinfo-make-menu info 'main)) + (detail-menu (org-texinfo-make-menu info 'detailed))) + (concat + ;; Header + header "\n" + "@c %**start of header\n" + ;; Filename and Title + "@setfilename " info-filename "\n" + "@settitle " title "\n" + ;; Coding system. + (format + "@documentencoding %s\n" + (catch 'coding-system + (let ((case-fold-search t) + (name (symbol-name (or org-texinfo-coding-system + buffer-file-coding-system)))) + (dolist (system org-texinfo-supported-coding-systems "UTF-8") + (when (org-string-match-p (regexp-quote system) name) + (throw 'coding-system system)))))) + "\n" + (format "@documentlanguage %s\n" lang) + "\n\n" + "@c Version and Contact Info\n" + "@set AUTHOR " author "\n" + + ;; Additional Header Options set by `#+TEXINFO_HEADER + (if texinfo-header + (concat "\n" + texinfo-header + "\n")) + + "@c %**end of header\n" + "@finalout\n" + "\n\n" + + ;; Additional Header Options set by #+TEXINFO_POST_HEADER + (if texinfo-post-header + (concat "\n" + texinfo-post-header + "\n")) + + ;; Copying + "@copying\n" + ;; Only export the content of the headline, do not need the + ;; initial headline. + (org-export-data (nth 2 copying) info) + "@end copying\n" + "\n\n" + + ;; Info directory information + ;; Only supply if both title and category are provided + (if (and dircat dirtitle) + (concat "@dircategory " dircat "\n" + "@direntry\n" + "* " dirtitle "." + (make-string dirspacing ?\s) + dirdesc "\n" + "@end direntry\n")) + "\n\n" + + ;; Title + "@titlepage\n" + "@title " title "\n\n" + (if subtitle + (concat "@subtitle " subtitle "\n")) + "@author " author "\n" + (if subauthor + (concat subauthor "\n")) + "\n" + "@c The following two commands start the copyright page.\n" + "@page\n" + "@vskip 0pt plus 1filll\n" + "@insertcopying\n" + "@end titlepage\n\n" + "@c Output the table of contents at the beginning.\n" + "@contents\n\n" + + ;; Configure Top Node when not for Tex + "@ifnottex\n" + "@node Top\n" + "@top " title " Manual\n" + "@insertcopying\n" + "@end ifnottex\n\n" + + ;; Do not output menus if they are empty + (if menu + ;; Menu + (concat "@menu\n" + menu + "\n\n" + ;; Detailed Menu + (if detail-menu + (concat "@detailmenu\n" + " --- The Detailed Node Listing ---\n" + detail-menu + "\n\n" + "@end detailmenu\n")) + "@end menu\n")) + "\n\n" + + ;; Document's body. + contents + "\n" + ;; Creator. + (let ((creator-info (plist-get info :with-creator))) + (cond + ((not creator-info) "") + ((eq creator-info 'comment) + (format "@c %s\n" (plist-get info :creator))) + (t (concat (plist-get info :creator) "\n")))) + ;; Document end. + "\n@bye"))) + + + +;;; Transcode Functions + +;;; Bold + +(defun org-texinfo-bold (bold contents info) + "Transcode BOLD from Org to Texinfo. +CONTENTS is the text with bold markup. INFO is a plist holding +contextual information." + (org-texinfo--text-markup contents 'bold)) + +;;; Center Block + +(defun org-texinfo-center-block (center-block contents info) + "Transcode a CENTER-BLOCK element from Org to Texinfo. +CONTENTS holds the contents of the block. INFO is a plist used +as a communication channel." + contents) + +;;; Clock + +(defun org-texinfo-clock (clock contents info) + "Transcode a CLOCK element from Org to Texinfo. +CONTENTS is nil. INFO is a plist holding contextual +information." + (concat + "@noindent" + (format "@strong{%s} " org-clock-string) + (format org-texinfo-inactive-timestamp-format + (concat (org-translate-time + (org-element-property :raw-value + (org-element-property :value clock))) + (let ((time (org-element-property :duration clock))) + (and time (format " (%s)" time))))) + "@*")) + +;;; Code + +(defun org-texinfo-code (code contents info) + "Transcode a CODE object from Org to Texinfo. +CONTENTS is nil. INFO is a plist used as a communication +channel." + (org-texinfo--text-markup (org-element-property :value code) 'code)) + +;;; Comment + +(defun org-texinfo-comment (comment contents info) + "Transcode a COMMENT object from Org to Texinfo. +CONTENTS is the text in the comment. INFO is a plist holding +contextual information." + (org-texinfo--text-markup (org-element-property :value comment) 'comment)) + +;;; Comment Block + +(defun org-texinfo-comment-block (comment-block contents info) + "Transcode a COMMENT-BLOCK object from Org to Texinfo. +CONTENTS is the text within the block. INFO is a plist holding +contextual information." + (format "@ignore\n%s@end ignore" (org-element-property :value comment-block))) + +;;; Drawer + +(defun org-texinfo-drawer (drawer contents info) + "Transcode a DRAWER element from Org to Texinfo. +CONTENTS holds the contents of the block. INFO is a plist +holding contextual information." + (let* ((name (org-element-property :drawer-name drawer)) + (output (if (functionp org-texinfo-format-drawer-function) + (funcall org-texinfo-format-drawer-function + name contents) + ;; If there's no user defined function: simply + ;; display contents of the drawer. + contents))) + output)) + +;;; Dynamic Block + +(defun org-texinfo-dynamic-block (dynamic-block contents info) + "Transcode a DYNAMIC-BLOCK element from Org to Texinfo. +CONTENTS holds the contents of the block. INFO is a plist +holding contextual information. See `org-export-data'." + contents) + +;;; Entity + +(defun org-texinfo-entity (entity contents info) + "Transcode an ENTITY object from Org to Texinfo. +CONTENTS are the definition itself. INFO is a plist holding +contextual information." + (let ((ent (org-element-property :latex entity))) + (if (org-element-property :latex-math-p entity) (format "@math{%s}" ent) ent))) + +;;; Example Block + +(defun org-texinfo-example-block (example-block contents info) + "Transcode an EXAMPLE-BLOCK element from Org to Texinfo. +CONTENTS is nil. INFO is a plist holding contextual +information." + (format "@verbatim\n%s@end verbatim" + (org-export-format-code-default example-block info))) + +;;; Export Block + +(defun org-texinfo-export-block (export-block contents info) + "Transcode a EXPORT-BLOCK element from Org to Texinfo. +CONTENTS is nil. INFO is a plist holding contextual information." + (when (string= (org-element-property :type export-block) "TEXINFO") + (org-remove-indentation (org-element-property :value export-block)))) + +;;; Export Snippet + +(defun org-texinfo-export-snippet (export-snippet contents info) + "Transcode a EXPORT-SNIPPET object from Org to Texinfo. +CONTENTS is nil. INFO is a plist holding contextual information." + (when (eq (org-export-snippet-backend export-snippet) 'texinfo) + (org-element-property :value export-snippet))) + +;;; Fixed Width + +(defun org-texinfo-fixed-width (fixed-width contents info) + "Transcode a FIXED-WIDTH element from Org to Texinfo. +CONTENTS is nil. INFO is a plist holding contextual information." + (format "@example\n%s\n@end example" + (org-remove-indentation + (org-texinfo--sanitize-content + (org-element-property :value fixed-width))))) + +;;; Footnote Reference +;; + +(defun org-texinfo-footnote-reference (footnote contents info) + "Create a footnote reference for FOOTNOTE. + +FOOTNOTE is the footnote to define. CONTENTS is nil. INFO is a +plist holding contextual information." + (let ((def (org-export-get-footnote-definition footnote info))) + (format "@footnote{%s}" + (org-trim (org-export-data def info))))) + +;;; Headline + +(defun org-texinfo-headline (headline contents info) + "Transcode a HEADLINE element from Org to Texinfo. +CONTENTS holds the contents of the headline. INFO is a plist +holding contextual information." + (let* ((class (plist-get info :texinfo-class)) + (level (org-export-get-relative-level headline info)) + (numberedp (org-export-numbered-headline-p headline info)) + (class-sectionning (assoc class org-texinfo-classes)) + ;; Find the index type, if any + (index (org-element-property :INDEX headline)) + ;; Check if it is an appendix + (appendix (org-element-property :APPENDIX headline)) + ;; Retrieve headline text + (text (org-texinfo--sanitize-headline + (org-element-property :title headline) info)) + ;; Create node info, to insert it before section formatting. + ;; Use custom menu title if present + (node (format "@node %s\n" (org-texinfo--get-node headline info))) + ;; Menus must be generated with first child, otherwise they + ;; will not nest properly + (menu (let* ((first (org-export-first-sibling-p headline info)) + (parent (org-export-get-parent-headline headline)) + (title (org-texinfo--sanitize-headline + (org-element-property :title parent) info)) + heading listing + (tree (plist-get info :parse-tree))) + (if first + (org-element-map (plist-get info :parse-tree) 'headline + (lambda (ref) + (if (member title (org-element-property :title ref)) + (push ref heading))) + info t)) + (setq listing (org-texinfo--build-menu + (car heading) level info)) + (if listing + (setq listing (replace-regexp-in-string + "%" "%%" listing) + listing (format + "\n@menu\n%s\n@end menu\n\n" listing)) + 'nil))) + ;; Section formatting will set two placeholders: one for the + ;; title and the other for the contents. + (section-fmt + (let ((sec (if (and (symbolp (nth 2 class-sectionning)) + (fboundp (nth 2 class-sectionning))) + (funcall (nth 2 class-sectionning) level numberedp) + (nth (1+ level) class-sectionning)))) + (cond + ;; No section available for that LEVEL. + ((not sec) nil) + ;; Section format directly returned by a function. + ((stringp sec) sec) + ;; (numbered-section . unnumbered-section) + ((not (consp (cdr sec))) + (cond + ;;If an index, always unnumbered + (index + (concat menu node (cdr sec) "\n%s")) + (appendix + (concat menu node (replace-regexp-in-string + "unnumbered" + "appendix" + (cdr sec)) "\n%s")) + ;; Otherwise number as needed. + (t + (concat menu node + (funcall + (if numberedp #'car #'cdr) sec) "\n%s"))))))) + (todo + (and (plist-get info :with-todo-keywords) + (let ((todo (org-element-property :todo-keyword headline))) + (and todo (org-export-data todo info))))) + (todo-type (and todo (org-element-property :todo-type headline))) + (tags (and (plist-get info :with-tags) + (org-export-get-tags headline info))) + (priority (and (plist-get info :with-priority) + (org-element-property :priority headline))) + ;; Create the headline text along with a no-tag version. The + ;; latter is required to remove tags from table of contents. + (full-text (org-texinfo--sanitize-content + (if (functionp org-texinfo-format-headline-function) + ;; User-defined formatting function. + (funcall org-texinfo-format-headline-function + todo todo-type priority text tags) + ;; Default formatting. + (concat + (when todo + (format "@strong{%s} " todo)) + (when priority (format "@emph{#%s} " priority)) + text + (when tags + (format " :%s:" + (mapconcat 'identity tags ":"))))))) + (full-text-no-tag + (org-texinfo--sanitize-content + (if (functionp org-texinfo-format-headline-function) + ;; User-defined formatting function. + (funcall org-texinfo-format-headline-function + todo todo-type priority text nil) + ;; Default formatting. + (concat + (when todo (format "@strong{%s} " todo)) + (when priority (format "@emph{#%c} " priority)) + text)))) + (pre-blanks + (make-string (org-element-property :pre-blank headline) 10))) + (cond + ;; Case 1: This is a footnote section: ignore it. + ((org-element-property :footnote-section-p headline) nil) + ;; Case 2: This is the `copying' section: ignore it + ;; This is used elsewhere. + ((org-element-property :COPYING headline) nil) + ;; Case 3: An index. If it matches one of the known indexes, + ;; print it as such following the contents, otherwise + ;; print the contents and leave the index up to the user. + (index + (format + section-fmt full-text + (concat pre-blanks contents "\n" + (if (member index '("cp" "fn" "ky" "pg" "tp" "vr")) + (concat "@printindex " index))))) + ;; Case 4: This is a deep sub-tree: export it as a list item. + ;; Also export as items headlines for which no section + ;; format has been found. + ((or (not section-fmt) (org-export-low-level-p headline info)) + ;; Build the real contents of the sub-tree. + (let ((low-level-body + (concat + ;; If the headline is the first sibling, start a list. + (when (org-export-first-sibling-p headline info) + (format "@%s\n" (if numberedp 'enumerate 'itemize))) + ;; Itemize headline + "@item\n" full-text "\n" pre-blanks contents))) + ;; If headline is not the last sibling simply return + ;; LOW-LEVEL-BODY. Otherwise, also close the list, before any + ;; blank line. + (if (not (org-export-last-sibling-p headline info)) low-level-body + (replace-regexp-in-string + "[ \t\n]*\\'" + (format "\n@end %s" (if numberedp 'enumerate 'itemize)) + low-level-body)))) + ;; Case 5: Standard headline. Export it as a section. + (t + (cond + ((not (and tags (eq (plist-get info :with-tags) 'not-in-toc))) + ;; Regular section. Use specified format string. + (format (replace-regexp-in-string "%]" "%%]" section-fmt) full-text + (concat pre-blanks contents))) + ((string-match "\\`@\\(.*?\\){" section-fmt) + ;; If tags should be removed from table of contents, insert + ;; title without tags as an alternative heading in sectioning + ;; command. + (format (replace-match (concat (match-string 1 section-fmt) "[%s]") + nil nil section-fmt 1) + ;; Replace square brackets with parenthesis since + ;; square brackets are not supported in optional + ;; arguments. + (replace-regexp-in-string + "\\[" "(" + (replace-regexp-in-string + "\\]" ")" + full-text-no-tag)) + full-text + (concat pre-blanks contents))) + (t + ;; Impossible to add an alternative heading. Fallback to + ;; regular sectioning format string. + (format (replace-regexp-in-string "%]" "%%]" section-fmt) full-text + (concat pre-blanks contents)))))))) + +;;; Inline Src Block + +(defun org-texinfo-inline-src-block (inline-src-block contents info) + "Transcode an INLINE-SRC-BLOCK element from Org to Texinfo. +CONTENTS holds the contents of the item. INFO is a plist holding +contextual information." + (let* ((code (org-element-property :value inline-src-block)) + (separator (org-texinfo--find-verb-separator code))) + (concat "@verb{" separator code separator "}"))) + +;;; Inlinetask + +(defun org-texinfo-inlinetask (inlinetask contents info) + "Transcode an INLINETASK element from Org to Texinfo. +CONTENTS holds the contents of the block. INFO is a plist +holding contextual information." + (let ((title (org-export-data (org-element-property :title inlinetask) info)) + (todo (and (plist-get info :with-todo-keywords) + (let ((todo (org-element-property :todo-keyword inlinetask))) + (and todo (org-export-data todo info))))) + (todo-type (org-element-property :todo-type inlinetask)) + (tags (and (plist-get info :with-tags) + (org-export-get-tags inlinetask info))) + (priority (and (plist-get info :with-priority) + (org-element-property :priority inlinetask)))) + ;; If `org-texinfo-format-inlinetask-function' is provided, call it + ;; with appropriate arguments. + (if (functionp org-texinfo-format-inlinetask-function) + (funcall org-texinfo-format-inlinetask-function + todo todo-type priority title tags contents) + ;; Otherwise, use a default template. + (let ((full-title + (concat + (when todo (format "@strong{%s} " todo)) + (when priority (format "#%c " priority)) + title + (when tags (format ":%s:" + (mapconcat 'identity tags ":")))))) + (format (concat "@center %s\n\n" + "%s" + "\n") + full-title contents))))) + +;;; Italic + +(defun org-texinfo-italic (italic contents info) + "Transcode ITALIC from Org to Texinfo. +CONTENTS is the text with italic markup. INFO is a plist holding +contextual information." + (org-texinfo--text-markup contents 'italic)) + +;;; Item + +(defun org-texinfo-item (item contents info) + "Transcode an ITEM element from Org to Texinfo. +CONTENTS holds the contents of the item. INFO is a plist holding +contextual information." + (let* ((tag (org-element-property :tag item)) + (desc (org-export-data tag info))) + (concat "\n@item " (if tag desc) "\n" + (and contents (org-trim contents)) "\n"))) + +;;; Keyword + +(defun org-texinfo-keyword (keyword contents info) + "Transcode a KEYWORD element from Org to Texinfo. +CONTENTS is nil. INFO is a plist holding contextual information." + (let ((key (org-element-property :key keyword)) + (value (org-element-property :value keyword))) + (cond + ((string= key "TEXINFO") value) + ((string= key "CINDEX") (format "@cindex %s" value)) + ((string= key "FINDEX") (format "@findex %s" value)) + ((string= key "KINDEX") (format "@kindex %s" value)) + ((string= key "PINDEX") (format "@pindex %s" value)) + ((string= key "TINDEX") (format "@tindex %s" value)) + ((string= key "VINDEX") (format "@vindex %s" value))))) + +;;; Line Break + +(defun org-texinfo-line-break (line-break contents info) + "Transcode a LINE-BREAK object from Org to Texinfo. +CONTENTS is nil. INFO is a plist holding contextual information." + "@*\n") + +;;; Link + +(defun org-texinfo-link (link desc info) + "Transcode a LINK object from Org to Texinfo. + +DESC is the description part of the link, or the empty string. +INFO is a plist holding contextual information. See +`org-export-data'." + (let* ((type (org-element-property :type link)) + (raw-path (org-element-property :path link)) + ;; Ensure DESC really exists, or set it to nil. + (desc (and (not (string= desc "")) desc)) + (path (cond + ((member type '("http" "https" "ftp")) + (concat type ":" raw-path)) + ((string= type "file") + (if (file-name-absolute-p raw-path) + (concat "file://" (expand-file-name raw-path)) + (concat "file://" raw-path))) + (t raw-path))) + (email (if (string= type "mailto") + (let ((text (replace-regexp-in-string + "@" "@@" raw-path))) + (concat text (if desc (concat "," desc)))))) + protocol) + (cond + ;; Links pointing to a headline: Find destination and build + ;; appropriate referencing command. + ((member type '("custom-id" "id")) + (let ((destination (org-export-resolve-id-link link info))) + (case (org-element-type destination) + ;; Id link points to an external file. + (plain-text + (if desc (format "@uref{file://%s,%s}" destination desc) + (format "@uref{file://%s}" destination))) + ;; LINK points to a headline. Use the headline as the NODE target + (headline + (format "@ref{%s,%s}" + (org-texinfo--get-node destination info) + (or desc ""))) + (otherwise + (let ((path (org-export-solidify-link-text path))) + (if (not desc) (format "@ref{%s}" path) + (format "@ref{%s,,%s}" path desc))))))) + ((member type '("info")) + (let* ((info-path (split-string path "[:#]")) + (info-manual (car info-path)) + (info-node (or (cadr info-path) "top")) + (title (or desc ""))) + (format "@ref{%s,%s,,%s,}" info-node title info-manual))) + ((member type '("fuzzy")) + (let ((destination (org-export-resolve-fuzzy-link link info))) + (case (org-element-type destination) + ;; Id link points to an external file. + (plain-text + (if desc (format "@uref{file://%s,%s}" destination desc) + (format "@uref{file://%s}" destination))) + ;; LINK points to a headline. Use the headline as the NODE target + (headline + (format "@ref{%s,%s}" + (org-texinfo--get-node destination info) + (or desc ""))) + (otherwise + (let ((path (org-export-solidify-link-text path))) + (if (not desc) (format "@ref{%s}" path) + (format "@ref{%s,,%s}" path desc))))))) + ;; Special case for email addresses + (email + (format "@email{%s}" email)) + ;; External link with a description part. + ((and path desc) (format "@uref{%s,%s}" path desc)) + ;; External link without a description part. + (path (format "@uref{%s}" path)) + ;; No path, only description. Try to do something useful. + (t (format org-texinfo-link-with-unknown-path-format desc))))) + + +;;; Menu + +(defun org-texinfo-make-menu (info level) + "Create the menu for inclusion in the texifo document. + +INFO is the parsed buffer that contains the headlines. LEVEL +determines whether to make the main menu, or the detailed menu. + +This is only used for generating the primary menu. In-Node menus +are generated directly." + (let ((parse (plist-get info :parse-tree))) + (cond + ;; Generate the main menu + ((eq level 'main) (org-texinfo--build-menu parse 1 info)) + ;; Generate the detailed (recursive) menu + ((eq level 'detailed) + ;; Requires recursion + ;;(org-texinfo--build-detailed-menu parse top info) + (org-texinfo--build-menu parse 1 info 'detailed))))) + +;;; Paragraph + +(defun org-texinfo-paragraph (paragraph contents info) + "Transcode a PARAGRAPH element from Org to Texinfo. +CONTENTS is the contents of the paragraph, as a string. INFO is +the plist used as a communication channel." + contents) + +;;; Plain List + +(defun org-texinfo-plain-list (plain-list contents info) + "Transcode a PLAIN-LIST element from Org to Texinfo. +CONTENTS is the contents of the list. INFO is a plist holding +contextual information." + (let* ((attr (org-export-read-attribute :attr_texinfo plain-list)) + (indic (or (plist-get attr :indic) + org-texinfo-def-table-markup)) + (type (org-element-property :type plain-list)) + (table-type (plist-get attr :table-type)) + ;; Ensure valid texinfo table type. + (table-type (if (member table-type '("ftable" "vtable")) table-type + "table")) + (list-type (cond + ((eq type 'ordered) "enumerate") + ((eq type 'unordered) "itemize") + ((eq type 'descriptive) table-type)))) + (format "@%s%s\n@end %s" + (if (eq type 'descriptive) + (concat list-type " " indic) + list-type) + contents + list-type))) + +;;; Plain Text + +(defun org-texinfo-plain-text (text info) + "Transcode a TEXT string from Org to Texinfo. +TEXT is the string to transcode. INFO is a plist holding +contextual information." + ;; First protect @, { and }. + (let ((output (org-texinfo--sanitize-content text))) + ;; Activate smart quotes. Be sure to provide original TEXT string + ;; since OUTPUT may have been modified. + (when (plist-get info :with-smart-quotes) + (setq output + (org-export-activate-smart-quotes output :texinfo info text))) + ;; LaTeX into @LaTeX{} and TeX into @TeX{} + (let ((case-fold-search nil) + (start 0)) + (while (string-match "\\(\\(?:La\\)?TeX\\)" output start) + (setq output (replace-match + (format "@%s{}" (match-string 1 output)) nil t output) + start (match-end 0)))) + ;; Convert special strings. + (when (plist-get info :with-special-strings) + (while (string-match (regexp-quote "...") output) + (setq output (replace-match "@dots{}" nil t output)))) + ;; Handle break preservation if required. + (when (plist-get info :preserve-breaks) + (setq output (replace-regexp-in-string + "\\(\\\\\\\\\\)?[ \t]*\n" " @*\n" output))) + ;; Return value. + output)) + +;;; Planning + +(defun org-texinfo-planning (planning contents info) + "Transcode a PLANNING element from Org to Texinfo. +CONTENTS is nil. INFO is a plist holding contextual +information." + (concat + "@noindent" + (mapconcat + 'identity + (delq nil + (list + (let ((closed (org-element-property :closed planning))) + (when closed + (concat + (format "@strong{%s} " org-closed-string) + (format org-texinfo-inactive-timestamp-format + (org-translate-time + (org-element-property :raw-value closed)))))) + (let ((deadline (org-element-property :deadline planning))) + (when deadline + (concat + (format "@strong{%s} " org-deadline-string) + (format org-texinfo-active-timestamp-format + (org-translate-time + (org-element-property :raw-value deadline)))))) + (let ((scheduled (org-element-property :scheduled planning))) + (when scheduled + (concat + (format "@strong{%s} " org-scheduled-string) + (format org-texinfo-active-timestamp-format + (org-translate-time + (org-element-property :raw-value scheduled)))))))) + " ") + "@*")) + +;;; Property Drawer + +(defun org-texinfo-property-drawer (property-drawer contents info) + "Transcode a PROPERTY-DRAWER element from Org to Texinfo. +CONTENTS is nil. INFO is a plist holding contextual +information." + ;; The property drawer isn't exported but we want separating blank + ;; lines nonetheless. + "") + +;;; Quote Block + +(defun org-texinfo-quote-block (quote-block contents info) + "Transcode a QUOTE-BLOCK element from Org to Texinfo. +CONTENTS holds the contents of the block. INFO is a plist +holding contextual information." + (let* ((title (org-element-property :name quote-block)) + (start-quote (concat "@quotation" + (if title + (format " %s" title))))) + (format "%s\n%s@end quotation" start-quote contents))) + +;;; Quote Section + +(defun org-texinfo-quote-section (quote-section contents info) + "Transcode a QUOTE-SECTION element from Org to Texinfo. +CONTENTS is nil. INFO is a plist holding contextual information." + (let ((value (org-remove-indentation + (org-element-property :value quote-section)))) + (when value (format "@verbatim\n%s@end verbatim" value)))) + +;;; Radio Target + +(defun org-texinfo-radio-target (radio-target text info) + "Transcode a RADIO-TARGET object from Org to Texinfo. +TEXT is the text of the target. INFO is a plist holding +contextual information." + (format "@anchor{%s}%s" + (org-export-solidify-link-text + (org-element-property :value radio-target)) + text)) + +;;; Section + +(defun org-texinfo-section (section contents info) + "Transcode a SECTION element from Org to Texinfo. +CONTENTS holds the contents of the section. INFO is a plist +holding contextual information." + contents) + +;;; Special Block + +(defun org-texinfo-special-block (special-block contents info) + "Transcode a SPECIAL-BLOCK element from Org to Texinfo. +CONTENTS holds the contents of the block. INFO is a plist used +as a communication channel." + contents) + +;;; Src Block + +(defun org-texinfo-src-block (src-block contents info) + "Transcode a SRC-BLOCK element from Org to Texinfo. +CONTENTS holds the contents of the item. INFO is a plist holding +contextual information." + (let* ((lang (org-element-property :language src-block)) + (lisp-p (string-match-p "lisp" lang)) + (src-contents (org-texinfo--sanitize-content + (org-export-format-code-default src-block info)))) + (cond + ;; Case 1. Lisp Block + (lisp-p + (format "@lisp\n%s@end lisp" + src-contents)) + ;; Case 2. Other blocks + (t + (format "@example\n%s@end example" + src-contents))))) + +;;; Statistics Cookie + +(defun org-texinfo-statistics-cookie (statistics-cookie contents info) + "Transcode a STATISTICS-COOKIE object from Org to Texinfo. +CONTENTS is nil. INFO is a plist holding contextual information." + (org-element-property :value statistics-cookie)) + +;;; Subscript + +(defun org-texinfo-subscript (subscript contents info) + "Transcode a SUBSCRIPT object from Org to Texinfo. +CONTENTS is the contents of the object. INFO is a plist holding +contextual information." + (format "@math{_%s}" contents)) + +;;; Superscript + +(defun org-texinfo-superscript (superscript contents info) + "Transcode a SUPERSCRIPT object from Org to Texinfo. +CONTENTS is the contents of the object. INFO is a plist holding +contextual information." + (format "@math{^%s}" contents)) + +;;; Table +;; +;; `org-texinfo-table' is the entry point for table transcoding. It +;; takes care of tables with a "verbatim" attribute. Otherwise, it +;; delegates the job to either `org-texinfo-table--table.el-table' or +;; `org-texinfo-table--org-table' functions, depending of the type of +;; the table. +;; +;; `org-texinfo-table--align-string' is a subroutine used to build +;; alignment string for Org tables. + +(defun org-texinfo-table (table contents info) + "Transcode a TABLE element from Org to Texinfo. +CONTENTS is the contents of the table. INFO is a plist holding +contextual information." + (cond + ;; Case 1: verbatim table. + ((or org-texinfo-tables-verbatim + (let ((attr (mapconcat 'identity + (org-element-property :attr_latex table) + " "))) + (and attr (string-match "\\" attr)))) + (format "@verbatim \n%s\n@end verbatim" + ;; Re-create table, without affiliated keywords. + (org-trim + (org-element-interpret-data + `(table nil ,@(org-element-contents table)))))) + ;; Case 2: table.el table. Convert it using appropriate tools. + ((eq (org-element-property :type table) 'table.el) + (org-texinfo-table--table.el-table table contents info)) + ;; Case 3: Standard table. + (t (org-texinfo-table--org-table table contents info)))) + +(defun org-texinfo-table-column-widths (table info) + "Determine the largest table cell in each column to process alignment. + +TABLE is the table element to transcode. INFO is a plist used as +a communication channel." + (let* ((rows (org-element-map table 'table-row 'identity info)) + (collected (loop for row in rows collect + (org-element-map row 'table-cell 'identity info))) + (number-cells (length (car collected))) + cells counts) + (loop for row in collected do + (push (mapcar (lambda (ref) + (let* ((start (org-element-property :contents-begin ref)) + (end (org-element-property :contents-end ref)) + (length (- end start))) + length)) row) cells)) + (setq cells (org-remove-if 'null cells)) + (push (loop for count from 0 to (- number-cells 1) collect + (loop for item in cells collect + (nth count item))) counts) + (mapconcat (lambda (size) + (make-string size ?a)) (mapcar (lambda (ref) + (apply 'max `(,@ref))) (car counts)) + "} {"))) + +(defun org-texinfo-table--org-table (table contents info) + "Return appropriate Texinfo code for an Org table. + +TABLE is the table type element to transcode. CONTENTS is its +contents, as a string. INFO is a plist used as a communication +channel. + +This function assumes TABLE has `org' as its `:type' attribute." + (let* ((attr (org-export-read-attribute :attr_texinfo table)) + (col-width (plist-get attr :columns)) + (columns (if col-width + (format "@columnfractions %s" + col-width) + (format "{%s}" + (org-texinfo-table-column-widths + table info))))) + ;; Prepare the final format string for the table. + (cond + ;; Longtable. + ;; Others. + (t (concat + (format "@multitable %s\n%s@end multitable" + columns + contents)))))) + +(defun org-texinfo-table--table.el-table (table contents info) + "Returns nothing. + +Rather than return an invalid table, nothing is returned." + 'nil) + +;;; Table Cell + +(defun org-texinfo-table-cell (table-cell contents info) + "Transcode a TABLE-CELL element from Org to Texinfo. +CONTENTS is the cell contents. INFO is a plist used as +a communication channel." + (concat (if (and contents + org-texinfo-table-scientific-notation + (string-match orgtbl-exp-regexp contents)) + ;; Use appropriate format string for scientific + ;; notation. + (format org-texinfo-table-scientific-notation + (match-string 1 contents) + (match-string 2 contents)) + contents) + (when (org-export-get-next-element table-cell info) "\n@tab "))) + +;;; Table Row + +(defun org-texinfo-table-row (table-row contents info) + "Transcode a TABLE-ROW element from Org to Texinfo. +CONTENTS is the contents of the row. INFO is a plist used as +a communication channel." + ;; Rules are ignored since table separators are deduced from + ;; borders of the current row. + (when (eq (org-element-property :type table-row) 'standard) + (let ((rowgroup-tag + (cond + ;; Case 1: Belongs to second or subsequent rowgroup. + ((not (= 1 (org-export-table-row-group table-row info))) + "@item ") + ;; Case 2: Row is from first rowgroup. Table has >=1 rowgroups. + ((org-export-table-has-header-p + (org-export-get-parent-table table-row) info) + "@headitem ") + ;; Case 3: Row is from first and only row group. + (t "@item ")))) + (when (eq (org-element-property :type table-row) 'standard) + (concat rowgroup-tag contents "\n"))))) + +;;; Target + +(defun org-texinfo-target (target contents info) + "Transcode a TARGET object from Org to Texinfo. +CONTENTS is nil. INFO is a plist holding contextual +information." + (format "@anchor{%s}" + (org-export-solidify-link-text (org-element-property :value target)))) + +;;; Timestamp + +(defun org-texinfo-timestamp (timestamp contents info) + "Transcode a TIMESTAMP object from Org to Texinfo. +CONTENTS is nil. INFO is a plist holding contextual +information." + (let ((value (org-texinfo-plain-text + (org-timestamp-translate timestamp) info))) + (case (org-element-property :type timestamp) + ((active active-range) + (format org-texinfo-active-timestamp-format value)) + ((inactive inactive-range) + (format org-texinfo-inactive-timestamp-format value)) + (t (format org-texinfo-diary-timestamp-format value))))) + +;;; Verbatim + +(defun org-texinfo-verbatim (verbatim contents info) + "Transcode a VERBATIM object from Org to Texinfo. +CONTENTS is nil. INFO is a plist used as a communication +channel." + (org-texinfo--text-markup (org-element-property :value verbatim) 'verbatim)) + +;;; Verse Block + +(defun org-texinfo-verse-block (verse-block contents info) + "Transcode a VERSE-BLOCK element from Org to Texinfo. +CONTENTS is verse block contents. INFO is a plist holding +contextual information." + ;; In a verse environment, add a line break to each newline + ;; character and change each white space at beginning of a line + ;; into a space of 1 em. Also change each blank line with + ;; a vertical space of 1 em. + (progn + (setq contents (replace-regexp-in-string + "^ *\\\\\\\\$" "\\\\vspace*{1em}" + (replace-regexp-in-string + "\\(\\\\\\\\\\)?[ \t]*\n" " \\\\\\\\\n" contents))) + (while (string-match "^[ \t]+" contents) + (let ((new-str (format "\\hspace*{%dem}" + (length (match-string 0 contents))))) + (setq contents (replace-match new-str nil t contents)))) + (format "\\begin{verse}\n%s\\end{verse}" contents))) + + +;;; Interactive functions + +(defun org-texinfo-export-to-texinfo + (&optional async subtreep visible-only body-only ext-plist) + "Export current buffer to a Texinfo file. + +If narrowing is active in the current buffer, only export its +narrowed part. + +If a region is active, export that region. + +A non-nil optional argument ASYNC means the process should happen +asynchronously. The resulting file should be accessible through +the `org-export-stack' interface. + +When optional argument SUBTREEP is non-nil, export the sub-tree +at point, extracting information from the headline properties +first. + +When optional argument VISIBLE-ONLY is non-nil, don't export +contents of hidden elements. + +When optional argument BODY-ONLY is non-nil, only write code +between \"\\begin{document}\" and \"\\end{document}\". + +EXT-PLIST, when provided, is a property list with external +parameters overriding Org default settings, but still inferior to +file-local settings. + +Return output file's name." + (interactive) + (let ((outfile (org-export-output-file-name ".texi" subtreep)) + (org-export-coding-system `,org-texinfo-coding-system)) + (org-export-to-file 'texinfo outfile + async subtreep visible-only body-only ext-plist))) + +(defun org-texinfo-export-to-info + (&optional async subtreep visible-only body-only ext-plist) + "Export current buffer to Texinfo then process through to INFO. + +If narrowing is active in the current buffer, only export its +narrowed part. + +If a region is active, export that region. + +A non-nil optional argument ASYNC means the process should happen +asynchronously. The resulting file should be accessible through +the `org-export-stack' interface. + +When optional argument SUBTREEP is non-nil, export the sub-tree +at point, extracting information from the headline properties +first. + +When optional argument VISIBLE-ONLY is non-nil, don't export +contents of hidden elements. + +When optional argument BODY-ONLY is non-nil, only write code +between \"\\begin{document}\" and \"\\end{document}\". + +EXT-PLIST, when provided, is a property list with external +parameters overriding Org default settings, but still inferior to +file-local settings. + +When optional argument PUB-DIR is set, use it as the publishing +directory. + +Return INFO file's name." + (interactive) + (let ((outfile (org-export-output-file-name ".texi" subtreep)) + (org-export-coding-system `,org-texinfo-coding-system)) + (org-export-to-file 'texinfo outfile + async subtreep visible-only body-only ext-plist + (lambda (file) (org-texinfo-compile file))))) + +;;;###autoload +(defun org-texinfo-publish-to-texinfo (plist filename pub-dir) + "Publish an org file to Texinfo. + +FILENAME is the filename of the Org file to be published. PLIST +is the property list for the given project. PUB-DIR is the +publishing directory. + +Return output file name." + (org-publish-org-to 'texinfo filename ".texi" plist pub-dir)) + +;;;###autoload +(defun org-texinfo-convert-region-to-texinfo () + "Assume the current region has org-mode syntax, and convert it to Texinfo. +This can be used in any buffer. For example, you can write an +itemized list in org-mode syntax in an Texinfo buffer and use +this command to convert it." + (interactive) + (org-export-replace-region-by 'texinfo)) + +(defun org-texinfo-compile (file) + "Compile a texinfo file. + +FILE is the name of the file being compiled. Processing is +done through the command specified in `org-texinfo-info-process'. + +Return INFO file name or an error if it couldn't be produced." + (let* ((base-name (file-name-sans-extension (file-name-nondirectory file))) + (full-name (file-truename file)) + (out-dir (file-name-directory file)) + ;; Properly set working directory for compilation. + (default-directory (if (file-name-absolute-p file) + (file-name-directory full-name) + default-directory)) + errors) + (message (format "Processing Texinfo file %s..." file)) + (save-window-excursion + (cond + ;; A function is provided: Apply it. + ((functionp org-texinfo-info-process) + (funcall org-texinfo-info-process (shell-quote-argument file))) + ;; A list is provided: Replace %b, %f and %o with appropriate + ;; values in each command before applying it. Output is + ;; redirected to "*Org INFO Texinfo Output*" buffer. + ((consp org-texinfo-info-process) + (let ((outbuf (get-buffer-create "*Org INFO Texinfo Output*"))) + (mapc + (lambda (command) + (shell-command + (replace-regexp-in-string + "%b" (shell-quote-argument base-name) + (replace-regexp-in-string + "%f" (shell-quote-argument full-name) + (replace-regexp-in-string + "%o" (shell-quote-argument out-dir) command t t) t t) t t) + outbuf)) + org-texinfo-info-process) + ;; Collect standard errors from output buffer. + (setq errors (org-texinfo-collect-errors outbuf)))) + (t (error "No valid command to process to Info"))) + (let ((infofile (concat out-dir base-name ".info"))) + ;; Check for process failure. Provide collected errors if + ;; possible. + (if (not (file-exists-p infofile)) + (error (concat (format "INFO file %s wasn't produced" infofile) + (when errors (concat ": " errors)))) + ;; Else remove log files, when specified, and signal end of + ;; process to user, along with any error encountered. + (when org-texinfo-remove-logfiles + (dolist (ext org-texinfo-logfiles-extensions) + (let ((file (concat out-dir base-name "." ext))) + (when (file-exists-p file) (delete-file file))))) + (message (concat "Process completed" + (if (not errors) "." + (concat " with errors: " errors))))) + ;; Return output file name. + infofile)))) + +(defun org-texinfo-collect-errors (buffer) + "Collect some kind of errors from \"makeinfo\" command output. + +BUFFER is the buffer containing output. + +Return collected error types as a string, or nil if there was +none." + (with-current-buffer buffer + (save-excursion + (goto-char (point-min)) + ;; Find final "makeinfo" run. + (when t + (let ((case-fold-search t) + (errors "")) + (when (save-excursion + (re-search-forward "perhaps incorrect sectioning?" nil t)) + (setq errors (concat errors " [incorrect sectioning]"))) + (when (save-excursion + (re-search-forward "missing close brace" nil t)) + (setq errors (concat errors " [syntax error]"))) + (when (save-excursion + (re-search-forward "Unknown command" nil t)) + (setq errors (concat errors " [undefined @command]"))) + (when (save-excursion + (re-search-forward "No matching @end" nil t)) + (setq errors (concat errors " [block incomplete]"))) + (when (save-excursion + (re-search-forward "requires a sectioning" nil t)) + (setq errors (concat errors " [invalid section command]"))) + (when (save-excursion + (re-search-forward "\\[unexpected\]" nil t)) + (setq errors (concat errors " [unexpected error]"))) + (when (save-excursion + (re-search-forward "misplaced " nil t)) + (setq errors (concat errors " [syntax error]"))) + (and (org-string-nw-p errors) (org-trim errors))))))) + + +(provide 'ox-texinfo) + +;; Local variables: +;; generated-autoload-file: "org-loaddefs.el" +;; End: + +;;; ox-texinfo.el ends here diff --git a/lisp/org/ox.el b/lisp/org/ox.el new file mode 100644 index 00000000000..f7566945a81 --- /dev/null +++ b/lisp/org/ox.el @@ -0,0 +1,6208 @@ +;;; ox.el --- Generic Export Engine for Org Mode + +;; Copyright (C) 2012, 2013 Free Software Foundation, Inc. + +;; Author: Nicolas Goaziou +;; Keywords: outlines, hypermedia, calendar, wp + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: +;; +;; This library implements a generic export engine for Org, built on +;; its syntactical parser: Org Elements. +;; +;; Besides that parser, the generic exporter is made of three distinct +;; parts: +;; +;; - The communication channel consists in a property list, which is +;; created and updated during the process. Its use is to offer +;; every piece of information, would it be about initial environment +;; or contextual data, all in a single place. The exhaustive list +;; of properties is given in "The Communication Channel" section of +;; this file. +;; +;; - The transcoder walks the parse tree, ignores or treat as plain +;; text elements and objects according to export options, and +;; eventually calls back-end specific functions to do the real +;; transcoding, concatenating their return value along the way. +;; +;; - The filter system is activated at the very beginning and the very +;; end of the export process, and each time an element or an object +;; has been converted. It is the entry point to fine-tune standard +;; output from back-end transcoders. See "The Filter System" +;; section for more information. +;; +;; The core function is `org-export-as'. It returns the transcoded +;; buffer as a string. +;; +;; An export back-end is defined with `org-export-define-backend'. +;; This function can also support specific buffer keywords, OPTION +;; keyword's items and filters. Refer to function's documentation for +;; more information. +;; +;; If the new back-end shares most properties with another one, +;; `org-export-define-derived-backend' can be used to simplify the +;; process. +;; +;; Any back-end can define its own variables. Among them, those +;; customizable should belong to the `org-export-BACKEND' group. +;; +;; Tools for common tasks across back-ends are implemented in the +;; following part of the file. +;; +;; Then, a wrapper macro for asynchronous export, +;; `org-export-async-start', along with tools to display results. are +;; given in the penultimate part. +;; +;; Eventually, a dispatcher (`org-export-dispatch') for standard +;; back-ends is provided in the last one. + +;;; Code: + +(eval-when-compile (require 'cl)) +(require 'org-element) +(require 'org-macro) +(require 'ob-exp) + +(declare-function org-publish "ox-publish" (project &optional force async)) +(declare-function org-publish-all "ox-publish" (&optional force async)) +(declare-function + org-publish-current-file "ox-publish" (&optional force async)) +(declare-function org-publish-current-project "ox-publish" + (&optional force async)) + +(defvar org-publish-project-alist) +(defvar org-table-number-fraction) +(defvar org-table-number-regexp) + + + +;;; Internal Variables +;; +;; Among internal variables, the most important is +;; `org-export-options-alist'. This variable define the global export +;; options, shared between every exporter, and how they are acquired. + +(defconst org-export-max-depth 19 + "Maximum nesting depth for headlines, counting from 0.") + +(defconst org-export-options-alist + '((:author "AUTHOR" nil user-full-name t) + (:creator "CREATOR" nil org-export-creator-string) + (:date "DATE" nil nil t) + (:description "DESCRIPTION" nil nil newline) + (:email "EMAIL" nil user-mail-address t) + (:exclude-tags "EXCLUDE_TAGS" nil org-export-exclude-tags split) + (:headline-levels nil "H" org-export-headline-levels) + (:keywords "KEYWORDS" nil nil space) + (:language "LANGUAGE" nil org-export-default-language t) + (:preserve-breaks nil "\\n" org-export-preserve-breaks) + (:section-numbers nil "num" org-export-with-section-numbers) + (:select-tags "SELECT_TAGS" nil org-export-select-tags split) + (:time-stamp-file nil "timestamp" org-export-time-stamp-file) + (:title "TITLE" nil nil space) + (:with-archived-trees nil "arch" org-export-with-archived-trees) + (:with-author nil "author" org-export-with-author) + (:with-clocks nil "c" org-export-with-clocks) + (:with-creator nil "creator" org-export-with-creator) + (:with-date nil "date" org-export-with-date) + (:with-drawers nil "d" org-export-with-drawers) + (:with-email nil "email" org-export-with-email) + (:with-emphasize nil "*" org-export-with-emphasize) + (:with-entities nil "e" org-export-with-entities) + (:with-fixed-width nil ":" org-export-with-fixed-width) + (:with-footnotes nil "f" org-export-with-footnotes) + (:with-inlinetasks nil "inline" org-export-with-inlinetasks) + (:with-latex nil "tex" org-export-with-latex) + (:with-planning nil "p" org-export-with-planning) + (:with-priority nil "pri" org-export-with-priority) + (:with-smart-quotes nil "'" org-export-with-smart-quotes) + (:with-special-strings nil "-" org-export-with-special-strings) + (:with-statistics-cookies nil "stat" org-export-with-statistics-cookies) + (:with-sub-superscript nil "^" org-export-with-sub-superscripts) + (:with-toc nil "toc" org-export-with-toc) + (:with-tables nil "|" org-export-with-tables) + (:with-tags nil "tags" org-export-with-tags) + (:with-tasks nil "tasks" org-export-with-tasks) + (:with-timestamps nil "<" org-export-with-timestamps) + (:with-todo-keywords nil "todo" org-export-with-todo-keywords)) + "Alist between export properties and ways to set them. + +The CAR of the alist is the property name, and the CDR is a list +like (KEYWORD OPTION DEFAULT BEHAVIOUR) where: + +KEYWORD is a string representing a buffer keyword, or nil. Each + property defined this way can also be set, during subtree + export, through a headline property named after the keyword + with the \"EXPORT_\" prefix (i.e. DATE keyword and EXPORT_DATE + property). +OPTION is a string that could be found in an #+OPTIONS: line. +DEFAULT is the default value for the property. +BEHAVIOUR determines how Org should handle multiple keywords for + the same property. It is a symbol among: + nil Keep old value and discard the new one. + t Replace old value with the new one. + `space' Concatenate the values, separating them with a space. + `newline' Concatenate the values, separating them with + a newline. + `split' Split values at white spaces, and cons them to the + previous list. + +Values set through KEYWORD and OPTION have precedence over +DEFAULT. + +All these properties should be back-end agnostic. Back-end +specific properties are set through `org-export-define-backend'. +Properties redefined there have precedence over these.") + +(defconst org-export-special-keywords '("FILETAGS" "SETUPFILE" "OPTIONS") + "List of in-buffer keywords that require special treatment. +These keywords are not directly associated to a property. The +way they are handled must be hard-coded into +`org-export--get-inbuffer-options' function.") + +(defconst org-export-filters-alist + '((:filter-bold . org-export-filter-bold-functions) + (:filter-babel-call . org-export-filter-babel-call-functions) + (:filter-center-block . org-export-filter-center-block-functions) + (:filter-clock . org-export-filter-clock-functions) + (:filter-code . org-export-filter-code-functions) + (:filter-comment . org-export-filter-comment-functions) + (:filter-comment-block . org-export-filter-comment-block-functions) + (:filter-diary-sexp . org-export-filter-diary-sexp-functions) + (:filter-drawer . org-export-filter-drawer-functions) + (:filter-dynamic-block . org-export-filter-dynamic-block-functions) + (:filter-entity . org-export-filter-entity-functions) + (:filter-example-block . org-export-filter-example-block-functions) + (:filter-export-block . org-export-filter-export-block-functions) + (:filter-export-snippet . org-export-filter-export-snippet-functions) + (:filter-final-output . org-export-filter-final-output-functions) + (:filter-fixed-width . org-export-filter-fixed-width-functions) + (:filter-footnote-definition . org-export-filter-footnote-definition-functions) + (:filter-footnote-reference . org-export-filter-footnote-reference-functions) + (:filter-headline . org-export-filter-headline-functions) + (:filter-horizontal-rule . org-export-filter-horizontal-rule-functions) + (:filter-inline-babel-call . org-export-filter-inline-babel-call-functions) + (:filter-inline-src-block . org-export-filter-inline-src-block-functions) + (:filter-inlinetask . org-export-filter-inlinetask-functions) + (:filter-italic . org-export-filter-italic-functions) + (:filter-item . org-export-filter-item-functions) + (:filter-keyword . org-export-filter-keyword-functions) + (:filter-latex-environment . org-export-filter-latex-environment-functions) + (:filter-latex-fragment . org-export-filter-latex-fragment-functions) + (:filter-line-break . org-export-filter-line-break-functions) + (:filter-link . org-export-filter-link-functions) + (:filter-node-property . org-export-filter-node-property-functions) + (:filter-options . org-export-filter-options-functions) + (:filter-paragraph . org-export-filter-paragraph-functions) + (:filter-parse-tree . org-export-filter-parse-tree-functions) + (:filter-plain-list . org-export-filter-plain-list-functions) + (:filter-plain-text . org-export-filter-plain-text-functions) + (:filter-planning . org-export-filter-planning-functions) + (:filter-property-drawer . org-export-filter-property-drawer-functions) + (:filter-quote-block . org-export-filter-quote-block-functions) + (:filter-quote-section . org-export-filter-quote-section-functions) + (:filter-radio-target . org-export-filter-radio-target-functions) + (:filter-section . org-export-filter-section-functions) + (:filter-special-block . org-export-filter-special-block-functions) + (:filter-src-block . org-export-filter-src-block-functions) + (:filter-statistics-cookie . org-export-filter-statistics-cookie-functions) + (:filter-strike-through . org-export-filter-strike-through-functions) + (:filter-subscript . org-export-filter-subscript-functions) + (:filter-superscript . org-export-filter-superscript-functions) + (:filter-table . org-export-filter-table-functions) + (:filter-table-cell . org-export-filter-table-cell-functions) + (:filter-table-row . org-export-filter-table-row-functions) + (:filter-target . org-export-filter-target-functions) + (:filter-timestamp . org-export-filter-timestamp-functions) + (:filter-underline . org-export-filter-underline-functions) + (:filter-verbatim . org-export-filter-verbatim-functions) + (:filter-verse-block . org-export-filter-verse-block-functions)) + "Alist between filters properties and initial values. + +The key of each association is a property name accessible through +the communication channel. Its value is a configurable global +variable defining initial filters. + +This list is meant to install user specified filters. Back-end +developers may install their own filters using +`org-export-define-backend'. Filters defined there will always +be prepended to the current list, so they always get applied +first.") + +(defconst org-export-default-inline-image-rule + `(("file" . + ,(format "\\.%s\\'" + (regexp-opt + '("png" "jpeg" "jpg" "gif" "tiff" "tif" "xbm" + "xpm" "pbm" "pgm" "ppm") t)))) + "Default rule for link matching an inline image. +This rule applies to links with no description. By default, it +will be considered as an inline image if it targets a local file +whose extension is either \"png\", \"jpeg\", \"jpg\", \"gif\", +\"tiff\", \"tif\", \"xbm\", \"xpm\", \"pbm\", \"pgm\" or \"ppm\". +See `org-export-inline-image-p' for more information about +rules.") + +(defvar org-export-async-debug nil + "Non-nil means asynchronous export process should leave data behind. + +This data is found in the appropriate \"*Org Export Process*\" +buffer, and in files prefixed with \"org-export-process\" and +located in `temporary-file-directory'. + +When non-nil, it will also set `debug-on-error' to a non-nil +value in the external process.") + +(defvar org-export-stack-contents nil + "Record asynchronously generated export results and processes. +This is an alist: its CAR is the source of the +result (destination file or buffer for a finished process, +original buffer for a running one) and its CDR is a list +containing the back-end used, as a symbol, and either a process +or the time at which it finished. It is used to build the menu +from `org-export-stack'.") + +(defvar org-export--registered-backends nil + "List of backends currently available in the exporter. +This variable is set with `org-export-define-backend' and +`org-export-define-derived-backend' functions.") + +(defvar org-export-dispatch-last-action nil + "Last command called from the dispatcher. +The value should be a list. Its CAR is the action, as a symbol, +and its CDR is a list of export options.") + +(defvar org-export-dispatch-last-position (make-marker) + "The position where the last export command was created using the dispatcher. +This marker will be used with `C-u C-c C-e' to make sure export repetition +uses the same subtree if the previous command was restricted to a subtree.") + +;; For compatibility with Org < 8 +(defvar org-export-current-backend nil + "Name, if any, of the back-end used during an export process. + +Its value is a symbol such as `html', `latex', `ascii', or nil if +the back-end is anonymous (see `org-export-create-backend') or if +there is no export process in progress. + +It can be used to teach Babel blocks how to act differently +according to the back-end used.") + + +;;; User-configurable Variables +;; +;; Configuration for the masses. +;; +;; They should never be accessed directly, as their value is to be +;; stored in a property list (cf. `org-export-options-alist'). +;; Back-ends will read their value from there instead. + +(defgroup org-export nil + "Options for exporting Org mode files." + :tag "Org Export" + :group 'org) + +(defgroup org-export-general nil + "General options for export engine." + :tag "Org Export General" + :group 'org-export) + +(defcustom org-export-with-archived-trees 'headline + "Whether sub-trees with the ARCHIVE tag should be exported. + +This can have three different values: +nil Do not export, pretend this tree is not present. +t Do export the entire tree. +`headline' Only export the headline, but skip the tree below it. + +This option can also be set with the OPTIONS keyword, +e.g. \"arch:nil\"." + :group 'org-export-general + :type '(choice + (const :tag "Not at all" nil) + (const :tag "Headline only" headline) + (const :tag "Entirely" t))) + +(defcustom org-export-with-author t + "Non-nil means insert author name into the exported file. +This option can also be set with the OPTIONS keyword, +e.g. \"author:nil\"." + :group 'org-export-general + :type 'boolean) + +(defcustom org-export-with-clocks nil + "Non-nil means export CLOCK keywords. +This option can also be set with the OPTIONS keyword, +e.g. \"c:t\"." + :group 'org-export-general + :type 'boolean) + +(defcustom org-export-with-creator 'comment + "Non-nil means the postamble should contain a creator sentence. + +The sentence can be set in `org-export-creator-string' and +defaults to \"Generated by Org mode XX in Emacs XXX.\". + +If the value is `comment' insert it as a comment." + :group 'org-export-general + :type '(choice + (const :tag "No creator sentence" nil) + (const :tag "Sentence as a comment" 'comment) + (const :tag "Insert the sentence" t))) + +(defcustom org-export-with-date t + "Non-nil means insert date in the exported document. +This option can also be set with the OPTIONS keyword, +e.g. \"date:nil\"." + :group 'org-export-general + :type 'boolean) + +(defcustom org-export-date-timestamp-format nil + "Time-stamp format string to use for DATE keyword. + +The format string, when specified, only applies if date consists +in a single time-stamp. Otherwise its value will be ignored. + +See `format-time-string' for details on how to build this +string." + :group 'org-export-general + :type '(choice + (string :tag "Time-stamp format string") + (const :tag "No format string" nil))) + +(defcustom org-export-creator-string + (format "Emacs %s (Org mode %s)" + emacs-version + (if (fboundp 'org-version) (org-version) "unknown version")) + "Information about the creator of the document. +This option can also be set on with the CREATOR keyword." + :group 'org-export-general + :type '(string :tag "Creator string")) + +(defcustom org-export-with-drawers '(not "LOGBOOK") + "Non-nil means export contents of standard drawers. + +When t, all drawers are exported. This may also be a list of +drawer names to export. If that list starts with `not', only +drawers with such names will be ignored. + +This variable doesn't apply to properties drawers. + +This option can also be set with the OPTIONS keyword, +e.g. \"d:nil\"." + :group 'org-export-general + :version "24.4" + :package-version '(Org . "8.0") + :type '(choice + (const :tag "All drawers" t) + (const :tag "None" nil) + (repeat :tag "Selected drawers" + (string :tag "Drawer name")) + (list :tag "Ignored drawers" + (const :format "" not) + (repeat :tag "Specify names of drawers to ignore during export" + :inline t + (string :tag "Drawer name"))))) + +(defcustom org-export-with-email nil + "Non-nil means insert author email into the exported file. +This option can also be set with the OPTIONS keyword, +e.g. \"email:t\"." + :group 'org-export-general + :type 'boolean) + +(defcustom org-export-with-emphasize t + "Non-nil means interpret *word*, /word/, _word_ and +word+. + +If the export target supports emphasizing text, the word will be +typeset in bold, italic, with an underline or strike-through, +respectively. + +This option can also be set with the OPTIONS keyword, +e.g. \"*:nil\"." + :group 'org-export-general + :type 'boolean) + +(defcustom org-export-exclude-tags '("noexport") + "Tags that exclude a tree from export. + +All trees carrying any of these tags will be excluded from +export. This is without condition, so even subtrees inside that +carry one of the `org-export-select-tags' will be removed. + +This option can also be set with the EXCLUDE_TAGS keyword." + :group 'org-export-general + :type '(repeat (string :tag "Tag"))) + +(defcustom org-export-with-fixed-width t + "Non-nil means lines starting with \":\" will be in fixed width font. + +This can be used to have pre-formatted text, fragments of code +etc. For example: + : ;; Some Lisp examples + : (while (defc cnt) + : (ding)) +will be looking just like this in also HTML. See also the QUOTE +keyword. Not all export backends support this. + +This option can also be set with the OPTIONS keyword, +e.g. \"::nil\"." + :group 'org-export-general + :type 'boolean) + +(defcustom org-export-with-footnotes t + "Non-nil means Org footnotes should be exported. +This option can also be set with the OPTIONS keyword, +e.g. \"f:nil\"." + :group 'org-export-general + :type 'boolean) + +(defcustom org-export-with-latex t + "Non-nil means process LaTeX environments and fragments. + +This option can also be set with the OPTIONS line, +e.g. \"tex:verbatim\". Allowed values are: + +nil Ignore math snippets. +`verbatim' Keep everything in verbatim. +t Allow export of math snippets." + :group 'org-export-general + :version "24.4" + :package-version '(Org . "8.0") + :type '(choice + (const :tag "Do not process math in any way" nil) + (const :tag "Interpret math snippets" t) + (const :tag "Leave math verbatim" verbatim))) + +(defcustom org-export-headline-levels 3 + "The last level which is still exported as a headline. + +Inferior levels will usually produce itemize or enumerate lists +when exported, but back-end behaviour may differ. + +This option can also be set with the OPTIONS keyword, +e.g. \"H:2\"." + :group 'org-export-general + :type 'integer) + +(defcustom org-export-default-language "en" + "The default language for export and clocktable translations, as a string. +This may have an association in +`org-clock-clocktable-language-setup', +`org-export-smart-quotes-alist' and `org-export-dictionary'. +This option can also be set with the LANGUAGE keyword." + :group 'org-export-general + :type '(string :tag "Language")) + +(defcustom org-export-preserve-breaks nil + "Non-nil means preserve all line breaks when exporting. +This option can also be set with the OPTIONS keyword, +e.g. \"\\n:t\"." + :group 'org-export-general + :type 'boolean) + +(defcustom org-export-with-entities t + "Non-nil means interpret entities when exporting. + +For example, HTML export converts \\alpha to α and \\AA to +Å. + +For a list of supported names, see the constant `org-entities' +and the user option `org-entities-user'. + +This option can also be set with the OPTIONS keyword, +e.g. \"e:nil\"." + :group 'org-export-general + :type 'boolean) + +(defcustom org-export-with-inlinetasks t + "Non-nil means inlinetasks should be exported. +This option can also be set with the OPTIONS keyword, +e.g. \"inline:nil\"." + :group 'org-export-general + :version "24.4" + :package-version '(Org . "8.0") + :type 'boolean) + +(defcustom org-export-with-planning nil + "Non-nil means include planning info in export. + +Planning info is the line containing either SCHEDULED:, +DEADLINE:, CLOSED: time-stamps, or a combination of them. + +This option can also be set with the OPTIONS keyword, +e.g. \"p:t\"." + :group 'org-export-general + :version "24.4" + :package-version '(Org . "8.0") + :type 'boolean) + +(defcustom org-export-with-priority nil + "Non-nil means include priority cookies in export. +This option can also be set with the OPTIONS keyword, +e.g. \"pri:t\"." + :group 'org-export-general + :type 'boolean) + +(defcustom org-export-with-section-numbers t + "Non-nil means add section numbers to headlines when exporting. + +When set to an integer n, numbering will only happen for +headlines whose relative level is higher or equal to n. + +This option can also be set with the OPTIONS keyword, +e.g. \"num:t\"." + :group 'org-export-general + :type 'boolean) + +(defcustom org-export-select-tags '("export") + "Tags that select a tree for export. + +If any such tag is found in a buffer, all trees that do not carry +one of these tags will be ignored during export. Inside trees +that are selected like this, you can still deselect a subtree by +tagging it with one of the `org-export-exclude-tags'. + +This option can also be set with the SELECT_TAGS keyword." + :group 'org-export-general + :type '(repeat (string :tag "Tag"))) + +(defcustom org-export-with-smart-quotes nil + "Non-nil means activate smart quotes during export. +This option can also be set with the OPTIONS keyword, +e.g., \"':t\". + +When setting this to non-nil, you need to take care of +using the correct Babel package when exporting to LaTeX. +E.g., you can load Babel for french like this: + +#+LATEX_HEADER: \\usepackage[french]{babel}" + :group 'org-export-general + :version "24.4" + :package-version '(Org . "8.0") + :type 'boolean) + +(defcustom org-export-with-special-strings t + "Non-nil means interpret \"\\-\", \"--\" and \"---\" for export. + +When this option is turned on, these strings will be exported as: + + Org HTML LaTeX UTF-8 + -----+----------+--------+------- + \\- ­ \\- + -- – -- – + --- — --- — + ... … \\ldots … + +This option can also be set with the OPTIONS keyword, +e.g. \"-:nil\"." + :group 'org-export-general + :type 'boolean) + +(defcustom org-export-with-statistics-cookies t + "Non-nil means include statistics cookies in export. +This option can also be set with the OPTIONS keyword, +e.g. \"stat:nil\"" + :group 'org-export-general + :version "24.4" + :package-version '(Org . "8.0") + :type 'boolean) + +(defcustom org-export-with-sub-superscripts t + "Non-nil means interpret \"_\" and \"^\" for export. + +When this option is turned on, you can use TeX-like syntax for +sub- and superscripts. Several characters after \"_\" or \"^\" +will be considered as a single item - so grouping with {} is +normally not needed. For example, the following things will be +parsed as single sub- or superscripts. + + 10^24 or 10^tau several digits will be considered 1 item. + 10^-12 or 10^-tau a leading sign with digits or a word + x^2-y^3 will be read as x^2 - y^3, because items are + terminated by almost any nonword/nondigit char. + x_{i^2} or x^(2-i) braces or parenthesis do grouping. + +Still, ambiguity is possible - so when in doubt use {} to enclose +the sub/superscript. If you set this variable to the symbol +`{}', the braces are *required* in order to trigger +interpretations as sub/superscript. This can be helpful in +documents that need \"_\" frequently in plain text. + +This option can also be set with the OPTIONS keyword, +e.g. \"^:nil\"." + :group 'org-export-general + :type '(choice + (const :tag "Interpret them" t) + (const :tag "Curly brackets only" {}) + (const :tag "Do not interpret them" nil))) + +(defcustom org-export-with-toc t + "Non-nil means create a table of contents in exported files. + +The TOC contains headlines with levels up +to`org-export-headline-levels'. When an integer, include levels +up to N in the toc, this may then be different from +`org-export-headline-levels', but it will not be allowed to be +larger than the number of headline levels. When nil, no table of +contents is made. + +This option can also be set with the OPTIONS keyword, +e.g. \"toc:nil\" or \"toc:3\"." + :group 'org-export-general + :type '(choice + (const :tag "No Table of Contents" nil) + (const :tag "Full Table of Contents" t) + (integer :tag "TOC to level"))) + +(defcustom org-export-with-tables t + "If non-nil, lines starting with \"|\" define a table. +For example: + + | Name | Address | Birthday | + |-------------+----------+-----------| + | Arthur Dent | England | 29.2.2100 | + +This option can also be set with the OPTIONS keyword, +e.g. \"|:nil\"." + :group 'org-export-general + :type 'boolean) + +(defcustom org-export-with-tags t + "If nil, do not export tags, just remove them from headlines. + +If this is the symbol `not-in-toc', tags will be removed from +table of contents entries, but still be shown in the headlines of +the document. + +This option can also be set with the OPTIONS keyword, +e.g. \"tags:nil\"." + :group 'org-export-general + :type '(choice + (const :tag "Off" nil) + (const :tag "Not in TOC" not-in-toc) + (const :tag "On" t))) + +(defcustom org-export-with-tasks t + "Non-nil means include TODO items for export. + +This may have the following values: +t include tasks independent of state. +`todo' include only tasks that are not yet done. +`done' include only tasks that are already done. +nil ignore all tasks. +list of keywords include tasks with these keywords. + +This option can also be set with the OPTIONS keyword, +e.g. \"tasks:nil\"." + :group 'org-export-general + :type '(choice + (const :tag "All tasks" t) + (const :tag "No tasks" nil) + (const :tag "Not-done tasks" todo) + (const :tag "Only done tasks" done) + (repeat :tag "Specific TODO keywords" + (string :tag "Keyword")))) + +(defcustom org-export-time-stamp-file t + "Non-nil means insert a time stamp into the exported file. +The time stamp shows when the file was created. This option can +also be set with the OPTIONS keyword, e.g. \"timestamp:nil\"." + :group 'org-export-general + :type 'boolean) + +(defcustom org-export-with-timestamps t + "Non nil means allow timestamps in export. + +It can be set to any of the following values: + t export all timestamps. + `active' export active timestamps only. + `inactive' export inactive timestamps only. + nil do not export timestamps + +This only applies to timestamps isolated in a paragraph +containing only timestamps. Other timestamps are always +exported. + +This option can also be set with the OPTIONS keyword, e.g. +\"<:nil\"." + :group 'org-export-general + :type '(choice + (const :tag "All timestamps" t) + (const :tag "Only active timestamps" active) + (const :tag "Only inactive timestamps" inactive) + (const :tag "No timestamp" nil))) + +(defcustom org-export-with-todo-keywords t + "Non-nil means include TODO keywords in export. +When nil, remove all these keywords from the export. This option +can also be set with the OPTIONS keyword, e.g. \"todo:nil\"." + :group 'org-export-general + :type 'boolean) + +(defcustom org-export-allow-bind-keywords nil + "Non-nil means BIND keywords can define local variable values. +This is a potential security risk, which is why the default value +is nil. You can also allow them through local buffer variables." + :group 'org-export-general + :version "24.4" + :package-version '(Org . "8.0") + :type 'boolean) + +(defcustom org-export-snippet-translation-alist nil + "Alist between export snippets back-ends and exporter back-ends. + +This variable allows to provide shortcuts for export snippets. + +For example, with a value of '\(\(\"h\" . \"html\"\)\), the +HTML back-end will recognize the contents of \"@@h:@@\" as +HTML code while every other back-end will ignore it." + :group 'org-export-general + :version "24.4" + :package-version '(Org . "8.0") + :type '(repeat + (cons (string :tag "Shortcut") + (string :tag "Back-end")))) + +(defcustom org-export-coding-system nil + "Coding system for the exported file." + :group 'org-export-general + :version "24.4" + :package-version '(Org . "8.0") + :type 'coding-system) + +(defcustom org-export-copy-to-kill-ring 'if-interactive + "Should we push exported content to the kill ring?" + :group 'org-export-general + :version "24.3" + :type '(choice + (const :tag "Always" t) + (const :tag "When export is done interactively" if-interactive) + (const :tag "Never" nil))) + +(defcustom org-export-initial-scope 'buffer + "The initial scope when exporting with `org-export-dispatch'. +This variable can be either set to `buffer' or `subtree'." + :group 'org-export-general + :type '(choice + (const :tag "Export current buffer" buffer) + (const :tag "Export current subtree" subtree))) + +(defcustom org-export-show-temporary-export-buffer t + "Non-nil means show buffer after exporting to temp buffer. +When Org exports to a file, the buffer visiting that file is ever +shown, but remains buried. However, when exporting to +a temporary buffer, that buffer is popped up in a second window. +When this variable is nil, the buffer remains buried also in +these cases." + :group 'org-export-general + :type 'boolean) + +(defcustom org-export-in-background nil + "Non-nil means export and publishing commands will run in background. +Results from an asynchronous export are never displayed +automatically. But you can retrieve them with \\[org-export-stack]." + :group 'org-export-general + :version "24.4" + :package-version '(Org . "8.0") + :type 'boolean) + +(defcustom org-export-async-init-file user-init-file + "File used to initialize external export process. +Value must be an absolute file name. It defaults to user's +initialization file. Though, a specific configuration makes the +process faster and the export more portable." + :group 'org-export-general + :version "24.4" + :package-version '(Org . "8.0") + :type '(file :must-match t)) + +(defcustom org-export-dispatch-use-expert-ui nil + "Non-nil means using a non-intrusive `org-export-dispatch'. +In that case, no help buffer is displayed. Though, an indicator +for current export scope is added to the prompt (\"b\" when +output is restricted to body only, \"s\" when it is restricted to +the current subtree, \"v\" when only visible elements are +considered for export, \"f\" when publishing functions should be +passed the FORCE argument and \"a\" when the export should be +asynchronous). Also, \[?] allows to switch back to standard +mode." + :group 'org-export-general + :version "24.4" + :package-version '(Org . "8.0") + :type 'boolean) + + + +;;; Defining Back-ends +;; +;; An export back-end is a structure with `org-export-backend' type +;; and `name', `parent', `transcoders', `options', `filters', `blocks' +;; and `menu' slots. +;; +;; At the lowest level, a back-end is created with +;; `org-export-create-backend' function. +;; +;; A named back-end can be registered with +;; `org-export-register-backend' function. A registered back-end can +;; later be referred to by its name, with `org-export-get-backend' +;; function. Also, such a back-end can become the parent of a derived +;; back-end from which slot values will be inherited by default. +;; `org-export-derived-backend-p' can check if a given back-end is +;; derived from a list of back-end names. +;; +;; `org-export-get-all-transcoders', `org-export-get-all-options' and +;; `org-export-get-all-filters' return the full alist of transcoders, +;; options and filters, including those inherited from ancestors. +;; +;; At a higher level, `org-export-define-backend' is the standard way +;; to define an export back-end. If the new back-end is similar to +;; a registered back-end, `org-export-define-derived-backend' may be +;; used instead. +;; +;; Eventually `org-export-barf-if-invalid-backend' returns an error +;; when a given back-end hasn't been registered yet. + +(defstruct (org-export-backend (:constructor org-export-create-backend) + (:copier nil)) + name parent transcoders options filters blocks menu) + +(defun org-export-get-backend (name) + "Return export back-end named after NAME. +NAME is a symbol. Return nil if no such back-end is found." + (catch 'found + (dolist (b org-export--registered-backends) + (when (eq (org-export-backend-name b) name) + (throw 'found b))))) + +(defun org-export-register-backend (backend) + "Register BACKEND as a known export back-end. +BACKEND is a structure with `org-export-backend' type." + ;; Refuse to register an unnamed back-end. + (unless (org-export-backend-name backend) + (error "Cannot register a unnamed export back-end")) + ;; Refuse to register a back-end with an unknown parent. + (let ((parent (org-export-backend-parent backend))) + (when (and parent (not (org-export-get-backend parent))) + (error "Cannot use unknown \"%s\" back-end as a parent" parent))) + ;; Register dedicated export blocks in the parser. + (dolist (name (org-export-backend-blocks backend)) + (add-to-list 'org-element-block-name-alist + (cons name 'org-element-export-block-parser))) + ;; If a back-end with the same name as BACKEND is already + ;; registered, replace it with BACKEND. Otherwise, simply add + ;; BACKEND to the list of registered back-ends. + (let ((old (org-export-get-backend (org-export-backend-name backend)))) + (if old (setcar (memq old org-export--registered-backends) backend) + (push backend org-export--registered-backends)))) + +(defun org-export-barf-if-invalid-backend (backend) + "Signal an error if BACKEND isn't defined." + (unless (org-export-backend-p backend) + (error "Unknown \"%s\" back-end: Aborting export" backend))) + +(defun org-export-derived-backend-p (backend &rest backends) + "Non-nil if BACKEND is derived from one of BACKENDS. +BACKEND is an export back-end, as returned by, e.g., +`org-export-create-backend', or a symbol referring to +a registered back-end. BACKENDS is constituted of symbols." + (when (symbolp backend) (setq backend (org-export-get-backend backend))) + (when backend + (catch 'exit + (while (org-export-backend-parent backend) + (when (memq (org-export-backend-name backend) backends) + (throw 'exit t)) + (setq backend + (org-export-get-backend (org-export-backend-parent backend)))) + (memq (org-export-backend-name backend) backends)))) + +(defun org-export-get-all-transcoders (backend) + "Return full translation table for BACKEND. + +BACKEND is an export back-end, as return by, e.g,, +`org-export-create-backend'. Return value is an alist where +keys are element or object types, as symbols, and values are +transcoders. + +Unlike to `org-export-backend-transcoders', this function +also returns transcoders inherited from parent back-ends, +if any." + (when (symbolp backend) (setq backend (org-export-get-backend backend))) + (when backend + (let ((transcoders (org-export-backend-transcoders backend)) + parent) + (while (setq parent (org-export-backend-parent backend)) + (setq backend (org-export-get-backend parent)) + (setq transcoders + (append transcoders (org-export-backend-transcoders backend)))) + transcoders))) + +(defun org-export-get-all-options (backend) + "Return export options for BACKEND. + +BACKEND is an export back-end, as return by, e.g,, +`org-export-create-backend'. See `org-export-options-alist' +for the shape of the return value. + +Unlike to `org-export-backend-options', this function also +returns options inherited from parent back-ends, if any." + (when (symbolp backend) (setq backend (org-export-get-backend backend))) + (when backend + (let ((options (org-export-backend-options backend)) + parent) + (while (setq parent (org-export-backend-parent backend)) + (setq backend (org-export-get-backend parent)) + (setq options (append options (org-export-backend-options backend)))) + options))) + +(defun org-export-get-all-filters (backend) + "Return complete list of filters for BACKEND. + +BACKEND is an export back-end, as return by, e.g,, +`org-export-create-backend'. Return value is an alist where +keys are symbols and values lists of functions. + +Unlike to `org-export-backend-filters', this function also +returns filters inherited from parent back-ends, if any." + (when (symbolp backend) (setq backend (org-export-get-backend backend))) + (when backend + (let ((filters (org-export-backend-filters backend)) + parent) + (while (setq parent (org-export-backend-parent backend)) + (setq backend (org-export-get-backend parent)) + (setq filters (append filters (org-export-backend-filters backend)))) + filters))) + +(defun org-export-define-backend (backend transcoders &rest body) + "Define a new back-end BACKEND. + +TRANSCODERS is an alist between object or element types and +functions handling them. + +These functions should return a string without any trailing +space, or nil. They must accept three arguments: the object or +element itself, its contents or nil when it isn't recursive and +the property list used as a communication channel. + +Contents, when not nil, are stripped from any global indentation +\(although the relative one is preserved). They also always end +with a single newline character. + +If, for a given type, no function is found, that element or +object type will simply be ignored, along with any blank line or +white space at its end. The same will happen if the function +returns the nil value. If that function returns the empty +string, the type will be ignored, but the blank lines or white +spaces will be kept. + +In addition to element and object types, one function can be +associated to the `template' (or `inner-template') symbol and +another one to the `plain-text' symbol. + +The former returns the final transcoded string, and can be used +to add a preamble and a postamble to document's body. It must +accept two arguments: the transcoded string and the property list +containing export options. A function associated to `template' +will not be applied if export has option \"body-only\". +A function associated to `inner-template' is always applied. + +The latter, when defined, is to be called on every text not +recognized as an element or an object. It must accept two +arguments: the text string and the information channel. It is an +appropriate place to protect special chars relative to the +back-end. + +BODY can start with pre-defined keyword arguments. The following +keywords are understood: + + :export-block + + String, or list of strings, representing block names that + will not be parsed. This is used to specify blocks that will + contain raw code specific to the back-end. These blocks + still have to be handled by the relative `export-block' type + translator. + + :filters-alist + + Alist between filters and function, or list of functions, + specific to the back-end. See `org-export-filters-alist' for + a list of all allowed filters. Filters defined here + shouldn't make a back-end test, as it may prevent back-ends + derived from this one to behave properly. + + :menu-entry + + Menu entry for the export dispatcher. It should be a list + like: + + '(KEY DESCRIPTION-OR-ORDINAL ACTION-OR-MENU) + + where : + + KEY is a free character selecting the back-end. + + DESCRIPTION-OR-ORDINAL is either a string or a number. + + If it is a string, is will be used to name the back-end in + its menu entry. If it is a number, the following menu will + be displayed as a sub-menu of the back-end with the same + KEY. Also, the number will be used to determine in which + order such sub-menus will appear (lowest first). + + ACTION-OR-MENU is either a function or an alist. + + If it is an action, it will be called with four + arguments (booleans): ASYNC, SUBTREEP, VISIBLE-ONLY and + BODY-ONLY. See `org-export-as' for further explanations on + some of them. + + If it is an alist, associations should follow the + pattern: + + '(KEY DESCRIPTION ACTION) + + where KEY, DESCRIPTION and ACTION are described above. + + Valid values include: + + '(?m \"My Special Back-end\" my-special-export-function) + + or + + '(?l \"Export to LaTeX\" + \(?p \"As PDF file\" org-latex-export-to-pdf) + \(?o \"As PDF file and open\" + \(lambda (a s v b) + \(if a (org-latex-export-to-pdf t s v b) + \(org-open-file + \(org-latex-export-to-pdf nil s v b))))))) + + or the following, which will be added to the previous + sub-menu, + + '(?l 1 + \((?B \"As TEX buffer (Beamer)\" org-beamer-export-as-latex) + \(?P \"As PDF file (Beamer)\" org-beamer-export-to-pdf))) + + :options-alist + + Alist between back-end specific properties introduced in + communication channel and how their value are acquired. See + `org-export-options-alist' for more information about + structure of the values." + (declare (indent 1)) + (let (blocks filters menu-entry options contents) + (while (keywordp (car body)) + (case (pop body) + (:export-block (let ((names (pop body))) + (setq blocks (if (consp names) (mapcar 'upcase names) + (list (upcase names)))))) + (:filters-alist (setq filters (pop body))) + (:menu-entry (setq menu-entry (pop body))) + (:options-alist (setq options (pop body))) + (t (pop body)))) + (org-export-register-backend + (org-export-create-backend :name backend + :transcoders transcoders + :options options + :filters filters + :blocks blocks + :menu menu-entry)))) + +(defun org-export-define-derived-backend (child parent &rest body) + "Create a new back-end as a variant of an existing one. + +CHILD is the name of the derived back-end. PARENT is the name of +the parent back-end. + +BODY can start with pre-defined keyword arguments. The following +keywords are understood: + + :export-block + + String, or list of strings, representing block names that + will not be parsed. This is used to specify blocks that will + contain raw code specific to the back-end. These blocks + still have to be handled by the relative `export-block' type + translator. + + :filters-alist + + Alist of filters that will overwrite or complete filters + defined in PARENT back-end. See `org-export-filters-alist' + for a list of allowed filters. + + :menu-entry + + Menu entry for the export dispatcher. See + `org-export-define-backend' for more information about the + expected value. + + :options-alist + + Alist of back-end specific properties that will overwrite or + complete those defined in PARENT back-end. Refer to + `org-export-options-alist' for more information about + structure of the values. + + :translate-alist + + Alist of element and object types and transcoders that will + overwrite or complete transcode table from PARENT back-end. + Refer to `org-export-define-backend' for detailed information + about transcoders. + +As an example, here is how one could define \"my-latex\" back-end +as a variant of `latex' back-end with a custom template function: + + \(org-export-define-derived-backend 'my-latex 'latex + :translate-alist '((template . my-latex-template-fun))) + +The back-end could then be called with, for example: + + \(org-export-to-buffer 'my-latex \"*Test my-latex*\")" + (declare (indent 2)) + (let (blocks filters menu-entry options transcoders contents) + (while (keywordp (car body)) + (case (pop body) + (:export-block (let ((names (pop body))) + (setq blocks (if (consp names) (mapcar 'upcase names) + (list (upcase names)))))) + (:filters-alist (setq filters (pop body))) + (:menu-entry (setq menu-entry (pop body))) + (:options-alist (setq options (pop body))) + (:translate-alist (setq transcoders (pop body))) + (t (pop body)))) + (org-export-register-backend + (org-export-create-backend :name child + :parent parent + :transcoders transcoders + :options options + :filters filters + :blocks blocks + :menu menu-entry)))) + + + +;;; The Communication Channel +;; +;; During export process, every function has access to a number of +;; properties. They are of two types: +;; +;; 1. Environment options are collected once at the very beginning of +;; the process, out of the original buffer and configuration. +;; Collecting them is handled by `org-export-get-environment' +;; function. +;; +;; Most environment options are defined through the +;; `org-export-options-alist' variable. +;; +;; 2. Tree properties are extracted directly from the parsed tree, +;; just before export, by `org-export-collect-tree-properties'. +;; +;; Here is the full list of properties available during transcode +;; process, with their category and their value type. +;; +;; + `:author' :: Author's name. +;; - category :: option +;; - type :: string +;; +;; + `:back-end' :: Current back-end used for transcoding. +;; - category :: tree +;; - type :: symbol +;; +;; + `:creator' :: String to write as creation information. +;; - category :: option +;; - type :: string +;; +;; + `:date' :: String to use as date. +;; - category :: option +;; - type :: string +;; +;; + `:description' :: Description text for the current data. +;; - category :: option +;; - type :: string +;; +;; + `:email' :: Author's email. +;; - category :: option +;; - type :: string +;; +;; + `:exclude-tags' :: Tags for exclusion of subtrees from export +;; process. +;; - category :: option +;; - type :: list of strings +;; +;; + `:export-options' :: List of export options available for current +;; process. +;; - category :: none +;; - type :: list of symbols, among `subtree', `body-only' and +;; `visible-only'. +;; +;; + `:exported-data' :: Hash table used for memoizing +;; `org-export-data'. +;; - category :: tree +;; - type :: hash table +;; +;; + `:filetags' :: List of global tags for buffer. Used by +;; `org-export-get-tags' to get tags with inheritance. +;; - category :: option +;; - type :: list of strings +;; +;; + `:footnote-definition-alist' :: Alist between footnote labels and +;; their definition, as parsed data. Only non-inlined footnotes +;; are represented in this alist. Also, every definition isn't +;; guaranteed to be referenced in the parse tree. The purpose of +;; this property is to preserve definitions from oblivion +;; (i.e. when the parse tree comes from a part of the original +;; buffer), it isn't meant for direct use in a back-end. To +;; retrieve a definition relative to a reference, use +;; `org-export-get-footnote-definition' instead. +;; - category :: option +;; - type :: alist (STRING . LIST) +;; +;; + `:headline-levels' :: Maximum level being exported as an +;; headline. Comparison is done with the relative level of +;; headlines in the parse tree, not necessarily with their +;; actual level. +;; - category :: option +;; - type :: integer +;; +;; + `:headline-offset' :: Difference between relative and real level +;; of headlines in the parse tree. For example, a value of -1 +;; means a level 2 headline should be considered as level +;; 1 (cf. `org-export-get-relative-level'). +;; - category :: tree +;; - type :: integer +;; +;; + `:headline-numbering' :: Alist between headlines and their +;; numbering, as a list of numbers +;; (cf. `org-export-get-headline-number'). +;; - category :: tree +;; - type :: alist (INTEGER . LIST) +;; +;; + `:id-alist' :: Alist between ID strings and destination file's +;; path, relative to current directory. It is used by +;; `org-export-resolve-id-link' to resolve ID links targeting an +;; external file. +;; - category :: option +;; - type :: alist (STRING . STRING) +;; +;; + `:ignore-list' :: List of elements and objects that should be +;; ignored during export. +;; - category :: tree +;; - type :: list of elements and objects +;; +;; + `:input-file' :: Full path to input file, if any. +;; - category :: option +;; - type :: string or nil +;; +;; + `:keywords' :: List of keywords attached to data. +;; - category :: option +;; - type :: string +;; +;; + `:language' :: Default language used for translations. +;; - category :: option +;; - type :: string +;; +;; + `:parse-tree' :: Whole parse tree, available at any time during +;; transcoding. +;; - category :: option +;; - type :: list (as returned by `org-element-parse-buffer') +;; +;; + `:preserve-breaks' :: Non-nil means transcoding should preserve +;; all line breaks. +;; - category :: option +;; - type :: symbol (nil, t) +;; +;; + `:section-numbers' :: Non-nil means transcoding should add +;; section numbers to headlines. +;; - category :: option +;; - type :: symbol (nil, t) +;; +;; + `:select-tags' :: List of tags enforcing inclusion of sub-trees +;; in transcoding. When such a tag is present, subtrees without +;; it are de facto excluded from the process. See +;; `use-select-tags'. +;; - category :: option +;; - type :: list of strings +;; +;; + `:time-stamp-file' :: Non-nil means transcoding should insert +;; a time stamp in the output. +;; - category :: option +;; - type :: symbol (nil, t) +;; +;; + `:translate-alist' :: Alist between element and object types and +;; transcoding functions relative to the current back-end. +;; Special keys `inner-template', `template' and `plain-text' are +;; also possible. +;; - category :: option +;; - type :: alist (SYMBOL . FUNCTION) +;; +;; + `:with-archived-trees' :: Non-nil when archived subtrees should +;; also be transcoded. If it is set to the `headline' symbol, +;; only the archived headline's name is retained. +;; - category :: option +;; - type :: symbol (nil, t, `headline') +;; +;; + `:with-author' :: Non-nil means author's name should be included +;; in the output. +;; - category :: option +;; - type :: symbol (nil, t) +;; +;; + `:with-clocks' :: Non-nil means clock keywords should be exported. +;; - category :: option +;; - type :: symbol (nil, t) +;; +;; + `:with-creator' :: Non-nil means a creation sentence should be +;; inserted at the end of the transcoded string. If the value +;; is `comment', it should be commented. +;; - category :: option +;; - type :: symbol (`comment', nil, t) +;; +;; + `:with-date' :: Non-nil means output should contain a date. +;; - category :: option +;; - type :. symbol (nil, t) +;; +;; + `:with-drawers' :: Non-nil means drawers should be exported. If +;; its value is a list of names, only drawers with such names +;; will be transcoded. If that list starts with `not', drawer +;; with these names will be skipped. +;; - category :: option +;; - type :: symbol (nil, t) or list of strings +;; +;; + `:with-email' :: Non-nil means output should contain author's +;; email. +;; - category :: option +;; - type :: symbol (nil, t) +;; +;; + `:with-emphasize' :: Non-nil means emphasized text should be +;; interpreted. +;; - category :: option +;; - type :: symbol (nil, t) +;; +;; + `:with-fixed-width' :: Non-nil if transcoder should interpret +;; strings starting with a colon as a fixed-with (verbatim) area. +;; - category :: option +;; - type :: symbol (nil, t) +;; +;; + `:with-footnotes' :: Non-nil if transcoder should interpret +;; footnotes. +;; - category :: option +;; - type :: symbol (nil, t) +;; +;; + `:with-latex' :: Non-nil means `latex-environment' elements and +;; `latex-fragment' objects should appear in export output. When +;; this property is set to `verbatim', they will be left as-is. +;; - category :: option +;; - type :: symbol (`verbatim', nil, t) +;; +;; + `:with-planning' :: Non-nil means transcoding should include +;; planning info. +;; - category :: option +;; - type :: symbol (nil, t) +;; +;; + `:with-priority' :: Non-nil means transcoding should include +;; priority cookies. +;; - category :: option +;; - type :: symbol (nil, t) +;; +;; + `:with-smart-quotes' :: Non-nil means activate smart quotes in +;; plain text. +;; - category :: option +;; - type :: symbol (nil, t) +;; +;; + `:with-special-strings' :: Non-nil means transcoding should +;; interpret special strings in plain text. +;; - category :: option +;; - type :: symbol (nil, t) +;; +;; + `:with-sub-superscript' :: Non-nil means transcoding should +;; interpret subscript and superscript. With a value of "{}", +;; only interpret those using curly brackets. +;; - category :: option +;; - type :: symbol (nil, {}, t) +;; +;; + `:with-tables' :: Non-nil means transcoding should interpret +;; tables. +;; - category :: option +;; - type :: symbol (nil, t) +;; +;; + `:with-tags' :: Non-nil means transcoding should keep tags in +;; headlines. A `not-in-toc' value will remove them from the +;; table of contents, if any, nonetheless. +;; - category :: option +;; - type :: symbol (nil, t, `not-in-toc') +;; +;; + `:with-tasks' :: Non-nil means transcoding should include +;; headlines with a TODO keyword. A `todo' value will only +;; include headlines with a todo type keyword while a `done' +;; value will do the contrary. If a list of strings is provided, +;; only tasks with keywords belonging to that list will be kept. +;; - category :: option +;; - type :: symbol (t, todo, done, nil) or list of strings +;; +;; + `:with-timestamps' :: Non-nil means transcoding should include +;; time stamps. Special value `active' (resp. `inactive') ask to +;; export only active (resp. inactive) timestamps. Otherwise, +;; completely remove them. +;; - category :: option +;; - type :: symbol: (`active', `inactive', t, nil) +;; +;; + `:with-toc' :: Non-nil means that a table of contents has to be +;; added to the output. An integer value limits its depth. +;; - category :: option +;; - type :: symbol (nil, t or integer) +;; +;; + `:with-todo-keywords' :: Non-nil means transcoding should +;; include TODO keywords. +;; - category :: option +;; - type :: symbol (nil, t) + + +;;;; Environment Options +;; +;; Environment options encompass all parameters defined outside the +;; scope of the parsed data. They come from five sources, in +;; increasing precedence order: +;; +;; - Global variables, +;; - Buffer's attributes, +;; - Options keyword symbols, +;; - Buffer keywords, +;; - Subtree properties. +;; +;; The central internal function with regards to environment options +;; is `org-export-get-environment'. It updates global variables with +;; "#+BIND:" keywords, then retrieve and prioritize properties from +;; the different sources. +;; +;; The internal functions doing the retrieval are: +;; `org-export--get-global-options', +;; `org-export--get-buffer-attributes', +;; `org-export--parse-option-keyword', +;; `org-export--get-subtree-options' and +;; `org-export--get-inbuffer-options' +;; +;; Also, `org-export--list-bound-variables' collects bound variables +;; along with their value in order to set them as buffer local +;; variables later in the process. + +(defun org-export-get-environment (&optional backend subtreep ext-plist) + "Collect export options from the current buffer. + +Optional argument BACKEND is an export back-end, as returned by +`org-export-create-backend'. + +When optional argument SUBTREEP is non-nil, assume the export is +done against the current sub-tree. + +Third optional argument EXT-PLIST is a property list with +external parameters overriding Org default settings, but still +inferior to file-local settings." + ;; First install #+BIND variables since these must be set before + ;; global options are read. + (dolist (pair (org-export--list-bound-variables)) + (org-set-local (car pair) (nth 1 pair))) + ;; Get and prioritize export options... + (org-combine-plists + ;; ... from global variables... + (org-export--get-global-options backend) + ;; ... from an external property list... + ext-plist + ;; ... from in-buffer settings... + (org-export--get-inbuffer-options backend) + ;; ... and from subtree, when appropriate. + (and subtreep (org-export--get-subtree-options backend)) + ;; Eventually add misc. properties. + (list + :back-end + backend + :translate-alist (org-export-get-all-transcoders backend) + :footnote-definition-alist + ;; Footnotes definitions must be collected in the original + ;; buffer, as there's no insurance that they will still be in + ;; the parse tree, due to possible narrowing. + (let (alist) + (org-with-wide-buffer + (goto-char (point-min)) + (while (re-search-forward org-footnote-definition-re nil t) + (let ((def (save-match-data (org-element-at-point)))) + (when (eq (org-element-type def) 'footnote-definition) + (push + (cons (org-element-property :label def) + (let ((cbeg (org-element-property :contents-begin def))) + (when cbeg + (org-element--parse-elements + cbeg (org-element-property :contents-end def) + nil nil nil nil (list 'org-data nil))))) + alist)))) + alist)) + :id-alist + ;; Collect id references. + (let (alist) + (org-with-wide-buffer + (goto-char (point-min)) + (while (re-search-forward "\\[\\[id:\\S-+?\\]" nil t) + (let ((link (org-element-context))) + (when (eq (org-element-type link) 'link) + (let* ((id (org-element-property :path link)) + (file (org-id-find-id-file id))) + (when file + (push (cons id (file-relative-name file)) alist))))))) + alist)))) + +(defun org-export--parse-option-keyword (options &optional backend) + "Parse an OPTIONS line and return values as a plist. +Optional argument BACKEND is an export back-end, as returned by, +e.g., `org-export-create-backend'. It specifies which back-end +specific items to read, if any." + (let* ((all + ;; Priority is given to back-end specific options. + (append (and backend (org-export-get-all-options backend)) + org-export-options-alist)) + plist) + (dolist (option all) + (let ((property (car option)) + (item (nth 2 option))) + (when (and item + (not (plist-member plist property)) + (string-match (concat "\\(\\`\\|[ \t]\\)" + (regexp-quote item) + ":\\(([^)\n]+)\\|[^ \t\n\r;,.]*\\)") + options)) + (setq plist (plist-put plist + property + (car (read-from-string + (match-string 2 options)))))))) + plist)) + +(defun org-export--get-subtree-options (&optional backend) + "Get export options in subtree at point. +Optional argument BACKEND is an export back-end, as returned by, +e.g., `org-export-create-backend'. It specifies back-end used +for export. Return options as a plist." + ;; For each buffer keyword, create a headline property setting the + ;; same property in communication channel. The name for the property + ;; is the keyword with "EXPORT_" appended to it. + (org-with-wide-buffer + (let (prop plist) + ;; Make sure point is at a heading. + (if (org-at-heading-p) (org-up-heading-safe) (org-back-to-heading t)) + ;; Take care of EXPORT_TITLE. If it isn't defined, use headline's + ;; title as its fallback value. + (when (setq prop (or (org-entry-get (point) "EXPORT_TITLE") + (progn (looking-at org-todo-line-regexp) + (org-match-string-no-properties 3)))) + (setq plist + (plist-put + plist :title + (org-element-parse-secondary-string + prop (org-element-restriction 'keyword))))) + ;; EXPORT_OPTIONS are parsed in a non-standard way. + (when (setq prop (org-entry-get (point) "EXPORT_OPTIONS")) + (setq plist + (nconc plist (org-export--parse-option-keyword prop backend)))) + ;; Handle other keywords. TITLE keyword is excluded as it has + ;; been handled already. + (let ((seen '("TITLE"))) + (mapc + (lambda (option) + (let ((property (car option)) + (keyword (nth 1 option))) + (when (and keyword (not (member keyword seen))) + (let* ((subtree-prop (concat "EXPORT_" keyword)) + ;; Export properties are not case-sensitive. + (value (let ((case-fold-search t)) + (org-entry-get (point) subtree-prop)))) + (push keyword seen) + (when (and value (not (plist-member plist property))) + (setq plist + (plist-put + plist + property + (cond + ;; Parse VALUE if required. + ((member keyword org-element-document-properties) + (org-element-parse-secondary-string + value (org-element-restriction 'keyword))) + ;; If BEHAVIOUR is `split' expected value is + ;; a list of strings, not a string. + ((eq (nth 4 option) 'split) (org-split-string value)) + (t value))))))))) + ;; Look for both general keywords and back-end specific + ;; options, with priority given to the latter. + (append (and backend (org-export-get-all-options backend)) + org-export-options-alist))) + ;; Return value. + plist))) + +(defun org-export--get-inbuffer-options (&optional backend) + "Return current buffer export options, as a plist. + +Optional argument BACKEND, when non-nil, is an export back-end, +as returned by, e.g., `org-export-create-backend'. It specifies +which back-end specific options should also be read in the +process. + +Assume buffer is in Org mode. Narrowing, if any, is ignored." + (let* (plist + get-options ; For byte-compiler. + (case-fold-search t) + (options (append + ;; Priority is given to back-end specific options. + (and backend (org-export-get-all-options backend)) + org-export-options-alist)) + (regexp (format "^[ \t]*#\\+%s:" + (regexp-opt (nconc (delq nil (mapcar 'cadr options)) + org-export-special-keywords)))) + (find-properties + (lambda (keyword) + ;; Return all properties associated to KEYWORD. + (let (properties) + (dolist (option options properties) + (when (equal (nth 1 option) keyword) + (pushnew (car option) properties)))))) + (get-options + (lambda (&optional files plist) + ;; Recursively read keywords in buffer. FILES is a list + ;; of files read so far. PLIST is the current property + ;; list obtained. + (org-with-wide-buffer + (goto-char (point-min)) + (while (re-search-forward regexp nil t) + (let ((element (org-element-at-point))) + (when (eq (org-element-type element) 'keyword) + (let ((key (org-element-property :key element)) + (val (org-element-property :value element))) + (cond + ;; Options in `org-export-special-keywords'. + ((equal key "SETUPFILE") + (let ((file (expand-file-name + (org-remove-double-quotes (org-trim val))))) + ;; Avoid circular dependencies. + (unless (member file files) + (with-temp-buffer + (insert (org-file-contents file 'noerror)) + (let ((org-inhibit-startup t)) (org-mode)) + (setq plist (funcall get-options + (cons file files) plist)))))) + ((equal key "OPTIONS") + (setq plist + (org-combine-plists + plist + (org-export--parse-option-keyword val backend)))) + ((equal key "FILETAGS") + (setq plist + (org-combine-plists + plist + (list :filetags + (org-uniquify + (append (org-split-string val ":") + (plist-get plist :filetags))))))) + (t + ;; Options in `org-export-options-alist'. + (dolist (property (funcall find-properties key)) + (let ((behaviour (nth 4 (assq property options)))) + (setq plist + (plist-put + plist property + ;; Handle value depending on specified + ;; BEHAVIOUR. + (case behaviour + (space + (if (not (plist-get plist property)) + (org-trim val) + (concat (plist-get plist property) + " " + (org-trim val)))) + (newline + (org-trim + (concat (plist-get plist property) + "\n" + (org-trim val)))) + (split `(,@(plist-get plist property) + ,@(org-split-string val))) + ('t val) + (otherwise + (if (not (plist-member plist property)) val + (plist-get plist property)))))))))))))) + ;; Return final value. + plist)))) + ;; Read options in the current buffer. + (setq plist (funcall get-options + (and buffer-file-name (list buffer-file-name)) nil)) + ;; Parse keywords specified in `org-element-document-properties' + ;; and return PLIST. + (dolist (keyword org-element-document-properties plist) + (dolist (property (funcall find-properties keyword)) + (let ((value (plist-get plist property))) + (when (stringp value) + (setq plist + (plist-put plist property + (org-element-parse-secondary-string + value (org-element-restriction 'keyword)))))))))) + +(defun org-export--get-buffer-attributes () + "Return properties related to buffer attributes, as a plist." + ;; Store full path of input file name, or nil. For internal use. + (let ((visited-file (buffer-file-name (buffer-base-buffer)))) + (list :input-file visited-file + :title (if (not visited-file) (buffer-name (buffer-base-buffer)) + (file-name-sans-extension + (file-name-nondirectory visited-file)))))) + +(defun org-export--get-global-options (&optional backend) + "Return global export options as a plist. +Optional argument BACKEND, if non-nil, is an export back-end, as +returned by, e.g., `org-export-create-backend'. It specifies +which back-end specific export options should also be read in the +process." + (let (plist + ;; Priority is given to back-end specific options. + (all (append (and backend (org-export-get-all-options backend)) + org-export-options-alist))) + (dolist (cell all plist) + (let ((prop (car cell)) + (default-value (nth 3 cell))) + (unless (or (not default-value) (plist-member plist prop)) + (setq plist + (plist-put + plist + prop + ;; Eval default value provided. If keyword is + ;; a member of `org-element-document-properties', + ;; parse it as a secondary string before storing it. + (let ((value (eval (nth 3 cell)))) + (if (not (stringp value)) value + (let ((keyword (nth 1 cell))) + (if (member keyword org-element-document-properties) + (org-element-parse-secondary-string + value (org-element-restriction 'keyword)) + value))))))))))) + +(defun org-export--list-bound-variables () + "Return variables bound from BIND keywords in current buffer. +Also look for BIND keywords in setup files. The return value is +an alist where associations are (VARIABLE-NAME VALUE)." + (when org-export-allow-bind-keywords + (let* (collect-bind ; For byte-compiler. + (collect-bind + (lambda (files alist) + ;; Return an alist between variable names and their + ;; value. FILES is a list of setup files names read so + ;; far, used to avoid circular dependencies. ALIST is + ;; the alist collected so far. + (let ((case-fold-search t)) + (org-with-wide-buffer + (goto-char (point-min)) + (while (re-search-forward + "^[ \t]*#\\+\\(BIND\\|SETUPFILE\\):" nil t) + (let ((element (org-element-at-point))) + (when (eq (org-element-type element) 'keyword) + (let ((val (org-element-property :value element))) + (if (equal (org-element-property :key element) "BIND") + (push (read (format "(%s)" val)) alist) + ;; Enter setup file. + (let ((file (expand-file-name + (org-remove-double-quotes val)))) + (unless (member file files) + (with-temp-buffer + (let ((org-inhibit-startup t)) (org-mode)) + (insert (org-file-contents file 'noerror)) + (setq alist + (funcall collect-bind + (cons file files) + alist)))))))))) + alist))))) + ;; Return value in appropriate order of appearance. + (nreverse (funcall collect-bind nil nil))))) + + +;;;; Tree Properties +;; +;; Tree properties are information extracted from parse tree. They +;; are initialized at the beginning of the transcoding process by +;; `org-export-collect-tree-properties'. +;; +;; Dedicated functions focus on computing the value of specific tree +;; properties during initialization. Thus, +;; `org-export--populate-ignore-list' lists elements and objects that +;; should be skipped during export, `org-export--get-min-level' gets +;; the minimal exportable level, used as a basis to compute relative +;; level for headlines. Eventually +;; `org-export--collect-headline-numbering' builds an alist between +;; headlines and their numbering. + +(defun org-export-collect-tree-properties (data info) + "Extract tree properties from parse tree. + +DATA is the parse tree from which information is retrieved. INFO +is a list holding export options. + +Following tree properties are set or updated: + +`:exported-data' Hash table used to memoize results from + `org-export-data'. + +`:footnote-definition-alist' List of footnotes definitions in + original buffer and current parse tree. + +`:headline-offset' Offset between true level of headlines and + local level. An offset of -1 means a headline + of level 2 should be considered as a level + 1 headline in the context. + +`:headline-numbering' Alist of all headlines as key an the + associated numbering as value. + +`:ignore-list' List of elements that should be ignored during + export. + +Return updated plist." + ;; Install the parse tree in the communication channel, in order to + ;; use `org-export-get-genealogy' and al. + (setq info (plist-put info :parse-tree data)) + ;; Get the list of elements and objects to ignore, and put it into + ;; `:ignore-list'. Do not overwrite any user ignore that might have + ;; been done during parse tree filtering. + (setq info + (plist-put info + :ignore-list + (append (org-export--populate-ignore-list data info) + (plist-get info :ignore-list)))) + ;; Compute `:headline-offset' in order to be able to use + ;; `org-export-get-relative-level'. + (setq info + (plist-put info + :headline-offset + (- 1 (org-export--get-min-level data info)))) + ;; Update footnotes definitions list with definitions in parse tree. + ;; This is required since buffer expansion might have modified + ;; boundaries of footnote definitions contained in the parse tree. + ;; This way, definitions in `footnote-definition-alist' are bound to + ;; match those in the parse tree. + (let ((defs (plist-get info :footnote-definition-alist))) + (org-element-map data 'footnote-definition + (lambda (fn) + (push (cons (org-element-property :label fn) + `(org-data nil ,@(org-element-contents fn))) + defs))) + (setq info (plist-put info :footnote-definition-alist defs))) + ;; Properties order doesn't matter: get the rest of the tree + ;; properties. + (nconc + `(:headline-numbering ,(org-export--collect-headline-numbering data info) + :exported-data ,(make-hash-table :test 'eq :size 4001)) + info)) + +(defun org-export--get-min-level (data options) + "Return minimum exportable headline's level in DATA. +DATA is parsed tree as returned by `org-element-parse-buffer'. +OPTIONS is a plist holding export options." + (catch 'exit + (let ((min-level 10000)) + (mapc + (lambda (blob) + (when (and (eq (org-element-type blob) 'headline) + (not (org-element-property :footnote-section-p blob)) + (not (memq blob (plist-get options :ignore-list)))) + (setq min-level (min (org-element-property :level blob) min-level))) + (when (= min-level 1) (throw 'exit 1))) + (org-element-contents data)) + ;; If no headline was found, for the sake of consistency, set + ;; minimum level to 1 nonetheless. + (if (= min-level 10000) 1 min-level)))) + +(defun org-export--collect-headline-numbering (data options) + "Return numbering of all exportable headlines in a parse tree. + +DATA is the parse tree. OPTIONS is the plist holding export +options. + +Return an alist whose key is a headline and value is its +associated numbering \(in the shape of a list of numbers\) or nil +for a footnotes section." + (let ((numbering (make-vector org-export-max-depth 0))) + (org-element-map data 'headline + (lambda (headline) + (unless (org-element-property :footnote-section-p headline) + (let ((relative-level + (1- (org-export-get-relative-level headline options)))) + (cons + headline + (loop for n across numbering + for idx from 0 to org-export-max-depth + when (< idx relative-level) collect n + when (= idx relative-level) collect (aset numbering idx (1+ n)) + when (> idx relative-level) do (aset numbering idx 0)))))) + options))) + +(defun org-export--populate-ignore-list (data options) + "Return list of elements and objects to ignore during export. +DATA is the parse tree to traverse. OPTIONS is the plist holding +export options." + (let* (ignore + walk-data + ;; First find trees containing a select tag, if any. + (selected (org-export--selected-trees data options)) + (walk-data + (lambda (data) + ;; Collect ignored elements or objects into IGNORE-LIST. + (let ((type (org-element-type data))) + (if (org-export--skip-p data options selected) (push data ignore) + (if (and (eq type 'headline) + (eq (plist-get options :with-archived-trees) 'headline) + (org-element-property :archivedp data)) + ;; If headline is archived but tree below has + ;; to be skipped, add it to ignore list. + (mapc (lambda (e) (push e ignore)) + (org-element-contents data)) + ;; Move into secondary string, if any. + (let ((sec-prop + (cdr (assq type org-element-secondary-value-alist)))) + (when sec-prop + (mapc walk-data (org-element-property sec-prop data)))) + ;; Move into recursive objects/elements. + (mapc walk-data (org-element-contents data)))))))) + ;; Main call. + (funcall walk-data data) + ;; Return value. + ignore)) + +(defun org-export--selected-trees (data info) + "Return list of headlines and inlinetasks with a select tag in their tree. +DATA is parsed data as returned by `org-element-parse-buffer'. +INFO is a plist holding export options." + (let* (selected-trees + walk-data ; For byte-compiler. + (walk-data + (function + (lambda (data genealogy) + (let ((type (org-element-type data))) + (cond + ((memq type '(headline inlinetask)) + (let ((tags (org-element-property :tags data))) + (if (loop for tag in (plist-get info :select-tags) + thereis (member tag tags)) + ;; When a select tag is found, mark full + ;; genealogy and every headline within the tree + ;; as acceptable. + (setq selected-trees + (append + genealogy + (org-element-map data '(headline inlinetask) + 'identity) + selected-trees)) + ;; If at a headline, continue searching in tree, + ;; recursively. + (when (eq type 'headline) + (mapc (lambda (el) + (funcall walk-data el (cons data genealogy))) + (org-element-contents data)))))) + ((or (eq type 'org-data) + (memq type org-element-greater-elements)) + (mapc (lambda (el) (funcall walk-data el genealogy)) + (org-element-contents data))))))))) + (funcall walk-data data nil) + selected-trees)) + +(defun org-export--skip-p (blob options selected) + "Non-nil when element or object BLOB should be skipped during export. +OPTIONS is the plist holding export options. SELECTED, when +non-nil, is a list of headlines or inlinetasks belonging to +a tree with a select tag." + (case (org-element-type blob) + (clock (not (plist-get options :with-clocks))) + (drawer + (let ((with-drawers-p (plist-get options :with-drawers))) + (or (not with-drawers-p) + (and (consp with-drawers-p) + ;; If `:with-drawers' value starts with `not', ignore + ;; every drawer whose name belong to that list. + ;; Otherwise, ignore drawers whose name isn't in that + ;; list. + (let ((name (org-element-property :drawer-name blob))) + (if (eq (car with-drawers-p) 'not) + (member-ignore-case name (cdr with-drawers-p)) + (not (member-ignore-case name with-drawers-p)))))))) + ((footnote-definition footnote-reference) + (not (plist-get options :with-footnotes))) + ((headline inlinetask) + (let ((with-tasks (plist-get options :with-tasks)) + (todo (org-element-property :todo-keyword blob)) + (todo-type (org-element-property :todo-type blob)) + (archived (plist-get options :with-archived-trees)) + (tags (org-element-property :tags blob))) + (or + (and (eq (org-element-type blob) 'inlinetask) + (not (plist-get options :with-inlinetasks))) + ;; Ignore subtrees with an exclude tag. + (loop for k in (plist-get options :exclude-tags) + thereis (member k tags)) + ;; When a select tag is present in the buffer, ignore any tree + ;; without it. + (and selected (not (memq blob selected))) + ;; Ignore commented sub-trees. + (org-element-property :commentedp blob) + ;; Ignore archived subtrees if `:with-archived-trees' is nil. + (and (not archived) (org-element-property :archivedp blob)) + ;; Ignore tasks, if specified by `:with-tasks' property. + (and todo + (or (not with-tasks) + (and (memq with-tasks '(todo done)) + (not (eq todo-type with-tasks))) + (and (consp with-tasks) (not (member todo with-tasks)))))))) + ((latex-environment latex-fragment) (not (plist-get options :with-latex))) + (planning (not (plist-get options :with-planning))) + (statistics-cookie (not (plist-get options :with-statistics-cookies))) + (table-cell + (and (org-export-table-has-special-column-p + (org-export-get-parent-table blob)) + (not (org-export-get-previous-element blob options)))) + (table-row (org-export-table-row-is-special-p blob options)) + (timestamp + ;; `:with-timestamps' only applies to isolated timestamps + ;; objects, i.e. timestamp objects in a paragraph containing only + ;; timestamps and whitespaces. + (when (let ((parent (org-export-get-parent-element blob))) + (and (memq (org-element-type parent) '(paragraph verse-block)) + (not (org-element-map parent + (cons 'plain-text + (remq 'timestamp org-element-all-objects)) + (lambda (obj) + (or (not (stringp obj)) (org-string-nw-p obj))) + options t)))) + (case (plist-get options :with-timestamps) + ('nil t) + (active + (not (memq (org-element-property :type blob) '(active active-range)))) + (inactive + (not (memq (org-element-property :type blob) + '(inactive inactive-range))))))))) + + +;;; The Transcoder +;; +;; `org-export-data' reads a parse tree (obtained with, i.e. +;; `org-element-parse-buffer') and transcodes it into a specified +;; back-end output. It takes care of filtering out elements or +;; objects according to export options and organizing the output blank +;; lines and white space are preserved. The function memoizes its +;; results, so it is cheap to call it within transcoders. +;; +;; It is possible to modify locally the back-end used by +;; `org-export-data' or even use a temporary back-end by using +;; `org-export-data-with-backend'. +;; +;; Internally, three functions handle the filtering of objects and +;; elements during the export. In particular, +;; `org-export-ignore-element' marks an element or object so future +;; parse tree traversals skip it, `org-export--interpret-p' tells which +;; elements or objects should be seen as real Org syntax and +;; `org-export-expand' transforms the others back into their original +;; shape +;; +;; `org-export-transcoder' is an accessor returning appropriate +;; translator function for a given element or object. + +(defun org-export-transcoder (blob info) + "Return appropriate transcoder for BLOB. +INFO is a plist containing export directives." + (let ((type (org-element-type blob))) + ;; Return contents only for complete parse trees. + (if (eq type 'org-data) (lambda (blob contents info) contents) + (let ((transcoder (cdr (assq type (plist-get info :translate-alist))))) + (and (functionp transcoder) transcoder))))) + +(defun org-export-data (data info) + "Convert DATA into current back-end format. + +DATA is a parse tree, an element or an object or a secondary +string. INFO is a plist holding export options. + +Return transcoded string." + (let ((memo (gethash data (plist-get info :exported-data) 'no-memo))) + (if (not (eq memo 'no-memo)) memo + (let* ((type (org-element-type data)) + (results + (cond + ;; Ignored element/object. + ((memq data (plist-get info :ignore-list)) nil) + ;; Plain text. + ((eq type 'plain-text) + (org-export-filter-apply-functions + (plist-get info :filter-plain-text) + (let ((transcoder (org-export-transcoder data info))) + (if transcoder (funcall transcoder data info) data)) + info)) + ;; Uninterpreted element/object: change it back to Org + ;; syntax and export again resulting raw string. + ((not (org-export--interpret-p data info)) + (org-export-data + (org-export-expand + data + (mapconcat (lambda (blob) (org-export-data blob info)) + (org-element-contents data) + "")) + info)) + ;; Secondary string. + ((not type) + (mapconcat (lambda (obj) (org-export-data obj info)) data "")) + ;; Element/Object without contents or, as a special case, + ;; headline with archive tag and archived trees restricted + ;; to title only. + ((or (not (org-element-contents data)) + (and (eq type 'headline) + (eq (plist-get info :with-archived-trees) 'headline) + (org-element-property :archivedp data))) + (let ((transcoder (org-export-transcoder data info))) + (or (and (functionp transcoder) + (funcall transcoder data nil info)) + ;; Export snippets never return a nil value so + ;; that white spaces following them are never + ;; ignored. + (and (eq type 'export-snippet) "")))) + ;; Element/Object with contents. + (t + (let ((transcoder (org-export-transcoder data info))) + (when transcoder + (let* ((greaterp (memq type org-element-greater-elements)) + (objectp + (and (not greaterp) + (memq type org-element-recursive-objects))) + (contents + (mapconcat + (lambda (element) (org-export-data element info)) + (org-element-contents + (if (or greaterp objectp) data + ;; Elements directly containing objects + ;; must have their indentation normalized + ;; first. + (org-element-normalize-contents + data + ;; When normalizing contents of the first + ;; paragraph in an item or a footnote + ;; definition, ignore first line's + ;; indentation: there is none and it + ;; might be misleading. + (when (eq type 'paragraph) + (let ((parent (org-export-get-parent data))) + (and + (eq (car (org-element-contents parent)) + data) + (memq (org-element-type parent) + '(footnote-definition item)))))))) + ""))) + (funcall transcoder data + (if (not greaterp) contents + (org-element-normalize-string contents)) + info)))))))) + ;; Final result will be memoized before being returned. + (puthash + data + (cond + ((not results) nil) + ((memq type '(org-data plain-text nil)) results) + ;; Append the same white space between elements or objects as in + ;; the original buffer, and call appropriate filters. + (t + (let ((results + (org-export-filter-apply-functions + (plist-get info (intern (format ":filter-%s" type))) + (let ((post-blank (or (org-element-property :post-blank data) + 0))) + (if (memq type org-element-all-elements) + (concat (org-element-normalize-string results) + (make-string post-blank ?\n)) + (concat results (make-string post-blank ? )))) + info))) + results))) + (plist-get info :exported-data)))))) + +(defun org-export-data-with-backend (data backend info) + "Convert DATA into BACKEND format. + +DATA is an element, an object, a secondary string or a string. +BACKEND is a symbol. INFO is a plist used as a communication +channel. + +Unlike to `org-export-with-backend', this function will +recursively convert DATA using BACKEND translation table." + (when (symbolp backend) (setq backend (org-export-get-backend backend))) + (org-export-data + data + ;; Set-up a new communication channel with translations defined in + ;; BACKEND as the translate table and a new hash table for + ;; memoization. + (org-combine-plists + info + (list :back-end backend + :translate-alist (org-export-get-all-transcoders backend) + ;; Size of the hash table is reduced since this function + ;; will probably be used on small trees. + :exported-data (make-hash-table :test 'eq :size 401))))) + +(defun org-export--interpret-p (blob info) + "Non-nil if element or object BLOB should be interpreted during export. +If nil, BLOB will appear as raw Org syntax. Check is done +according to export options INFO, stored as a plist." + (case (org-element-type blob) + ;; ... entities... + (entity (plist-get info :with-entities)) + ;; ... emphasis... + ((bold italic strike-through underline) + (plist-get info :with-emphasize)) + ;; ... fixed-width areas. + (fixed-width (plist-get info :with-fixed-width)) + ;; ... LaTeX environments and fragments... + ((latex-environment latex-fragment) + (let ((with-latex-p (plist-get info :with-latex))) + (and with-latex-p (not (eq with-latex-p 'verbatim))))) + ;; ... sub/superscripts... + ((subscript superscript) + (let ((sub/super-p (plist-get info :with-sub-superscript))) + (if (eq sub/super-p '{}) + (org-element-property :use-brackets-p blob) + sub/super-p))) + ;; ... tables... + (table (plist-get info :with-tables)) + (otherwise t))) + +(defun org-export-expand (blob contents &optional with-affiliated) + "Expand a parsed element or object to its original state. + +BLOB is either an element or an object. CONTENTS is its +contents, as a string or nil. + +When optional argument WITH-AFFILIATED is non-nil, add affiliated +keywords before output." + (let ((type (org-element-type blob))) + (concat (and with-affiliated (memq type org-element-all-elements) + (org-element--interpret-affiliated-keywords blob)) + (funcall (intern (format "org-element-%s-interpreter" type)) + blob contents)))) + +(defun org-export-ignore-element (element info) + "Add ELEMENT to `:ignore-list' in INFO. + +Any element in `:ignore-list' will be skipped when using +`org-element-map'. INFO is modified by side effects." + (plist-put info :ignore-list (cons element (plist-get info :ignore-list)))) + + + +;;; The Filter System +;; +;; Filters allow end-users to tweak easily the transcoded output. +;; They are the functional counterpart of hooks, as every filter in +;; a set is applied to the return value of the previous one. +;; +;; Every set is back-end agnostic. Although, a filter is always +;; called, in addition to the string it applies to, with the back-end +;; used as argument, so it's easy for the end-user to add back-end +;; specific filters in the set. The communication channel, as +;; a plist, is required as the third argument. +;; +;; From the developer side, filters sets can be installed in the +;; process with the help of `org-export-define-backend', which +;; internally stores filters as an alist. Each association has a key +;; among the following symbols and a function or a list of functions +;; as value. +;; +;; - `:filter-options' applies to the property list containing export +;; options. Unlike to other filters, functions in this list accept +;; two arguments instead of three: the property list containing +;; export options and the back-end. Users can set its value through +;; `org-export-filter-options-functions' variable. +;; +;; - `:filter-parse-tree' applies directly to the complete parsed +;; tree. Users can set it through +;; `org-export-filter-parse-tree-functions' variable. +;; +;; - `:filter-final-output' applies to the final transcoded string. +;; Users can set it with `org-export-filter-final-output-functions' +;; variable +;; +;; - `:filter-plain-text' applies to any string not recognized as Org +;; syntax. `org-export-filter-plain-text-functions' allows users to +;; configure it. +;; +;; - `:filter-TYPE' applies on the string returned after an element or +;; object of type TYPE has been transcoded. A user can modify +;; `org-export-filter-TYPE-functions' +;; +;; All filters sets are applied with +;; `org-export-filter-apply-functions' function. Filters in a set are +;; applied in a LIFO fashion. It allows developers to be sure that +;; their filters will be applied first. +;; +;; Filters properties are installed in communication channel with +;; `org-export-install-filters' function. +;; +;; Eventually, two hooks (`org-export-before-processing-hook' and +;; `org-export-before-parsing-hook') are run at the beginning of the +;; export process and just before parsing to allow for heavy structure +;; modifications. + + +;;;; Hooks + +(defvar org-export-before-processing-hook nil + "Hook run at the beginning of the export process. + +This is run before include keywords and macros are expanded and +Babel code blocks executed, on a copy of the original buffer +being exported. Visibility and narrowing are preserved. Point +is at the beginning of the buffer. + +Every function in this hook will be called with one argument: the +back-end currently used, as a symbol.") + +(defvar org-export-before-parsing-hook nil + "Hook run before parsing an export buffer. + +This is run after include keywords and macros have been expanded +and Babel code blocks executed, on a copy of the original buffer +being exported. Visibility and narrowing are preserved. Point +is at the beginning of the buffer. + +Every function in this hook will be called with one argument: the +back-end currently used, as a symbol.") + + +;;;; Special Filters + +(defvar org-export-filter-options-functions nil + "List of functions applied to the export options. +Each filter is called with two arguments: the export options, as +a plist, and the back-end, as a symbol. It must return +a property list containing export options.") + +(defvar org-export-filter-parse-tree-functions nil + "List of functions applied to the parsed tree. +Each filter is called with three arguments: the parse tree, as +returned by `org-element-parse-buffer', the back-end, as +a symbol, and the communication channel, as a plist. It must +return the modified parse tree to transcode.") + +(defvar org-export-filter-plain-text-functions nil + "List of functions applied to plain text. +Each filter is called with three arguments: a string which +contains no Org syntax, the back-end, as a symbol, and the +communication channel, as a plist. It must return a string or +nil.") + +(defvar org-export-filter-final-output-functions nil + "List of functions applied to the transcoded string. +Each filter is called with three arguments: the full transcoded +string, the back-end, as a symbol, and the communication channel, +as a plist. It must return a string that will be used as the +final export output.") + + +;;;; Elements Filters + +(defvar org-export-filter-babel-call-functions nil + "List of functions applied to a transcoded babel-call. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-center-block-functions nil + "List of functions applied to a transcoded center block. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-clock-functions nil + "List of functions applied to a transcoded clock. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-comment-functions nil + "List of functions applied to a transcoded comment. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-comment-block-functions nil + "List of functions applied to a transcoded comment-block. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-diary-sexp-functions nil + "List of functions applied to a transcoded diary-sexp. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-drawer-functions nil + "List of functions applied to a transcoded drawer. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-dynamic-block-functions nil + "List of functions applied to a transcoded dynamic-block. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-example-block-functions nil + "List of functions applied to a transcoded example-block. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-export-block-functions nil + "List of functions applied to a transcoded export-block. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-fixed-width-functions nil + "List of functions applied to a transcoded fixed-width. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-footnote-definition-functions nil + "List of functions applied to a transcoded footnote-definition. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-headline-functions nil + "List of functions applied to a transcoded headline. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-horizontal-rule-functions nil + "List of functions applied to a transcoded horizontal-rule. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-inlinetask-functions nil + "List of functions applied to a transcoded inlinetask. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-item-functions nil + "List of functions applied to a transcoded item. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-keyword-functions nil + "List of functions applied to a transcoded keyword. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-latex-environment-functions nil + "List of functions applied to a transcoded latex-environment. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-node-property-functions nil + "List of functions applied to a transcoded node-property. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-paragraph-functions nil + "List of functions applied to a transcoded paragraph. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-plain-list-functions nil + "List of functions applied to a transcoded plain-list. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-planning-functions nil + "List of functions applied to a transcoded planning. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-property-drawer-functions nil + "List of functions applied to a transcoded property-drawer. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-quote-block-functions nil + "List of functions applied to a transcoded quote block. +Each filter is called with three arguments: the transcoded quote +data, as a string, the back-end, as a symbol, and the +communication channel, as a plist. It must return a string or +nil.") + +(defvar org-export-filter-quote-section-functions nil + "List of functions applied to a transcoded quote-section. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-section-functions nil + "List of functions applied to a transcoded section. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-special-block-functions nil + "List of functions applied to a transcoded special block. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-src-block-functions nil + "List of functions applied to a transcoded src-block. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-table-functions nil + "List of functions applied to a transcoded table. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-table-cell-functions nil + "List of functions applied to a transcoded table-cell. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-table-row-functions nil + "List of functions applied to a transcoded table-row. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-verse-block-functions nil + "List of functions applied to a transcoded verse block. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + + +;;;; Objects Filters + +(defvar org-export-filter-bold-functions nil + "List of functions applied to transcoded bold text. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-code-functions nil + "List of functions applied to transcoded code text. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-entity-functions nil + "List of functions applied to a transcoded entity. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-export-snippet-functions nil + "List of functions applied to a transcoded export-snippet. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-footnote-reference-functions nil + "List of functions applied to a transcoded footnote-reference. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-inline-babel-call-functions nil + "List of functions applied to a transcoded inline-babel-call. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-inline-src-block-functions nil + "List of functions applied to a transcoded inline-src-block. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-italic-functions nil + "List of functions applied to transcoded italic text. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-latex-fragment-functions nil + "List of functions applied to a transcoded latex-fragment. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-line-break-functions nil + "List of functions applied to a transcoded line-break. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-link-functions nil + "List of functions applied to a transcoded link. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-radio-target-functions nil + "List of functions applied to a transcoded radio-target. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-statistics-cookie-functions nil + "List of functions applied to a transcoded statistics-cookie. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-strike-through-functions nil + "List of functions applied to transcoded strike-through text. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-subscript-functions nil + "List of functions applied to a transcoded subscript. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-superscript-functions nil + "List of functions applied to a transcoded superscript. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-target-functions nil + "List of functions applied to a transcoded target. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-timestamp-functions nil + "List of functions applied to a transcoded timestamp. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-underline-functions nil + "List of functions applied to transcoded underline text. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + +(defvar org-export-filter-verbatim-functions nil + "List of functions applied to transcoded verbatim text. +Each filter is called with three arguments: the transcoded data, +as a string, the back-end, as a symbol, and the communication +channel, as a plist. It must return a string or nil.") + + +;;;; Filters Tools +;; +;; Internal function `org-export-install-filters' installs filters +;; hard-coded in back-ends (developer filters) and filters from global +;; variables (user filters) in the communication channel. +;; +;; Internal function `org-export-filter-apply-functions' takes care +;; about applying each filter in order to a given data. It ignores +;; filters returning a nil value but stops whenever a filter returns +;; an empty string. + +(defun org-export-filter-apply-functions (filters value info) + "Call every function in FILTERS. + +Functions are called with arguments VALUE, current export +back-end's name and INFO. A function returning a nil value will +be skipped. If it returns the empty string, the process ends and +VALUE is ignored. + +Call is done in a LIFO fashion, to be sure that developer +specified filters, if any, are called first." + (catch 'exit + (let* ((backend (plist-get info :back-end)) + (backend-name (and backend (org-export-backend-name backend)))) + (dolist (filter filters value) + (let ((result (funcall filter value backend-name info))) + (cond ((not result) value) + ((equal value "") (throw 'exit nil)) + (t (setq value result)))))))) + +(defun org-export-install-filters (info) + "Install filters properties in communication channel. +INFO is a plist containing the current communication channel. +Return the updated communication channel." + (let (plist) + ;; Install user-defined filters with `org-export-filters-alist' + ;; and filters already in INFO (through ext-plist mechanism). + (mapc (lambda (p) + (let* ((prop (car p)) + (info-value (plist-get info prop)) + (default-value (symbol-value (cdr p)))) + (setq plist + (plist-put plist prop + ;; Filters in INFO will be called + ;; before those user provided. + (append (if (listp info-value) info-value + (list info-value)) + default-value))))) + org-export-filters-alist) + ;; Prepend back-end specific filters to that list. + (mapc (lambda (p) + ;; Single values get consed, lists are appended. + (let ((key (car p)) (value (cdr p))) + (when value + (setq plist + (plist-put + plist key + (if (atom value) (cons value (plist-get plist key)) + (append value (plist-get plist key)))))))) + (org-export-get-all-filters (plist-get info :back-end))) + ;; Return new communication channel. + (org-combine-plists info plist))) + + + +;;; Core functions +;; +;; This is the room for the main function, `org-export-as', along with +;; its derivative, `org-export-string-as'. +;; `org-export--copy-to-kill-ring-p' determines if output of these +;; function should be added to kill ring. +;; +;; Note that `org-export-as' doesn't really parse the current buffer, +;; but a copy of it (with the same buffer-local variables and +;; visibility), where macros and include keywords are expanded and +;; Babel blocks are executed, if appropriate. +;; `org-export-with-buffer-copy' macro prepares that copy. +;; +;; File inclusion is taken care of by +;; `org-export-expand-include-keyword' and +;; `org-export--prepare-file-contents'. Structure wise, including +;; a whole Org file in a buffer often makes little sense. For +;; example, if the file contains a headline and the include keyword +;; was within an item, the item should contain the headline. That's +;; why file inclusion should be done before any structure can be +;; associated to the file, that is before parsing. +;; +;; `org-export-insert-default-template' is a command to insert +;; a default template (or a back-end specific template) at point or in +;; current subtree. + +(defun org-export-copy-buffer () + "Return a copy of the current buffer. +The copy preserves Org buffer-local variables, visibility and +narrowing." + (let ((copy-buffer-fun (org-export--generate-copy-script (current-buffer))) + (new-buf (generate-new-buffer (buffer-name)))) + (with-current-buffer new-buf + (funcall copy-buffer-fun) + (set-buffer-modified-p nil)) + new-buf)) + +(defmacro org-export-with-buffer-copy (&rest body) + "Apply BODY in a copy of the current buffer. +The copy preserves local variables, visibility and contents of +the original buffer. Point is at the beginning of the buffer +when BODY is applied." + (declare (debug t)) + (org-with-gensyms (buf-copy) + `(let ((,buf-copy (org-export-copy-buffer))) + (unwind-protect + (with-current-buffer ,buf-copy + (goto-char (point-min)) + (progn ,@body)) + (and (buffer-live-p ,buf-copy) + ;; Kill copy without confirmation. + (progn (with-current-buffer ,buf-copy + (restore-buffer-modified-p nil)) + (kill-buffer ,buf-copy))))))) + +(defun org-export--generate-copy-script (buffer) + "Generate a function duplicating BUFFER. + +The copy will preserve local variables, visibility, contents and +narrowing of the original buffer. If a region was active in +BUFFER, contents will be narrowed to that region instead. + +The resulting function can be evaled at a later time, from +another buffer, effectively cloning the original buffer there. + +The function assumes BUFFER's major mode is `org-mode'." + (with-current-buffer buffer + `(lambda () + (let ((inhibit-modification-hooks t)) + ;; Set major mode. Ignore `org-mode-hook' as it has been run + ;; already in BUFFER. + (let ((org-mode-hook nil) (org-inhibit-startup t)) (org-mode)) + ;; Copy specific buffer local variables and variables set + ;; through BIND keywords. + ,@(let ((bound-variables (org-export--list-bound-variables)) + vars) + (dolist (entry (buffer-local-variables (buffer-base-buffer)) vars) + (when (consp entry) + (let ((var (car entry)) + (val (cdr entry))) + (and (not (eq var 'org-font-lock-keywords)) + (or (memq var + '(default-directory + buffer-file-name + buffer-file-coding-system)) + (assq var bound-variables) + (string-match "^\\(org-\\|orgtbl-\\)" + (symbol-name var))) + ;; Skip unreadable values, as they cannot be + ;; sent to external process. + (or (not val) (ignore-errors (read (format "%S" val)))) + (push `(set (make-local-variable (quote ,var)) + (quote ,val)) + vars)))))) + ;; Whole buffer contents. + (insert + ,(org-with-wide-buffer + (buffer-substring-no-properties + (point-min) (point-max)))) + ;; Narrowing. + ,(if (org-region-active-p) + `(narrow-to-region ,(region-beginning) ,(region-end)) + `(narrow-to-region ,(point-min) ,(point-max))) + ;; Current position of point. + (goto-char ,(point)) + ;; Overlays with invisible property. + ,@(let (ov-set) + (mapc + (lambda (ov) + (let ((invis-prop (overlay-get ov 'invisible))) + (when invis-prop + (push `(overlay-put + (make-overlay ,(overlay-start ov) + ,(overlay-end ov)) + 'invisible (quote ,invis-prop)) + ov-set)))) + (overlays-in (point-min) (point-max))) + ov-set))))) + +;;;###autoload +(defun org-export-as + (backend &optional subtreep visible-only body-only ext-plist) + "Transcode current Org buffer into BACKEND code. + +BACKEND is either an export back-end, as returned by, e.g., +`org-export-create-backend', or a symbol referring to +a registered back-end. + +If narrowing is active in the current buffer, only transcode its +narrowed part. + +If a region is active, transcode that region. + +When optional argument SUBTREEP is non-nil, transcode the +sub-tree at point, extracting information from the headline +properties first. + +When optional argument VISIBLE-ONLY is non-nil, don't export +contents of hidden elements. + +When optional argument BODY-ONLY is non-nil, only return body +code, without surrounding template. + +Optional argument EXT-PLIST, when provided, is a property list +with external parameters overriding Org default settings, but +still inferior to file-local settings. + +Return code as a string." + (when (symbolp backend) (setq backend (org-export-get-backend backend))) + (org-export-barf-if-invalid-backend backend) + (save-excursion + (save-restriction + ;; Narrow buffer to an appropriate region or subtree for + ;; parsing. If parsing subtree, be sure to remove main headline + ;; too. + (cond ((org-region-active-p) + (narrow-to-region (region-beginning) (region-end))) + (subtreep + (org-narrow-to-subtree) + (goto-char (point-min)) + (forward-line) + (narrow-to-region (point) (point-max)))) + ;; Initialize communication channel with original buffer + ;; attributes, unavailable in its copy. + (let* ((org-export-current-backend (org-export-backend-name backend)) + (info (org-combine-plists + (list :export-options + (delq nil + (list (and subtreep 'subtree) + (and visible-only 'visible-only) + (and body-only 'body-only)))) + (org-export--get-buffer-attributes))) + tree) + ;; Update communication channel and get parse tree. Buffer + ;; isn't parsed directly. Instead, a temporary copy is + ;; created, where include keywords, macros are expanded and + ;; code blocks are evaluated. + (org-export-with-buffer-copy + ;; Run first hook with current back-end's name as argument. + (run-hook-with-args 'org-export-before-processing-hook + (org-export-backend-name backend)) + (org-export-expand-include-keyword) + ;; Update macro templates since #+INCLUDE keywords might have + ;; added some new ones. + (org-macro-initialize-templates) + (org-macro-replace-all org-macro-templates) + (org-export-execute-babel-code) + ;; Update radio targets since keyword inclusion might have + ;; added some more. + (org-update-radio-target-regexp) + ;; Run last hook with current back-end's name as argument. + (goto-char (point-min)) + (save-excursion + (run-hook-with-args 'org-export-before-parsing-hook + (org-export-backend-name backend))) + ;; Update communication channel with environment. Also + ;; install user's and developer's filters. + (setq info + (org-export-install-filters + (org-combine-plists + info (org-export-get-environment backend subtreep ext-plist)))) + ;; Expand export-specific set of macros: {{{author}}}, + ;; {{{date}}}, {{{email}}} and {{{title}}}. It must be done + ;; once regular macros have been expanded, since document + ;; keywords may contain one of them. + (org-macro-replace-all + (list (cons "author" + (org-element-interpret-data (plist-get info :author))) + (cons "date" + (org-element-interpret-data (plist-get info :date))) + ;; EMAIL is not a parsed keyword: store it as-is. + (cons "email" (or (plist-get info :email) "")) + (cons "title" + (org-element-interpret-data (plist-get info :title))))) + ;; Call options filters and update export options. We do not + ;; use `org-export-filter-apply-functions' here since the + ;; arity of such filters is different. + (let ((backend-name (org-export-backend-name backend))) + (dolist (filter (plist-get info :filter-options)) + (let ((result (funcall filter info backend-name))) + (when result (setq info result))))) + ;; Parse buffer and call parse-tree filter on it. + (setq tree + (org-export-filter-apply-functions + (plist-get info :filter-parse-tree) + (org-element-parse-buffer nil visible-only) info)) + ;; Now tree is complete, compute its properties and add them + ;; to communication channel. + (setq info + (org-combine-plists + info (org-export-collect-tree-properties tree info))) + ;; Eventually transcode TREE. Wrap the resulting string into + ;; a template. + (let* ((body (org-element-normalize-string + (or (org-export-data tree info) ""))) + (inner-template (cdr (assq 'inner-template + (plist-get info :translate-alist)))) + (full-body (if (not (functionp inner-template)) body + (funcall inner-template body info))) + (template (cdr (assq 'template + (plist-get info :translate-alist))))) + ;; Remove all text properties since they cannot be + ;; retrieved from an external process. Finally call + ;; final-output filter and return result. + (org-no-properties + (org-export-filter-apply-functions + (plist-get info :filter-final-output) + (if (or (not (functionp template)) body-only) full-body + (funcall template full-body info)) + info)))))))) + +;;;###autoload +(defun org-export-string-as (string backend &optional body-only ext-plist) + "Transcode STRING into BACKEND code. + +BACKEND is either an export back-end, as returned by, e.g., +`org-export-create-backend', or a symbol referring to +a registered back-end. + +When optional argument BODY-ONLY is non-nil, only return body +code, without preamble nor postamble. + +Optional argument EXT-PLIST, when provided, is a property list +with external parameters overriding Org default settings, but +still inferior to file-local settings. + +Return code as a string." + (with-temp-buffer + (insert string) + (let ((org-inhibit-startup t)) (org-mode)) + (org-export-as backend nil nil body-only ext-plist))) + +;;;###autoload +(defun org-export-replace-region-by (backend) + "Replace the active region by its export to BACKEND. +BACKEND is either an export back-end, as returned by, e.g., +`org-export-create-backend', or a symbol referring to +a registered back-end." + (if (not (org-region-active-p)) + (user-error "No active region to replace") + (let* ((beg (region-beginning)) + (end (region-end)) + (str (buffer-substring beg end)) rpl) + (setq rpl (org-export-string-as str backend t)) + (delete-region beg end) + (insert rpl)))) + +;;;###autoload +(defun org-export-insert-default-template (&optional backend subtreep) + "Insert all export keywords with default values at beginning of line. + +BACKEND is a symbol referring to the name of a registered export +back-end, for which specific export options should be added to +the template, or `default' for default template. When it is nil, +the user will be prompted for a category. + +If SUBTREEP is non-nil, export configuration will be set up +locally for the subtree through node properties." + (interactive) + (unless (derived-mode-p 'org-mode) (user-error "Not in an Org mode buffer")) + (when (and subtreep (org-before-first-heading-p)) + (user-error "No subtree to set export options for")) + (let ((node (and subtreep (save-excursion (org-back-to-heading t) (point)))) + (backend + (or backend + (intern + (org-completing-read + "Options category: " + (cons "default" + (mapcar (lambda (b) + (symbol-name (org-export-backend-name b))) + org-export--registered-backends)))))) + options keywords) + ;; Populate OPTIONS and KEYWORDS. + (dolist (entry (cond ((eq backend 'default) org-export-options-alist) + ((org-export-backend-p backend) + (org-export-get-all-options backend)) + (t (org-export-get-all-options + (org-export-get-backend backend))))) + (let ((keyword (nth 1 entry)) + (option (nth 2 entry))) + (cond + (keyword (unless (assoc keyword keywords) + (let ((value + (if (eq (nth 4 entry) 'split) + (mapconcat 'identity (eval (nth 3 entry)) " ") + (eval (nth 3 entry))))) + (push (cons keyword value) keywords)))) + (option (unless (assoc option options) + (push (cons option (eval (nth 3 entry))) options)))))) + ;; Move to an appropriate location in order to insert options. + (unless subtreep (beginning-of-line)) + ;; First get TITLE, DATE, AUTHOR and EMAIL if they belong to the + ;; list of available keywords. + (when (assoc "TITLE" keywords) + (let ((title + (or (let ((visited-file (buffer-file-name (buffer-base-buffer)))) + (and visited-file + (file-name-sans-extension + (file-name-nondirectory visited-file)))) + (buffer-name (buffer-base-buffer))))) + (if (not subtreep) (insert (format "#+TITLE: %s\n" title)) + (org-entry-put node "EXPORT_TITLE" title)))) + (when (assoc "DATE" keywords) + (let ((date (with-temp-buffer (org-insert-time-stamp (current-time))))) + (if (not subtreep) (insert "#+DATE: " date "\n") + (org-entry-put node "EXPORT_DATE" date)))) + (when (assoc "AUTHOR" keywords) + (let ((author (cdr (assoc "AUTHOR" keywords)))) + (if subtreep (org-entry-put node "EXPORT_AUTHOR" author) + (insert + (format "#+AUTHOR:%s\n" + (if (not (org-string-nw-p author)) "" + (concat " " author))))))) + (when (assoc "EMAIL" keywords) + (let ((email (cdr (assoc "EMAIL" keywords)))) + (if subtreep (org-entry-put node "EXPORT_EMAIL" email) + (insert + (format "#+EMAIL:%s\n" + (if (not (org-string-nw-p email)) "" + (concat " " email))))))) + ;; Then (multiple) OPTIONS lines. Never go past fill-column. + (when options + (let ((items + (mapcar + #'(lambda (opt) (format "%s:%S" (car opt) (cdr opt))) + (sort options (lambda (k1 k2) (string< (car k1) (car k2))))))) + (if subtreep + (org-entry-put + node "EXPORT_OPTIONS" (mapconcat 'identity items " ")) + (while items + (insert "#+OPTIONS:") + (let ((width 10)) + (while (and items + (< (+ width (length (car items)) 1) fill-column)) + (let ((item (pop items))) + (insert " " item) + (incf width (1+ (length item)))))) + (insert "\n"))))) + ;; And the rest of keywords. + (dolist (key (sort keywords (lambda (k1 k2) (string< (car k1) (car k2))))) + (unless (member (car key) '("TITLE" "DATE" "AUTHOR" "EMAIL")) + (let ((val (cdr key))) + (if subtreep (org-entry-put node (concat "EXPORT_" (car key)) val) + (insert + (format "#+%s:%s\n" + (car key) + (if (org-string-nw-p val) (format " %s" val) ""))))))))) + +(defun org-export-expand-include-keyword (&optional included dir) + "Expand every include keyword in buffer. +Optional argument INCLUDED is a list of included file names along +with their line restriction, when appropriate. It is used to +avoid infinite recursion. Optional argument DIR is the current +working directory. It is used to properly resolve relative +paths." + (let ((case-fold-search t)) + (goto-char (point-min)) + (while (re-search-forward "^[ \t]*#\\+INCLUDE:" nil t) + (let ((element (save-match-data (org-element-at-point)))) + (when (eq (org-element-type element) 'keyword) + (beginning-of-line) + ;; Extract arguments from keyword's value. + (let* ((value (org-element-property :value element)) + (ind (org-get-indentation)) + (file (and (string-match + "^\\(\".+?\"\\|\\S-+\\)\\(?:\\s-+\\|$\\)" value) + (prog1 (expand-file-name + (org-remove-double-quotes + (match-string 1 value)) + dir) + (setq value (replace-match "" nil nil value))))) + (lines + (and (string-match + ":lines +\"\\(\\(?:[0-9]+\\)?-\\(?:[0-9]+\\)?\\)\"" + value) + (prog1 (match-string 1 value) + (setq value (replace-match "" nil nil value))))) + (env (cond ((string-match "\\" value) 'example) + ((string-match "\\ level limit) (- level limit)))))) + +(defun org-export-get-headline-number (headline info) + "Return HEADLINE numbering as a list of numbers. +INFO is a plist holding contextual information." + (cdr (assoc headline (plist-get info :headline-numbering)))) + +(defun org-export-numbered-headline-p (headline info) + "Return a non-nil value if HEADLINE element should be numbered. +INFO is a plist used as a communication channel." + (let ((sec-num (plist-get info :section-numbers)) + (level (org-export-get-relative-level headline info))) + (if (wholenump sec-num) (<= level sec-num) sec-num))) + +(defun org-export-number-to-roman (n) + "Convert integer N into a roman numeral." + (let ((roman '((1000 . "M") (900 . "CM") (500 . "D") (400 . "CD") + ( 100 . "C") ( 90 . "XC") ( 50 . "L") ( 40 . "XL") + ( 10 . "X") ( 9 . "IX") ( 5 . "V") ( 4 . "IV") + ( 1 . "I"))) + (res "")) + (if (<= n 0) + (number-to-string n) + (while roman + (if (>= n (caar roman)) + (setq n (- n (caar roman)) + res (concat res (cdar roman))) + (pop roman))) + res))) + +(defun org-export-get-tags (element info &optional tags inherited) + "Return list of tags associated to ELEMENT. + +ELEMENT has either an `headline' or an `inlinetask' type. INFO +is a plist used as a communication channel. + +Select tags (see `org-export-select-tags') and exclude tags (see +`org-export-exclude-tags') are removed from the list. + +When non-nil, optional argument TAGS should be a list of strings. +Any tag belonging to this list will also be removed. + +When optional argument INHERITED is non-nil, tags can also be +inherited from parent headlines and FILETAGS keywords." + (org-remove-if + (lambda (tag) (or (member tag (plist-get info :select-tags)) + (member tag (plist-get info :exclude-tags)) + (member tag tags))) + (if (not inherited) (org-element-property :tags element) + ;; Build complete list of inherited tags. + (let ((current-tag-list (org-element-property :tags element))) + (mapc + (lambda (parent) + (mapc + (lambda (tag) + (when (and (memq (org-element-type parent) '(headline inlinetask)) + (not (member tag current-tag-list))) + (push tag current-tag-list))) + (org-element-property :tags parent))) + (org-export-get-genealogy element)) + ;; Add FILETAGS keywords and return results. + (org-uniquify (append (plist-get info :filetags) current-tag-list)))))) + +(defun org-export-get-node-property (property blob &optional inherited) + "Return node PROPERTY value for BLOB. + +PROPERTY is an upcase symbol (i.e. `:COOKIE_DATA'). BLOB is an +element or object. + +If optional argument INHERITED is non-nil, the value can be +inherited from a parent headline. + +Return value is a string or nil." + (let ((headline (if (eq (org-element-type blob) 'headline) blob + (org-export-get-parent-headline blob)))) + (if (not inherited) (org-element-property property blob) + (let ((parent headline) value) + (catch 'found + (while parent + (when (plist-member (nth 1 parent) property) + (throw 'found (org-element-property property parent))) + (setq parent (org-element-property :parent parent)))))))) + +(defun org-export-get-category (blob info) + "Return category for element or object BLOB. + +INFO is a plist used as a communication channel. + +CATEGORY is automatically inherited from a parent headline, from +#+CATEGORY: keyword or created out of original file name. If all +fail, the fall-back value is \"???\"." + (or (let ((headline (if (eq (org-element-type blob) 'headline) blob + (org-export-get-parent-headline blob)))) + ;; Almost like `org-export-node-property', but we cannot trust + ;; `plist-member' as every headline has a `:CATEGORY' + ;; property, would it be nil or equal to "???" (which has the + ;; same meaning). + (let ((parent headline) value) + (catch 'found + (while parent + (let ((category (org-element-property :CATEGORY parent))) + (and category (not (equal "???" category)) + (throw 'found category))) + (setq parent (org-element-property :parent parent)))))) + (org-element-map (plist-get info :parse-tree) 'keyword + (lambda (kwd) + (when (equal (org-element-property :key kwd) "CATEGORY") + (org-element-property :value kwd))) + info 'first-match) + (let ((file (plist-get info :input-file))) + (and file (file-name-sans-extension (file-name-nondirectory file)))) + "???")) + +(defun org-export-get-alt-title (headline info) + "Return alternative title for HEADLINE, as a secondary string. +INFO is a plist used as a communication channel. If no optional +title is defined, fall-back to the regular title." + (or (org-element-property :alt-title headline) + (org-element-property :title headline))) + +(defun org-export-first-sibling-p (headline info) + "Non-nil when HEADLINE is the first sibling in its sub-tree. +INFO is a plist used as a communication channel." + (not (eq (org-element-type (org-export-get-previous-element headline info)) + 'headline))) + +(defun org-export-last-sibling-p (headline info) + "Non-nil when HEADLINE is the last sibling in its sub-tree. +INFO is a plist used as a communication channel." + (not (org-export-get-next-element headline info))) + + +;;;; For Keywords +;; +;; `org-export-get-date' returns a date appropriate for the document +;; to about to be exported. In particular, it takes care of +;; `org-export-date-timestamp-format'. + +(defun org-export-get-date (info &optional fmt) + "Return date value for the current document. + +INFO is a plist used as a communication channel. FMT, when +non-nil, is a time format string that will be applied on the date +if it consists in a single timestamp object. It defaults to +`org-export-date-timestamp-format' when nil. + +A proper date can be a secondary string, a string or nil. It is +meant to be translated with `org-export-data' or alike." + (let ((date (plist-get info :date)) + (fmt (or fmt org-export-date-timestamp-format))) + (cond ((not date) nil) + ((and fmt + (not (cdr date)) + (eq (org-element-type (car date)) 'timestamp)) + (org-timestamp-format (car date) fmt)) + (t date)))) + + +;;;; For Links +;; +;; `org-export-solidify-link-text' turns a string into a safer version +;; for links, replacing most non-standard characters with hyphens. +;; +;; `org-export-get-coderef-format' returns an appropriate format +;; string for coderefs. +;; +;; `org-export-inline-image-p' returns a non-nil value when the link +;; provided should be considered as an inline image. +;; +;; `org-export-resolve-fuzzy-link' searches destination of fuzzy links +;; (i.e. links with "fuzzy" as type) within the parsed tree, and +;; returns an appropriate unique identifier when found, or nil. +;; +;; `org-export-resolve-id-link' returns the first headline with +;; specified id or custom-id in parse tree, the path to the external +;; file with the id or nil when neither was found. +;; +;; `org-export-resolve-coderef' associates a reference to a line +;; number in the element it belongs, or returns the reference itself +;; when the element isn't numbered. + +(defun org-export-solidify-link-text (s) + "Take link text S and make a safe target out of it." + (save-match-data + (mapconcat 'identity (org-split-string s "[^a-zA-Z0-9_.-:]+") "-"))) + +(defun org-export-get-coderef-format (path desc) + "Return format string for code reference link. +PATH is the link path. DESC is its description." + (save-match-data + (cond ((not desc) "%s") + ((string-match (regexp-quote (concat "(" path ")")) desc) + (replace-match "%s" t t desc)) + (t desc)))) + +(defun org-export-inline-image-p (link &optional rules) + "Non-nil if LINK object points to an inline image. + +Optional argument is a set of RULES defining inline images. It +is an alist where associations have the following shape: + + \(TYPE . REGEXP) + +Applying a rule means apply REGEXP against LINK's path when its +type is TYPE. The function will return a non-nil value if any of +the provided rules is non-nil. The default rule is +`org-export-default-inline-image-rule'. + +This only applies to links without a description." + (and (not (org-element-contents link)) + (let ((case-fold-search t) + (rules (or rules org-export-default-inline-image-rule))) + (catch 'exit + (mapc + (lambda (rule) + (and (string= (org-element-property :type link) (car rule)) + (string-match (cdr rule) + (org-element-property :path link)) + (throw 'exit t))) + rules) + ;; Return nil if no rule matched. + nil)))) + +(defun org-export-resolve-coderef (ref info) + "Resolve a code reference REF. + +INFO is a plist used as a communication channel. + +Return associated line number in source code, or REF itself, +depending on src-block or example element's switches." + (org-element-map (plist-get info :parse-tree) '(example-block src-block) + (lambda (el) + (with-temp-buffer + (insert (org-trim (org-element-property :value el))) + (let* ((label-fmt (regexp-quote + (or (org-element-property :label-fmt el) + org-coderef-label-format))) + (ref-re + (format "^.*?\\S-.*?\\([ \t]*\\(%s\\)\\)[ \t]*$" + (replace-regexp-in-string "%s" ref label-fmt nil t)))) + ;; Element containing REF is found. Resolve it to either + ;; a label or a line number, as needed. + (when (re-search-backward ref-re nil t) + (cond + ((org-element-property :use-labels el) ref) + ((eq (org-element-property :number-lines el) 'continued) + (+ (org-export-get-loc el info) (line-number-at-pos))) + (t (line-number-at-pos))))))) + info 'first-match)) + +(defun org-export-resolve-fuzzy-link (link info) + "Return LINK destination. + +INFO is a plist holding contextual information. + +Return value can be an object, an element, or nil: + +- If LINK path matches a target object (i.e. <>) return it. + +- If LINK path exactly matches the name affiliated keyword + \(i.e. #+NAME: path) of an element, return that element. + +- If LINK path exactly matches any headline name, return that + element. If more than one headline share that name, priority + will be given to the one with the closest common ancestor, if + any, or the first one in the parse tree otherwise. + +- Otherwise, return nil. + +Assume LINK type is \"fuzzy\". White spaces are not +significant." + (let* ((raw-path (org-element-property :path link)) + (match-title-p (eq (aref raw-path 0) ?*)) + ;; Split PATH at white spaces so matches are space + ;; insensitive. + (path (org-split-string + (if match-title-p (substring raw-path 1) raw-path))) + ;; Cache for destinations that are not position dependent. + (link-cache + (or (plist-get info :resolve-fuzzy-link-cache) + (plist-get (setq info (plist-put info :resolve-fuzzy-link-cache + (make-hash-table :test 'equal))) + :resolve-fuzzy-link-cache))) + (cached (gethash path link-cache 'not-found))) + (cond + ;; Destination is not position dependent: use cached value. + ((and (not match-title-p) (not (eq cached 'not-found))) cached) + ;; First try to find a matching "<>" unless user specified + ;; he was looking for a headline (path starts with a "*" + ;; character). + ((and (not match-title-p) + (let ((match (org-element-map (plist-get info :parse-tree) 'target + (lambda (blob) + (and (equal (org-split-string + (org-element-property :value blob)) + path) + blob)) + info 'first-match))) + (and match (puthash path match link-cache))))) + ;; Then try to find an element with a matching "#+NAME: path" + ;; affiliated keyword. + ((and (not match-title-p) + (let ((match (org-element-map (plist-get info :parse-tree) + org-element-all-elements + (lambda (el) + (let ((name (org-element-property :name el))) + (when (and name + (equal (org-split-string name) path)) + el))) + info 'first-match))) + (and match (puthash path match link-cache))))) + ;; Last case: link either points to a headline or to nothingness. + ;; Try to find the source, with priority given to headlines with + ;; the closest common ancestor. If such candidate is found, + ;; return it, otherwise return nil. + (t + (let ((find-headline + (function + ;; Return first headline whose `:raw-value' property is + ;; NAME in parse tree DATA, or nil. Statistics cookies + ;; are ignored. + (lambda (name data) + (org-element-map data 'headline + (lambda (headline) + (when (equal (org-split-string + (replace-regexp-in-string + "\\[[0-9]+%\\]\\|\\[[0-9]+/[0-9]+\\]" "" + (org-element-property :raw-value headline))) + name) + headline)) + info 'first-match))))) + ;; Search among headlines sharing an ancestor with link, from + ;; closest to farthest. + (catch 'exit + (mapc + (lambda (parent) + (let ((foundp (funcall find-headline path parent))) + (when foundp (throw 'exit foundp)))) + (let ((parent-hl (org-export-get-parent-headline link))) + (if (not parent-hl) (list (plist-get info :parse-tree)) + (cons parent-hl (org-export-get-genealogy parent-hl))))) + ;; No destination found: return nil. + (and (not match-title-p) (puthash path nil link-cache)))))))) + +(defun org-export-resolve-id-link (link info) + "Return headline referenced as LINK destination. + +INFO is a plist used as a communication channel. + +Return value can be the headline element matched in current parse +tree, a file name or nil. Assume LINK type is either \"id\" or +\"custom-id\"." + (let ((id (org-element-property :path link))) + ;; First check if id is within the current parse tree. + (or (org-element-map (plist-get info :parse-tree) 'headline + (lambda (headline) + (when (or (string= (org-element-property :ID headline) id) + (string= (org-element-property :CUSTOM_ID headline) id)) + headline)) + info 'first-match) + ;; Otherwise, look for external files. + (cdr (assoc id (plist-get info :id-alist)))))) + +(defun org-export-resolve-radio-link (link info) + "Return radio-target object referenced as LINK destination. + +INFO is a plist used as a communication channel. + +Return value can be a radio-target object or nil. Assume LINK +has type \"radio\"." + (let ((path (replace-regexp-in-string + "[ \r\t\n]+" " " (org-element-property :path link)))) + (org-element-map (plist-get info :parse-tree) 'radio-target + (lambda (radio) + (and (eq (compare-strings + (replace-regexp-in-string + "[ \r\t\n]+" " " (org-element-property :value radio)) + nil nil path nil nil t) + t) + radio)) + info 'first-match))) + + +;;;; For References +;; +;; `org-export-get-ordinal' associates a sequence number to any object +;; or element. + +(defun org-export-get-ordinal (element info &optional types predicate) + "Return ordinal number of an element or object. + +ELEMENT is the element or object considered. INFO is the plist +used as a communication channel. + +Optional argument TYPES, when non-nil, is a list of element or +object types, as symbols, that should also be counted in. +Otherwise, only provided element's type is considered. + +Optional argument PREDICATE is a function returning a non-nil +value if the current element or object should be counted in. It +accepts two arguments: the element or object being considered and +the plist used as a communication channel. This allows to count +only a certain type of objects (i.e. inline images). + +Return value is a list of numbers if ELEMENT is a headline or an +item. It is nil for keywords. It represents the footnote number +for footnote definitions and footnote references. If ELEMENT is +a target, return the same value as if ELEMENT was the closest +table, item or headline containing the target. In any other +case, return the sequence number of ELEMENT among elements or +objects of the same type." + ;; Ordinal of a target object refer to the ordinal of the closest + ;; table, item, or headline containing the object. + (when (eq (org-element-type element) 'target) + (setq element + (loop for parent in (org-export-get-genealogy element) + when + (memq + (org-element-type parent) + '(footnote-definition footnote-reference headline item + table)) + return parent))) + (case (org-element-type element) + ;; Special case 1: A headline returns its number as a list. + (headline (org-export-get-headline-number element info)) + ;; Special case 2: An item returns its number as a list. + (item (let ((struct (org-element-property :structure element))) + (org-list-get-item-number + (org-element-property :begin element) + struct + (org-list-prevs-alist struct) + (org-list-parents-alist struct)))) + ((footnote-definition footnote-reference) + (org-export-get-footnote-number element info)) + (otherwise + (let ((counter 0)) + ;; Increment counter until ELEMENT is found again. + (org-element-map (plist-get info :parse-tree) + (or types (org-element-type element)) + (lambda (el) + (cond + ((eq element el) (1+ counter)) + ((not predicate) (incf counter) nil) + ((funcall predicate el info) (incf counter) nil))) + info 'first-match))))) + + +;;;; For Src-Blocks +;; +;; `org-export-get-loc' counts number of code lines accumulated in +;; src-block or example-block elements with a "+n" switch until +;; a given element, excluded. Note: "-n" switches reset that count. +;; +;; `org-export-unravel-code' extracts source code (along with a code +;; references alist) from an `element-block' or `src-block' type +;; element. +;; +;; `org-export-format-code' applies a formatting function to each line +;; of code, providing relative line number and code reference when +;; appropriate. Since it doesn't access the original element from +;; which the source code is coming, it expects from the code calling +;; it to know if lines should be numbered and if code references +;; should appear. +;; +;; Eventually, `org-export-format-code-default' is a higher-level +;; function (it makes use of the two previous functions) which handles +;; line numbering and code references inclusion, and returns source +;; code in a format suitable for plain text or verbatim output. + +(defun org-export-get-loc (element info) + "Return accumulated lines of code up to ELEMENT. + +INFO is the plist used as a communication channel. + +ELEMENT is excluded from count." + (let ((loc 0)) + (org-element-map (plist-get info :parse-tree) + `(src-block example-block ,(org-element-type element)) + (lambda (el) + (cond + ;; ELEMENT is reached: Quit the loop. + ((eq el element)) + ;; Only count lines from src-block and example-block elements + ;; with a "+n" or "-n" switch. A "-n" switch resets counter. + ((not (memq (org-element-type el) '(src-block example-block))) nil) + ((let ((linums (org-element-property :number-lines el))) + (when linums + ;; Accumulate locs or reset them. + (let ((lines (org-count-lines + (org-trim (org-element-property :value el))))) + (setq loc (if (eq linums 'new) lines (+ loc lines)))))) + ;; Return nil to stay in the loop. + nil))) + info 'first-match) + ;; Return value. + loc)) + +(defun org-export-unravel-code (element) + "Clean source code and extract references out of it. + +ELEMENT has either a `src-block' an `example-block' type. + +Return a cons cell whose CAR is the source code, cleaned from any +reference and protective comma and CDR is an alist between +relative line number (integer) and name of code reference on that +line (string)." + (let* ((line 0) refs + ;; Get code and clean it. Remove blank lines at its + ;; beginning and end. + (code (replace-regexp-in-string + "\\`\\([ \t]*\n\\)+" "" + (replace-regexp-in-string + "\\([ \t]*\n\\)*[ \t]*\\'" "\n" + (org-element-property :value element)))) + ;; Get format used for references. + (label-fmt (regexp-quote + (or (org-element-property :label-fmt element) + org-coderef-label-format))) + ;; Build a regexp matching a loc with a reference. + (with-ref-re + (format "^.*?\\S-.*?\\([ \t]*\\(%s\\)[ \t]*\\)$" + (replace-regexp-in-string + "%s" "\\([-a-zA-Z0-9_ ]+\\)" label-fmt nil t)))) + ;; Return value. + (cons + ;; Code with references removed. + (org-element-normalize-string + (mapconcat + (lambda (loc) + (incf line) + (if (not (string-match with-ref-re loc)) loc + ;; Ref line: remove ref, and signal its position in REFS. + (push (cons line (match-string 3 loc)) refs) + (replace-match "" nil nil loc 1))) + (org-split-string code "\n") "\n")) + ;; Reference alist. + refs))) + +(defun org-export-format-code (code fun &optional num-lines ref-alist) + "Format CODE by applying FUN line-wise and return it. + +CODE is a string representing the code to format. FUN is +a function. It must accept three arguments: a line of +code (string), the current line number (integer) or nil and the +reference associated to the current line (string) or nil. + +Optional argument NUM-LINES can be an integer representing the +number of code lines accumulated until the current code. Line +numbers passed to FUN will take it into account. If it is nil, +FUN's second argument will always be nil. This number can be +obtained with `org-export-get-loc' function. + +Optional argument REF-ALIST can be an alist between relative line +number (i.e. ignoring NUM-LINES) and the name of the code +reference on it. If it is nil, FUN's third argument will always +be nil. It can be obtained through the use of +`org-export-unravel-code' function." + (let ((--locs (org-split-string code "\n")) + (--line 0)) + (org-element-normalize-string + (mapconcat + (lambda (--loc) + (incf --line) + (let ((--ref (cdr (assq --line ref-alist)))) + (funcall fun --loc (and num-lines (+ num-lines --line)) --ref))) + --locs "\n")))) + +(defun org-export-format-code-default (element info) + "Return source code from ELEMENT, formatted in a standard way. + +ELEMENT is either a `src-block' or `example-block' element. INFO +is a plist used as a communication channel. + +This function takes care of line numbering and code references +inclusion. Line numbers, when applicable, appear at the +beginning of the line, separated from the code by two white +spaces. Code references, on the other hand, appear flushed to +the right, separated by six white spaces from the widest line of +code." + ;; Extract code and references. + (let* ((code-info (org-export-unravel-code element)) + (code (car code-info)) + (code-lines (org-split-string code "\n"))) + (if (null code-lines) "" + (let* ((refs (and (org-element-property :retain-labels element) + (cdr code-info))) + ;; Handle line numbering. + (num-start (case (org-element-property :number-lines element) + (continued (org-export-get-loc element info)) + (new 0))) + (num-fmt + (and num-start + (format "%%%ds " + (length (number-to-string + (+ (length code-lines) num-start)))))) + ;; Prepare references display, if required. Any reference + ;; should start six columns after the widest line of code, + ;; wrapped with parenthesis. + (max-width + (+ (apply 'max (mapcar 'length code-lines)) + (if (not num-start) 0 (length (format num-fmt num-start)))))) + (org-export-format-code + code + (lambda (loc line-num ref) + (let ((number-str (and num-fmt (format num-fmt line-num)))) + (concat + number-str + loc + (and ref + (concat (make-string + (- (+ 6 max-width) + (+ (length loc) (length number-str))) ? ) + (format "(%s)" ref)))))) + num-start refs))))) + + +;;;; For Tables +;; +;; `org-export-table-has-special-column-p' and and +;; `org-export-table-row-is-special-p' are predicates used to look for +;; meta-information about the table structure. +;; +;; `org-table-has-header-p' tells when the rows before the first rule +;; should be considered as table's header. +;; +;; `org-export-table-cell-width', `org-export-table-cell-alignment' +;; and `org-export-table-cell-borders' extract information from +;; a table-cell element. +;; +;; `org-export-table-dimensions' gives the number on rows and columns +;; in the table, ignoring horizontal rules and special columns. +;; `org-export-table-cell-address', given a table-cell object, returns +;; the absolute address of a cell. On the other hand, +;; `org-export-get-table-cell-at' does the contrary. +;; +;; `org-export-table-cell-starts-colgroup-p', +;; `org-export-table-cell-ends-colgroup-p', +;; `org-export-table-row-starts-rowgroup-p', +;; `org-export-table-row-ends-rowgroup-p', +;; `org-export-table-row-starts-header-p' and +;; `org-export-table-row-ends-header-p' indicate position of current +;; row or cell within the table. + +(defun org-export-table-has-special-column-p (table) + "Non-nil when TABLE has a special column. +All special columns will be ignored during export." + ;; The table has a special column when every first cell of every row + ;; has an empty value or contains a symbol among "/", "#", "!", "$", + ;; "*" "_" and "^". Though, do not consider a first row containing + ;; only empty cells as special. + (let ((special-column-p 'empty)) + (catch 'exit + (mapc + (lambda (row) + (when (eq (org-element-property :type row) 'standard) + (let ((value (org-element-contents + (car (org-element-contents row))))) + (cond ((member value '(("/") ("#") ("!") ("$") ("*") ("_") ("^"))) + (setq special-column-p 'special)) + ((not value)) + (t (throw 'exit nil)))))) + (org-element-contents table)) + (eq special-column-p 'special)))) + +(defun org-export-table-has-header-p (table info) + "Non-nil when TABLE has a header. + +INFO is a plist used as a communication channel. + +A table has a header when it contains at least two row groups." + (let ((cache (or (plist-get info :table-header-cache) + (plist-get (setq info + (plist-put info :table-header-cache + (make-hash-table :test 'eq))) + :table-header-cache)))) + (or (gethash table cache) + (let ((rowgroup 1) row-flag) + (puthash + table + (org-element-map table 'table-row + (lambda (row) + (cond + ((> rowgroup 1) t) + ((and row-flag (eq (org-element-property :type row) 'rule)) + (incf rowgroup) (setq row-flag nil)) + ((and (not row-flag) (eq (org-element-property :type row) + 'standard)) + (setq row-flag t) nil))) + info 'first-match) + cache))))) + +(defun org-export-table-row-is-special-p (table-row info) + "Non-nil if TABLE-ROW is considered special. + +INFO is a plist used as the communication channel. + +All special rows will be ignored during export." + (when (eq (org-element-property :type table-row) 'standard) + (let ((first-cell (org-element-contents + (car (org-element-contents table-row))))) + ;; A row is special either when... + (or + ;; ... it starts with a field only containing "/", + (equal first-cell '("/")) + ;; ... the table contains a special column and the row start + ;; with a marking character among, "^", "_", "$" or "!", + (and (org-export-table-has-special-column-p + (org-export-get-parent table-row)) + (member first-cell '(("^") ("_") ("$") ("!")))) + ;; ... it contains only alignment cookies and empty cells. + (let ((special-row-p 'empty)) + (catch 'exit + (mapc + (lambda (cell) + (let ((value (org-element-contents cell))) + ;; Since VALUE is a secondary string, the following + ;; checks avoid expanding it with `org-export-data'. + (cond ((not value)) + ((and (not (cdr value)) + (stringp (car value)) + (string-match "\\`<[lrc]?\\([0-9]+\\)?>\\'" + (car value))) + (setq special-row-p 'cookie)) + (t (throw 'exit nil))))) + (org-element-contents table-row)) + (eq special-row-p 'cookie))))))) + +(defun org-export-table-row-group (table-row info) + "Return TABLE-ROW's group number, as an integer. + +INFO is a plist used as the communication channel. + +Return value is the group number, as an integer, or nil for +special rows and rows separators. First group is also table's +header." + (let ((cache (or (plist-get info :table-row-group-cache) + (plist-get (setq info + (plist-put info :table-row-group-cache + (make-hash-table :test 'eq))) + :table-row-group-cache)))) + (cond ((gethash table-row cache)) + ((eq (org-element-property :type table-row) 'rule) nil) + (t (let ((group 0) row-flag) + (org-element-map (org-export-get-parent table-row) 'table-row + (lambda (row) + (if (eq (org-element-property :type row) 'rule) + (setq row-flag nil) + (unless row-flag (incf group) (setq row-flag t))) + (when (eq table-row row) (puthash table-row group cache))) + info 'first-match)))))) + +(defun org-export-table-cell-width (table-cell info) + "Return TABLE-CELL contents width. + +INFO is a plist used as the communication channel. + +Return value is the width given by the last width cookie in the +same column as TABLE-CELL, or nil." + (let* ((row (org-export-get-parent table-cell)) + (table (org-export-get-parent row)) + (cells (org-element-contents row)) + (columns (length cells)) + (column (- columns (length (memq table-cell cells)))) + (cache (or (plist-get info :table-cell-width-cache) + (plist-get (setq info + (plist-put info :table-cell-width-cache + (make-hash-table :test 'eq))) + :table-cell-width-cache))) + (width-vector (or (gethash table cache) + (puthash table (make-vector columns 'empty) cache))) + (value (aref width-vector column))) + (if (not (eq value 'empty)) value + (let (cookie-width) + (dolist (row (org-element-contents table) + (aset width-vector column cookie-width)) + (when (org-export-table-row-is-special-p row info) + ;; In a special row, try to find a width cookie at COLUMN. + (let* ((value (org-element-contents + (elt (org-element-contents row) column))) + (cookie (car value))) + ;; The following checks avoid expanding unnecessarily + ;; the cell with `org-export-data'. + (when (and value + (not (cdr value)) + (stringp cookie) + (string-match "\\`<[lrc]?\\([0-9]+\\)?>\\'" cookie) + (match-string 1 cookie)) + (setq cookie-width + (string-to-number (match-string 1 cookie))))))))))) + +(defun org-export-table-cell-alignment (table-cell info) + "Return TABLE-CELL contents alignment. + +INFO is a plist used as the communication channel. + +Return alignment as specified by the last alignment cookie in the +same column as TABLE-CELL. If no such cookie is found, a default +alignment value will be deduced from fraction of numbers in the +column (see `org-table-number-fraction' for more information). +Possible values are `left', `right' and `center'." + ;; Load `org-table-number-fraction' and `org-table-number-regexp'. + (require 'org-table) + (let* ((row (org-export-get-parent table-cell)) + (table (org-export-get-parent row)) + (cells (org-element-contents row)) + (columns (length cells)) + (column (- columns (length (memq table-cell cells)))) + (cache (or (plist-get info :table-cell-alignment-cache) + (plist-get (setq info + (plist-put info :table-cell-alignment-cache + (make-hash-table :test 'eq))) + :table-cell-alignment-cache))) + (align-vector (or (gethash table cache) + (puthash table (make-vector columns nil) cache)))) + (or (aref align-vector column) + (let ((number-cells 0) + (total-cells 0) + cookie-align + previous-cell-number-p) + (dolist (row (org-element-contents (org-export-get-parent row))) + (cond + ;; In a special row, try to find an alignment cookie at + ;; COLUMN. + ((org-export-table-row-is-special-p row info) + (let ((value (org-element-contents + (elt (org-element-contents row) column)))) + ;; Since VALUE is a secondary string, the following + ;; checks avoid useless expansion through + ;; `org-export-data'. + (when (and value + (not (cdr value)) + (stringp (car value)) + (string-match "\\`<\\([lrc]\\)?\\([0-9]+\\)?>\\'" + (car value)) + (match-string 1 (car value))) + (setq cookie-align (match-string 1 (car value)))))) + ;; Ignore table rules. + ((eq (org-element-property :type row) 'rule)) + ;; In a standard row, check if cell's contents are + ;; expressing some kind of number. Increase NUMBER-CELLS + ;; accordingly. Though, don't bother if an alignment + ;; cookie has already defined cell's alignment. + ((not cookie-align) + (let ((value (org-export-data + (org-element-contents + (elt (org-element-contents row) column)) + info))) + (incf total-cells) + ;; Treat an empty cell as a number if it follows + ;; a number. + (if (not (or (string-match org-table-number-regexp value) + (and (string= value "") previous-cell-number-p))) + (setq previous-cell-number-p nil) + (setq previous-cell-number-p t) + (incf number-cells)))))) + ;; Return value. Alignment specified by cookies has + ;; precedence over alignment deduced from cell's contents. + (aset align-vector + column + (cond ((equal cookie-align "l") 'left) + ((equal cookie-align "r") 'right) + ((equal cookie-align "c") 'center) + ((>= (/ (float number-cells) total-cells) + org-table-number-fraction) + 'right) + (t 'left))))))) + +(defun org-export-table-cell-borders (table-cell info) + "Return TABLE-CELL borders. + +INFO is a plist used as a communication channel. + +Return value is a list of symbols, or nil. Possible values are: +`top', `bottom', `above', `below', `left' and `right'. Note: +`top' (resp. `bottom') only happen for a cell in the first +row (resp. last row) of the table, ignoring table rules, if any. + +Returned borders ignore special rows." + (let* ((row (org-export-get-parent table-cell)) + (table (org-export-get-parent-table table-cell)) + borders) + ;; Top/above border? TABLE-CELL has a border above when a rule + ;; used to demarcate row groups can be found above. Hence, + ;; finding a rule isn't sufficient to push `above' in BORDERS: + ;; another regular row has to be found above that rule. + (let (rule-flag) + (catch 'exit + (mapc (lambda (row) + (cond ((eq (org-element-property :type row) 'rule) + (setq rule-flag t)) + ((not (org-export-table-row-is-special-p row info)) + (if rule-flag (throw 'exit (push 'above borders)) + (throw 'exit nil))))) + ;; Look at every row before the current one. + (cdr (memq row (reverse (org-element-contents table))))) + ;; No rule above, or rule found starts the table (ignoring any + ;; special row): TABLE-CELL is at the top of the table. + (when rule-flag (push 'above borders)) + (push 'top borders))) + ;; Bottom/below border? TABLE-CELL has a border below when next + ;; non-regular row below is a rule. + (let (rule-flag) + (catch 'exit + (mapc (lambda (row) + (cond ((eq (org-element-property :type row) 'rule) + (setq rule-flag t)) + ((not (org-export-table-row-is-special-p row info)) + (if rule-flag (throw 'exit (push 'below borders)) + (throw 'exit nil))))) + ;; Look at every row after the current one. + (cdr (memq row (org-element-contents table)))) + ;; No rule below, or rule found ends the table (modulo some + ;; special row): TABLE-CELL is at the bottom of the table. + (when rule-flag (push 'below borders)) + (push 'bottom borders))) + ;; Right/left borders? They can only be specified by column + ;; groups. Column groups are defined in a row starting with "/". + ;; Also a column groups row only contains "<", "<>", ">" or blank + ;; cells. + (catch 'exit + (let ((column (let ((cells (org-element-contents row))) + (- (length cells) (length (memq table-cell cells)))))) + (mapc + (lambda (row) + (unless (eq (org-element-property :type row) 'rule) + (when (equal (org-element-contents + (car (org-element-contents row))) + '("/")) + (let ((column-groups + (mapcar + (lambda (cell) + (let ((value (org-element-contents cell))) + (when (member value '(("<") ("<>") (">") nil)) + (car value)))) + (org-element-contents row)))) + ;; There's a left border when previous cell, if + ;; any, ends a group, or current one starts one. + (when (or (and (not (zerop column)) + (member (elt column-groups (1- column)) + '(">" "<>"))) + (member (elt column-groups column) '("<" "<>"))) + (push 'left borders)) + ;; There's a right border when next cell, if any, + ;; starts a group, or current one ends one. + (when (or (and (/= (1+ column) (length column-groups)) + (member (elt column-groups (1+ column)) + '("<" "<>"))) + (member (elt column-groups column) '(">" "<>"))) + (push 'right borders)) + (throw 'exit nil))))) + ;; Table rows are read in reverse order so last column groups + ;; row has precedence over any previous one. + (reverse (org-element-contents table))))) + ;; Return value. + borders)) + +(defun org-export-table-cell-starts-colgroup-p (table-cell info) + "Non-nil when TABLE-CELL is at the beginning of a row group. +INFO is a plist used as a communication channel." + ;; A cell starts a column group either when it is at the beginning + ;; of a row (or after the special column, if any) or when it has + ;; a left border. + (or (eq (org-element-map (org-export-get-parent table-cell) 'table-cell + 'identity info 'first-match) + table-cell) + (memq 'left (org-export-table-cell-borders table-cell info)))) + +(defun org-export-table-cell-ends-colgroup-p (table-cell info) + "Non-nil when TABLE-CELL is at the end of a row group. +INFO is a plist used as a communication channel." + ;; A cell ends a column group either when it is at the end of a row + ;; or when it has a right border. + (or (eq (car (last (org-element-contents + (org-export-get-parent table-cell)))) + table-cell) + (memq 'right (org-export-table-cell-borders table-cell info)))) + +(defun org-export-table-row-starts-rowgroup-p (table-row info) + "Non-nil when TABLE-ROW is at the beginning of a column group. +INFO is a plist used as a communication channel." + (unless (or (eq (org-element-property :type table-row) 'rule) + (org-export-table-row-is-special-p table-row info)) + (let ((borders (org-export-table-cell-borders + (car (org-element-contents table-row)) info))) + (or (memq 'top borders) (memq 'above borders))))) + +(defun org-export-table-row-ends-rowgroup-p (table-row info) + "Non-nil when TABLE-ROW is at the end of a column group. +INFO is a plist used as a communication channel." + (unless (or (eq (org-element-property :type table-row) 'rule) + (org-export-table-row-is-special-p table-row info)) + (let ((borders (org-export-table-cell-borders + (car (org-element-contents table-row)) info))) + (or (memq 'bottom borders) (memq 'below borders))))) + +(defun org-export-table-row-starts-header-p (table-row info) + "Non-nil when TABLE-ROW is the first table header's row. +INFO is a plist used as a communication channel." + (and (org-export-table-has-header-p + (org-export-get-parent-table table-row) info) + (org-export-table-row-starts-rowgroup-p table-row info) + (= (org-export-table-row-group table-row info) 1))) + +(defun org-export-table-row-ends-header-p (table-row info) + "Non-nil when TABLE-ROW is the last table header's row. +INFO is a plist used as a communication channel." + (and (org-export-table-has-header-p + (org-export-get-parent-table table-row) info) + (org-export-table-row-ends-rowgroup-p table-row info) + (= (org-export-table-row-group table-row info) 1))) + +(defun org-export-table-row-number (table-row info) + "Return TABLE-ROW number. +INFO is a plist used as a communication channel. Return value is +zero-based and ignores separators. The function returns nil for +special colums and separators." + (when (and (eq (org-element-property :type table-row) 'standard) + (not (org-export-table-row-is-special-p table-row info))) + (let ((number 0)) + (org-element-map (org-export-get-parent-table table-row) 'table-row + (lambda (row) + (cond ((eq row table-row) number) + ((eq (org-element-property :type row) 'standard) + (incf number) nil))) + info 'first-match)))) + +(defun org-export-table-dimensions (table info) + "Return TABLE dimensions. + +INFO is a plist used as a communication channel. + +Return value is a CONS like (ROWS . COLUMNS) where +ROWS (resp. COLUMNS) is the number of exportable +rows (resp. columns)." + (let (first-row (columns 0) (rows 0)) + ;; Set number of rows, and extract first one. + (org-element-map table 'table-row + (lambda (row) + (when (eq (org-element-property :type row) 'standard) + (incf rows) + (unless first-row (setq first-row row)))) info) + ;; Set number of columns. + (org-element-map first-row 'table-cell (lambda (cell) (incf columns)) info) + ;; Return value. + (cons rows columns))) + +(defun org-export-table-cell-address (table-cell info) + "Return address of a regular TABLE-CELL object. + +TABLE-CELL is the cell considered. INFO is a plist used as +a communication channel. + +Address is a CONS cell (ROW . COLUMN), where ROW and COLUMN are +zero-based index. Only exportable cells are considered. The +function returns nil for other cells." + (let* ((table-row (org-export-get-parent table-cell)) + (row-number (org-export-table-row-number table-row info))) + (when row-number + (cons row-number + (let ((col-count 0)) + (org-element-map table-row 'table-cell + (lambda (cell) + (if (eq cell table-cell) col-count (incf col-count) nil)) + info 'first-match)))))) + +(defun org-export-get-table-cell-at (address table info) + "Return regular table-cell object at ADDRESS in TABLE. + +Address is a CONS cell (ROW . COLUMN), where ROW and COLUMN are +zero-based index. TABLE is a table type element. INFO is +a plist used as a communication channel. + +If no table-cell, among exportable cells, is found at ADDRESS, +return nil." + (let ((column-pos (cdr address)) (column-count 0)) + (org-element-map + ;; Row at (car address) or nil. + (let ((row-pos (car address)) (row-count 0)) + (org-element-map table 'table-row + (lambda (row) + (cond ((eq (org-element-property :type row) 'rule) nil) + ((= row-count row-pos) row) + (t (incf row-count) nil))) + info 'first-match)) + 'table-cell + (lambda (cell) + (if (= column-count column-pos) cell + (incf column-count) nil)) + info 'first-match))) + + +;;;; For Tables Of Contents +;; +;; `org-export-collect-headlines' builds a list of all exportable +;; headline elements, maybe limited to a certain depth. One can then +;; easily parse it and transcode it. +;; +;; Building lists of tables, figures or listings is quite similar. +;; Once the generic function `org-export-collect-elements' is defined, +;; `org-export-collect-tables', `org-export-collect-figures' and +;; `org-export-collect-listings' can be derived from it. + +(defun org-export-collect-headlines (info &optional n) + "Collect headlines in order to build a table of contents. + +INFO is a plist used as a communication channel. + +When optional argument N is an integer, it specifies the depth of +the table of contents. Otherwise, it is set to the value of the +last headline level. See `org-export-headline-levels' for more +information. + +Return a list of all exportable headlines as parsed elements. +Footnote sections, if any, will be ignored." + (let ((limit (plist-get info :headline-levels))) + (setq n (if (wholenump n) (min n limit) limit)) + (org-element-map (plist-get info :parse-tree) 'headline + #'(lambda (headline) + (unless (org-element-property :footnote-section-p headline) + (let ((level (org-export-get-relative-level headline info))) + (and (<= level n) headline)))) + info))) + +(defun org-export-collect-elements (type info &optional predicate) + "Collect referenceable elements of a determined type. + +TYPE can be a symbol or a list of symbols specifying element +types to search. Only elements with a caption are collected. + +INFO is a plist used as a communication channel. + +When non-nil, optional argument PREDICATE is a function accepting +one argument, an element of type TYPE. It returns a non-nil +value when that element should be collected. + +Return a list of all elements found, in order of appearance." + (org-element-map (plist-get info :parse-tree) type + (lambda (element) + (and (org-element-property :caption element) + (or (not predicate) (funcall predicate element)) + element)) + info)) + +(defun org-export-collect-tables (info) + "Build a list of tables. +INFO is a plist used as a communication channel. + +Return a list of table elements with a caption." + (org-export-collect-elements 'table info)) + +(defun org-export-collect-figures (info predicate) + "Build a list of figures. + +INFO is a plist used as a communication channel. PREDICATE is +a function which accepts one argument: a paragraph element and +whose return value is non-nil when that element should be +collected. + +A figure is a paragraph type element, with a caption, verifying +PREDICATE. The latter has to be provided since a \"figure\" is +a vague concept that may depend on back-end. + +Return a list of elements recognized as figures." + (org-export-collect-elements 'paragraph info predicate)) + +(defun org-export-collect-listings (info) + "Build a list of src blocks. + +INFO is a plist used as a communication channel. + +Return a list of src-block elements with a caption." + (org-export-collect-elements 'src-block info)) + + +;;;; Smart Quotes +;; +;; The main function for the smart quotes sub-system is +;; `org-export-activate-smart-quotes', which replaces every quote in +;; a given string from the parse tree with its "smart" counterpart. +;; +;; Dictionary for smart quotes is stored in +;; `org-export-smart-quotes-alist'. +;; +;; Internally, regexps matching potential smart quotes (checks at +;; string boundaries are also necessary) are defined in +;; `org-export-smart-quotes-regexps'. + +(defconst org-export-smart-quotes-alist + '(("da" + ;; one may use: »...«, "...", ›...‹, or '...'. + ;; http://sproget.dk/raad-og-regler/retskrivningsregler/retskrivningsregler/a7-40-60/a7-58-anforselstegn/ + ;; LaTeX quotes require Babel! + (opening-double-quote :utf-8 "»" :html "»" :latex ">>" + :texinfo "@guillemetright{}") + (closing-double-quote :utf-8 "«" :html "«" :latex "<<" + :texinfo "@guillemetleft{}") + (opening-single-quote :utf-8 "›" :html "›" :latex "\\frq{}" + :texinfo "@guilsinglright{}") + (closing-single-quote :utf-8 "‹" :html "‹" :latex "\\flq{}" + :texinfo "@guilsingleft{}") + (apostrophe :utf-8 "’" :html "’")) + ("de" + (opening-double-quote :utf-8 "„" :html "„" :latex "\"`" + :texinfo "@quotedblbase{}") + (closing-double-quote :utf-8 "“" :html "“" :latex "\"'" + :texinfo "@quotedblleft{}") + (opening-single-quote :utf-8 "‚" :html "‚" :latex "\\glq{}" + :texinfo "@quotesinglbase{}") + (closing-single-quote :utf-8 "‘" :html "‘" :latex "\\grq{}" + :texinfo "@quoteleft{}") + (apostrophe :utf-8 "’" :html "’")) + ("en" + (opening-double-quote :utf-8 "“" :html "“" :latex "``" :texinfo "``") + (closing-double-quote :utf-8 "”" :html "”" :latex "''" :texinfo "''") + (opening-single-quote :utf-8 "‘" :html "‘" :latex "`" :texinfo "`") + (closing-single-quote :utf-8 "’" :html "’" :latex "'" :texinfo "'") + (apostrophe :utf-8 "’" :html "’")) + ("es" + (opening-double-quote :utf-8 "«" :html "«" :latex "\\guillemotleft{}" + :texinfo "@guillemetleft{}") + (closing-double-quote :utf-8 "»" :html "»" :latex "\\guillemotright{}" + :texinfo "@guillemetright{}") + (opening-single-quote :utf-8 "“" :html "“" :latex "``" :texinfo "``") + (closing-single-quote :utf-8 "”" :html "”" :latex "''" :texinfo "''") + (apostrophe :utf-8 "’" :html "’")) + ("fr" + (opening-double-quote :utf-8 "« " :html "« " :latex "\\og " + :texinfo "@guillemetleft{}@tie{}") + (closing-double-quote :utf-8 " »" :html " »" :latex "\\fg{}" + :texinfo "@tie{}@guillemetright{}") + (opening-single-quote :utf-8 "« " :html "« " :latex "\\og " + :texinfo "@guillemetleft{}@tie{}") + (closing-single-quote :utf-8 " »" :html " »" :latex "\\fg{}" + :texinfo "@tie{}@guillemetright{}") + (apostrophe :utf-8 "’" :html "’")) + ("no" + ;; https://nn.wikipedia.org/wiki/Sitatteikn + (opening-double-quote :utf-8 "«" :html "«" :latex "\\guillemotleft{}" + :texinfo "@guillemetleft{}") + (closing-double-quote :utf-8 "»" :html "»" :latex "\\guillemotright{}" + :texinfo "@guillemetright{}") + (opening-single-quote :utf-8 "‘" :html "‘" :latex "`" :texinfo "`") + (closing-single-quote :utf-8 "’" :html "’" :latex "'" :texinfo "'") + (apostrophe :utf-8 "’" :html "’")) + ("nb" + ;; https://nn.wikipedia.org/wiki/Sitatteikn + (opening-double-quote :utf-8 "«" :html "«" :latex "\\guillemotleft{}" + :texinfo "@guillemetleft{}") + (closing-double-quote :utf-8 "»" :html "»" :latex "\\guillemotright{}" + :texinfo "@guillemetright{}") + (opening-single-quote :utf-8 "‘" :html "‘" :latex "`" :texinfo "`") + (closing-single-quote :utf-8 "’" :html "’" :latex "'" :texinfo "'") + (apostrophe :utf-8 "’" :html "’")) + ("nn" + ;; https://nn.wikipedia.org/wiki/Sitatteikn + (opening-double-quote :utf-8 "«" :html "«" :latex "\\guillemotleft{}" + :texinfo "@guillemetleft{}") + (closing-double-quote :utf-8 "»" :html "»" :latex "\\guillemotright{}" + :texinfo "@guillemetright{}") + (opening-single-quote :utf-8 "‘" :html "‘" :latex "`" :texinfo "`") + (closing-single-quote :utf-8 "’" :html "’" :latex "'" :texinfo "'") + (apostrophe :utf-8 "’" :html "’")) + ("sv" + ;; based on https://sv.wikipedia.org/wiki/Citattecken + (opening-double-quote :utf-8 "”" :html "”" :latex "’’" :texinfo "’’") + (closing-double-quote :utf-8 "”" :html "”" :latex "’’" :texinfo "’’") + (opening-single-quote :utf-8 "’" :html "’" :latex "’" :texinfo "`") + (closing-single-quote :utf-8 "’" :html "’" :latex "’" :texinfo "'") + (apostrophe :utf-8 "’" :html "’")) + ) + "Smart quotes translations. + +Alist whose CAR is a language string and CDR is an alist with +quote type as key and a plist associating various encodings to +their translation as value. + +A quote type can be any symbol among `opening-double-quote', +`closing-double-quote', `opening-single-quote', +`closing-single-quote' and `apostrophe'. + +Valid encodings include `:utf-8', `:html', `:latex' and +`:texinfo'. + +If no translation is found, the quote character is left as-is.") + +(defconst org-export-smart-quotes-regexps + (list + ;; Possible opening quote at beginning of string. + "\\`\\([\"']\\)\\(\\w\\|\\s.\\|\\s_\\)" + ;; Possible closing quote at beginning of string. + "\\`\\([\"']\\)\\(\\s-\\|\\s)\\|\\s.\\)" + ;; Possible apostrophe at beginning of string. + "\\`\\('\\)\\S-" + ;; Opening single and double quotes. + "\\(?:\\s-\\|\\s(\\)\\([\"']\\)\\(?:\\w\\|\\s.\\|\\s_\\)" + ;; Closing single and double quotes. + "\\(?:\\w\\|\\s.\\|\\s_\\)\\([\"']\\)\\(?:\\s-\\|\\s)\\|\\s.\\)" + ;; Apostrophe. + "\\S-\\('\\)\\S-" + ;; Possible opening quote at end of string. + "\\(?:\\s-\\|\\s(\\)\\([\"']\\)\\'" + ;; Possible closing quote at end of string. + "\\(?:\\w\\|\\s.\\|\\s_\\)\\([\"']\\)\\'" + ;; Possible apostrophe at end of string. + "\\S-\\('\\)\\'") + "List of regexps matching a quote or an apostrophe. +In every regexp, quote or apostrophe matched is put in group 1.") + +(defun org-export-activate-smart-quotes (s encoding info &optional original) + "Replace regular quotes with \"smart\" quotes in string S. + +ENCODING is a symbol among `:html', `:latex', `:texinfo' and +`:utf-8'. INFO is a plist used as a communication channel. + +The function has to retrieve information about string +surroundings in parse tree. It can only happen with an +unmodified string. Thus, if S has already been through another +process, a non-nil ORIGINAL optional argument will provide that +original string. + +Return the new string." + (if (equal s "") "" + (let* ((prev (org-export-get-previous-element (or original s) info)) + ;; Try to be flexible when computing number of blanks + ;; before object. The previous object may be a string + ;; introduced by the back-end and not completely parsed. + (pre-blank (and prev + (or (org-element-property :post-blank prev) + ;; A string with missing `:post-blank' + ;; property. + (and (stringp prev) + (string-match " *\\'" prev) + (length (match-string 0 prev))) + ;; Fallback value. + 0))) + (next (org-export-get-next-element (or original s) info)) + (get-smart-quote + (lambda (q type) + ;; Return smart quote associated to a give quote Q, as + ;; a string. TYPE is a symbol among `open', `close' and + ;; `apostrophe'. + (let ((key (case type + (apostrophe 'apostrophe) + (open (if (equal "'" q) 'opening-single-quote + 'opening-double-quote)) + (otherwise (if (equal "'" q) 'closing-single-quote + 'closing-double-quote))))) + (or (plist-get + (cdr (assq key + (cdr (assoc (plist-get info :language) + org-export-smart-quotes-alist)))) + encoding) + q))))) + (if (or (equal "\"" s) (equal "'" s)) + ;; Only a quote: no regexp can match. We have to check both + ;; sides and decide what to do. + (cond ((and (not prev) (not next)) s) + ((not prev) (funcall get-smart-quote s 'open)) + ((and (not next) (zerop pre-blank)) + (funcall get-smart-quote s 'close)) + ((not next) s) + ((zerop pre-blank) (funcall get-smart-quote s 'apostrophe)) + (t (funcall get-smart-quote 'open))) + ;; 1. Replace quote character at the beginning of S. + (cond + ;; Apostrophe? + ((and prev (zerop pre-blank) + (string-match (nth 2 org-export-smart-quotes-regexps) s)) + (setq s (replace-match + (funcall get-smart-quote (match-string 1 s) 'apostrophe) + nil t s 1))) + ;; Closing quote? + ((and prev (zerop pre-blank) + (string-match (nth 1 org-export-smart-quotes-regexps) s)) + (setq s (replace-match + (funcall get-smart-quote (match-string 1 s) 'close) + nil t s 1))) + ;; Opening quote? + ((and (or (not prev) (> pre-blank 0)) + (string-match (nth 0 org-export-smart-quotes-regexps) s)) + (setq s (replace-match + (funcall get-smart-quote (match-string 1 s) 'open) + nil t s 1)))) + ;; 2. Replace quotes in the middle of the string. + (setq s (replace-regexp-in-string + ;; Opening quotes. + (nth 3 org-export-smart-quotes-regexps) + (lambda (text) + (funcall get-smart-quote (match-string 1 text) 'open)) + s nil t 1)) + (setq s (replace-regexp-in-string + ;; Closing quotes. + (nth 4 org-export-smart-quotes-regexps) + (lambda (text) + (funcall get-smart-quote (match-string 1 text) 'close)) + s nil t 1)) + (setq s (replace-regexp-in-string + ;; Apostrophes. + (nth 5 org-export-smart-quotes-regexps) + (lambda (text) + (funcall get-smart-quote (match-string 1 text) 'apostrophe)) + s nil t 1)) + ;; 3. Replace quote character at the end of S. + (cond + ;; Apostrophe? + ((and next (string-match (nth 8 org-export-smart-quotes-regexps) s)) + (setq s (replace-match + (funcall get-smart-quote (match-string 1 s) 'apostrophe) + nil t s 1))) + ;; Closing quote? + ((and (not next) + (string-match (nth 7 org-export-smart-quotes-regexps) s)) + (setq s (replace-match + (funcall get-smart-quote (match-string 1 s) 'close) + nil t s 1))) + ;; Opening quote? + ((and next (string-match (nth 6 org-export-smart-quotes-regexps) s)) + (setq s (replace-match + (funcall get-smart-quote (match-string 1 s) 'open) + nil t s 1)))) + ;; Return string with smart quotes. + s)))) + +;;;; Topology +;; +;; Here are various functions to retrieve information about the +;; neighbourhood of a given element or object. Neighbours of interest +;; are direct parent (`org-export-get-parent'), parent headline +;; (`org-export-get-parent-headline'), first element containing an +;; object, (`org-export-get-parent-element'), parent table +;; (`org-export-get-parent-table'), previous element or object +;; (`org-export-get-previous-element') and next element or object +;; (`org-export-get-next-element'). +;; +;; `org-export-get-genealogy' returns the full genealogy of a given +;; element or object, from closest parent to full parse tree. + +(defsubst org-export-get-parent (blob) + "Return BLOB parent or nil. +BLOB is the element or object considered." + (org-element-property :parent blob)) + +(defun org-export-get-genealogy (blob) + "Return full genealogy relative to a given element or object. + +BLOB is the element or object being considered. + +Ancestors are returned from closest to farthest, the last one +being the full parse tree." + (let (genealogy (parent blob)) + (while (setq parent (org-element-property :parent parent)) + (push parent genealogy)) + (nreverse genealogy))) + +(defun org-export-get-parent-headline (blob) + "Return BLOB parent headline or nil. +BLOB is the element or object being considered." + (let ((parent blob)) + (while (and (setq parent (org-element-property :parent parent)) + (not (eq (org-element-type parent) 'headline)))) + parent)) + +(defun org-export-get-parent-element (object) + "Return first element containing OBJECT or nil. +OBJECT is the object to consider." + (let ((parent object)) + (while (and (setq parent (org-element-property :parent parent)) + (memq (org-element-type parent) org-element-all-objects))) + parent)) + +(defun org-export-get-parent-table (object) + "Return OBJECT parent table or nil. +OBJECT is either a `table-cell' or `table-element' type object." + (let ((parent object)) + (while (and (setq parent (org-element-property :parent parent)) + (not (eq (org-element-type parent) 'table)))) + parent)) + +(defun org-export-get-previous-element (blob info &optional n) + "Return previous element or object. + +BLOB is an element or object. INFO is a plist used as +a communication channel. Return previous exportable element or +object, a string, or nil. + +When optional argument N is a positive integer, return a list +containing up to N siblings before BLOB, from farthest to +closest. With any other non-nil value, return a list containing +all of them." + (let ((siblings + ;; An object can belong to the contents of its parent or + ;; to a secondary string. We check the latter option + ;; first. + (let ((parent (org-export-get-parent blob))) + (or (let ((sec-value (org-element-property + (cdr (assq (org-element-type parent) + org-element-secondary-value-alist)) + parent))) + (and (memq blob sec-value) sec-value)) + (org-element-contents parent)))) + prev) + (catch 'exit + (mapc (lambda (obj) + (cond ((memq obj (plist-get info :ignore-list))) + ((null n) (throw 'exit obj)) + ((not (wholenump n)) (push obj prev)) + ((zerop n) (throw 'exit prev)) + (t (decf n) (push obj prev)))) + (cdr (memq blob (reverse siblings)))) + prev))) + +(defun org-export-get-next-element (blob info &optional n) + "Return next element or object. + +BLOB is an element or object. INFO is a plist used as +a communication channel. Return next exportable element or +object, a string, or nil. + +When optional argument N is a positive integer, return a list +containing up to N siblings after BLOB, from closest to farthest. +With any other non-nil value, return a list containing all of +them." + (let ((siblings + ;; An object can belong to the contents of its parent or to + ;; a secondary string. We check the latter option first. + (let ((parent (org-export-get-parent blob))) + (or (let ((sec-value (org-element-property + (cdr (assq (org-element-type parent) + org-element-secondary-value-alist)) + parent))) + (cdr (memq blob sec-value))) + (cdr (memq blob (org-element-contents parent)))))) + next) + (catch 'exit + (mapc (lambda (obj) + (cond ((memq obj (plist-get info :ignore-list))) + ((null n) (throw 'exit obj)) + ((not (wholenump n)) (push obj next)) + ((zerop n) (throw 'exit (nreverse next))) + (t (decf n) (push obj next)))) + siblings) + (nreverse next)))) + + +;;;; Translation +;; +;; `org-export-translate' translates a string according to the language +;; specified by the LANGUAGE keyword. `org-export-dictionary' contains +;; the dictionary used for the translation. + +(defconst org-export-dictionary + '(("%e %n: %c" + ("fr" :default "%e %n : %c" :html "%e %n : %c")) + ("Author" + ("ca" :default "Autor") + ("cs" :default "Autor") + ("da" :default "Forfatter") + ("de" :default "Autor") + ("eo" :html "Aŭtoro") + ("es" :default "Autor") + ("fi" :html "Tekijä") + ("fr" :default "Auteur") + ("hu" :default "Szerzõ") + ("is" :html "Höfundur") + ("it" :default "Autore") + ("ja" :html "著者" :utf-8 "著者") + ("nl" :default "Auteur") + ("no" :default "Forfatter") + ("nb" :default "Forfatter") + ("nn" :default "Forfattar") + ("pl" :default "Autor") + ("ru" :html "Автор" :utf-8 "Автор") + ("sv" :html "Författare") + ("uk" :html "Автор" :utf-8 "Автор") + ("zh-CN" :html "作者" :utf-8 "作者") + ("zh-TW" :html "作者" :utf-8 "作者")) + ("Date" + ("ca" :default "Data") + ("cs" :default "Datum") + ("da" :default "Dato") + ("de" :default "Datum") + ("eo" :default "Dato") + ("es" :default "Fecha") + ("fi" :html "Päivämäärä") + ("hu" :html "Dátum") + ("is" :default "Dagsetning") + ("it" :default "Data") + ("ja" :html "日付" :utf-8 "日付") + ("nl" :default "Datum") + ("no" :default "Dato") + ("nb" :default "Dato") + ("nn" :default "Dato") + ("pl" :default "Data") + ("ru" :html "Дата" :utf-8 "Дата") + ("sv" :default "Datum") + ("uk" :html "Дата" :utf-8 "Дата") + ("zh-CN" :html "日期" :utf-8 "日期") + ("zh-TW" :html "日期" :utf-8 "日期")) + ("Equation" + ("da" :default "Ligning") + ("de" :default "Gleichung") + ("es" :html "Ecuación" :default "Ecuación") + ("fr" :ascii "Equation" :default "Équation") + ("no" :default "Ligning") + ("nb" :default "Ligning") + ("nn" :default "Likning") + ("sv" :default "Ekvation") + ("zh-CN" :html "方程" :utf-8 "方程")) + ("Figure" + ("da" :default "Figur") + ("de" :default "Abbildung") + ("es" :default "Figura") + ("ja" :html "図" :utf-8 "図") + ("no" :default "Illustrasjon") + ("nb" :default "Illustrasjon") + ("nn" :default "Illustrasjon") + ("sv" :default "Illustration") + ("zh-CN" :html "图" :utf-8 "图")) + ("Figure %d:" + ("da" :default "Figur %d") + ("de" :default "Abbildung %d:") + ("es" :default "Figura %d:") + ("fr" :default "Figure %d :" :html "Figure %d :") + ("ja" :html "図%d: " :utf-8 "図%d: ") + ("no" :default "Illustrasjon %d") + ("nb" :default "Illustrasjon %d") + ("nn" :default "Illustrasjon %d") + ("sv" :default "Illustration %d") + ("zh-CN" :html "图%d " :utf-8 "图%d ")) + ("Footnotes" + ("ca" :html "Peus de pàgina") + ("cs" :default "Pozn\xe1mky pod carou") + ("da" :default "Fodnoter") + ("de" :html "Fußnoten" :default "Fußnoten") + ("eo" :default "Piednotoj") + ("es" :html "Nota al pie de página" :default "Nota al pie de página") + ("fi" :default "Alaviitteet") + ("fr" :default "Notes de bas de page") + ("hu" :html "Lábjegyzet") + ("is" :html "Aftanmálsgreinar") + ("it" :html "Note a piè di pagina") + ("ja" :html "脚注" :utf-8 "脚注") + ("nl" :default "Voetnoten") + ("no" :default "Fotnoter") + ("nb" :default "Fotnoter") + ("nn" :default "Fotnotar") + ("pl" :default "Przypis") + ("ru" :html "Сноски" :utf-8 "Сноски") + ("sv" :default "Fotnoter") + ("uk" :html "Примітки" + :utf-8 "Примітки") + ("zh-CN" :html "脚注" :utf-8 "脚注") + ("zh-TW" :html "腳註" :utf-8 "腳註")) + ("List of Listings" + ("da" :default "Programmer") + ("de" :default "Programmauflistungsverzeichnis") + ("es" :default "Indice de Listados de programas") + ("fr" :default "Liste des programmes") + ("no" :default "Dataprogrammer") + ("nb" :default "Dataprogrammer") + ("zh-CN" :html "代码目录" :utf-8 "代码目录")) + ("List of Tables" + ("da" :default "Tabeller") + ("de" :default "Tabellenverzeichnis") + ("es" :default "Indice de tablas") + ("fr" :default "Liste des tableaux") + ("no" :default "Tabeller") + ("nb" :default "Tabeller") + ("nn" :default "Tabeller") + ("sv" :default "Tabeller") + ("zh-CN" :html "表格目录" :utf-8 "表格目录")) + ("Listing %d:" + ("da" :default "Program %d") + ("de" :default "Programmlisting %d") + ("es" :default "Listado de programa %d") + ("fr" :default "Programme %d :" :html "Programme %d :") + ("no" :default "Dataprogram") + ("nb" :default "Dataprogram") + ("zh-CN" :html "代码%d " :utf-8 "代码%d ")) + ("See section %s" + ("da" :default "jævnfør afsnit %s") + ("de" :default "siehe Abschnitt %s") + ("es" :default "vea seccion %s") + ("fr" :default "cf. section %s") + ("zh-CN" :html "参见第%d节" :utf-8 "参见第%s节")) + ("Table" + ("de" :default "Tabelle") + ("es" :default "Tabla") + ("fr" :default "Tableau") + ("ja" :html "表" :utf-8 "表") + ("zh-CN" :html "表" :utf-8 "表")) + ("Table %d:" + ("da" :default "Tabel %d") + ("de" :default "Tabelle %d") + ("es" :default "Tabla %d") + ("fr" :default "Tableau %d :") + ("ja" :html "表%d:" :utf-8 "表%d:") + ("no" :default "Tabell %d") + ("nb" :default "Tabell %d") + ("nn" :default "Tabell %d") + ("sv" :default "Tabell %d") + ("zh-CN" :html "表%d " :utf-8 "表%d ")) + ("Table of Contents" + ("ca" :html "Índex") + ("cs" :default "Obsah") + ("da" :default "Indhold") + ("de" :default "Inhaltsverzeichnis") + ("eo" :default "Enhavo") + ("es" :html "Índice") + ("fi" :html "Sisällysluettelo") + ("fr" :ascii "Sommaire" :default "Table des matières") + ("hu" :html "Tartalomjegyzék") + ("is" :default "Efnisyfirlit") + ("it" :default "Indice") + ("ja" :html "目次" :utf-8 "目次") + ("nl" :default "Inhoudsopgave") + ("no" :default "Innhold") + ("nb" :default "Innhold") + ("nn" :default "Innhald") + ("pl" :html "Spis treści") + ("ru" :html "Содержание" + :utf-8 "Содержание") + ("sv" :html "Innehåll") + ("uk" :html "Зміст" :utf-8 "Зміст") + ("zh-CN" :html "目录" :utf-8 "目录") + ("zh-TW" :html "目錄" :utf-8 "目錄")) + ("Unknown reference" + ("da" :default "ukendt reference") + ("de" :default "Unbekannter Verweis") + ("es" :default "referencia desconocida") + ("fr" :ascii "Destination inconnue" :default "Référence inconnue") + ("zh-CN" :html "未知引用" :utf-8 "未知引用"))) + "Dictionary for export engine. + +Alist whose CAR is the string to translate and CDR is an alist +whose CAR is the language string and CDR is a plist whose +properties are possible charsets and values translated terms. + +It is used as a database for `org-export-translate'. Since this +function returns the string as-is if no translation was found, +the variable only needs to record values different from the +entry.") + +(defun org-export-translate (s encoding info) + "Translate string S according to language specification. + +ENCODING is a symbol among `:ascii', `:html', `:latex', `:latin1' +and `:utf-8'. INFO is a plist used as a communication channel. + +Translation depends on `:language' property. Return the +translated string. If no translation is found, try to fall back +to `:default' encoding. If it fails, return S." + (let* ((lang (plist-get info :language)) + (translations (cdr (assoc lang + (cdr (assoc s org-export-dictionary)))))) + (or (plist-get translations encoding) + (plist-get translations :default) + s))) + + + +;;; Asynchronous Export +;; +;; `org-export-async-start' is the entry point for asynchronous +;; export. It recreates current buffer (including visibility, +;; narrowing and visited file) in an external Emacs process, and +;; evaluates a command there. It then applies a function on the +;; returned results in the current process. +;; +;; At a higher level, `org-export-to-buffer' and `org-export-to-file' +;; allow to export to a buffer or a file, asynchronously or not. +;; +;; `org-export-output-file-name' is an auxiliary function meant to be +;; used with `org-export-to-file'. With a given extension, it tries +;; to provide a canonical file name to write export output to. +;; +;; Asynchronously generated results are never displayed directly. +;; Instead, they are stored in `org-export-stack-contents'. They can +;; then be retrieved by calling `org-export-stack'. +;; +;; Export Stack is viewed through a dedicated major mode +;;`org-export-stack-mode' and tools: `org-export-stack-refresh', +;;`org-export-stack-delete', `org-export-stack-view' and +;;`org-export-stack-clear'. +;; +;; For back-ends, `org-export-add-to-stack' add a new source to stack. +;; It should be used whenever `org-export-async-start' is called. + +(defmacro org-export-async-start (fun &rest body) + "Call function FUN on the results returned by BODY evaluation. + +BODY evaluation happens in an asynchronous process, from a buffer +which is an exact copy of the current one. + +Use `org-export-add-to-stack' in FUN in order to register results +in the stack. + +This is a low level function. See also `org-export-to-buffer' +and `org-export-to-file' for more specialized functions." + (declare (indent 1) (debug t)) + (org-with-gensyms (process temp-file copy-fun proc-buffer coding) + ;; Write the full sexp evaluating BODY in a copy of the current + ;; buffer to a temporary file, as it may be too long for program + ;; args in `start-process'. + `(with-temp-message "Initializing asynchronous export process" + (let ((,copy-fun (org-export--generate-copy-script (current-buffer))) + (,temp-file (make-temp-file "org-export-process")) + (,coding buffer-file-coding-system)) + (with-temp-file ,temp-file + (insert + ;; Null characters (from variable values) are inserted + ;; within the file. As a consequence, coding system for + ;; buffer contents will not be recognized properly. So, + ;; we make sure it is the same as the one used to display + ;; the original buffer. + (format ";; -*- coding: %s; -*-\n%S" + ,coding + `(with-temp-buffer + (when org-export-async-debug '(setq debug-on-error t)) + ;; Ignore `kill-emacs-hook' and code evaluation + ;; queries from Babel as we need a truly + ;; non-interactive process. + (setq kill-emacs-hook nil + org-babel-confirm-evaluate-answer-no t) + ;; Initialize export framework. + (require 'ox) + ;; Re-create current buffer there. + (funcall ,,copy-fun) + (restore-buffer-modified-p nil) + ;; Sexp to evaluate in the buffer. + (print (progn ,,@body)))))) + ;; Start external process. + (let* ((process-connection-type nil) + (,proc-buffer (generate-new-buffer-name "*Org Export Process*")) + (,process + (start-process + "org-export-process" ,proc-buffer + (expand-file-name invocation-name invocation-directory) + "-Q" "--batch" + "-l" org-export-async-init-file + "-l" ,temp-file))) + ;; Register running process in stack. + (org-export-add-to-stack (get-buffer ,proc-buffer) nil ,process) + ;; Set-up sentinel in order to catch results. + (let ((handler ,fun)) + (set-process-sentinel + ,process + `(lambda (p status) + (let ((proc-buffer (process-buffer p))) + (when (eq (process-status p) 'exit) + (unwind-protect + (if (zerop (process-exit-status p)) + (unwind-protect + (let ((results + (with-current-buffer proc-buffer + (goto-char (point-max)) + (backward-sexp) + (read (current-buffer))))) + (funcall ,handler results)) + (unless org-export-async-debug + (and (get-buffer proc-buffer) + (kill-buffer proc-buffer)))) + (org-export-add-to-stack proc-buffer nil p) + (ding) + (message "Process '%s' exited abnormally" p)) + (unless org-export-async-debug + (delete-file ,,temp-file))))))))))))) + +;;;###autoload +(defun org-export-to-buffer + (backend buffer + &optional async subtreep visible-only body-only ext-plist + post-process) + "Call `org-export-as' with output to a specified buffer. + +BACKEND is either an export back-end, as returned by, e.g., +`org-export-create-backend', or a symbol referring to +a registered back-end. + +BUFFER is the name of the output buffer. If it already exists, +it will be erased first, otherwise, it will be created. + +A non-nil optional argument ASYNC means the process should happen +asynchronously. The resulting buffer should then be accessible +through the `org-export-stack' interface. When ASYNC is nil, the +buffer is displayed if `org-export-show-temporary-export-buffer' +is non-nil. + +Optional arguments SUBTREEP, VISIBLE-ONLY, BODY-ONLY and +EXT-PLIST are similar to those used in `org-export-as', which +see. + +Optional argument POST-PROCESS is a function which should accept +no argument. It is always called within the current process, +from BUFFER, with point at its beginning. Export back-ends can +use it to set a major mode there, e.g, + + \(defun org-latex-export-as-latex + \(&optional async subtreep visible-only body-only ext-plist) + \(interactive) + \(org-export-to-buffer 'latex \"*Org LATEX Export*\" + async subtreep visible-only body-only ext-plist (lambda () (LaTeX-mode)))) + +This function returns BUFFER." + (declare (indent 2)) + (if async + (org-export-async-start + `(lambda (output) + (with-current-buffer (get-buffer-create ,buffer) + (erase-buffer) + (setq buffer-file-coding-system ',buffer-file-coding-system) + (insert output) + (goto-char (point-min)) + (org-export-add-to-stack (current-buffer) ',backend) + (ignore-errors (funcall ,post-process)))) + `(org-export-as + ',backend ,subtreep ,visible-only ,body-only ',ext-plist)) + (let ((output + (org-export-as backend subtreep visible-only body-only ext-plist)) + (buffer (get-buffer-create buffer)) + (encoding buffer-file-coding-system)) + (when (and (org-string-nw-p output) (org-export--copy-to-kill-ring-p)) + (org-kill-new output)) + (with-current-buffer buffer + (erase-buffer) + (setq buffer-file-coding-system encoding) + (insert output) + (goto-char (point-min)) + (and (functionp post-process) (funcall post-process))) + (when org-export-show-temporary-export-buffer + (switch-to-buffer-other-window buffer)) + buffer))) + +;;;###autoload +(defun org-export-to-file + (backend file &optional async subtreep visible-only body-only ext-plist + post-process) + "Call `org-export-as' with output to a specified file. + +BACKEND is either an export back-end, as returned by, e.g., +`org-export-create-backend', or a symbol referring to +a registered back-end. FILE is the name of the output file, as +a string. + +A non-nil optional argument ASYNC means the process should happen +asynchronously. The resulting buffer file then be accessible +through the `org-export-stack' interface. + +Optional arguments SUBTREEP, VISIBLE-ONLY, BODY-ONLY and +EXT-PLIST are similar to those used in `org-export-as', which +see. + +Optional argument POST-PROCESS is called with FILE as its +argument and happens asynchronously when ASYNC is non-nil. It +has to return a file name, or nil. Export back-ends can use this +to send the output file through additional processing, e.g, + + \(defun org-latex-export-to-latex + \(&optional async subtreep visible-only body-only ext-plist) + \(interactive) + \(let ((outfile (org-export-output-file-name \".tex\" subtreep))) + \(org-export-to-file 'latex outfile + async subtreep visible-only body-only ext-plist + \(lambda (file) (org-latex-compile file))) + +The function returns either a file name returned by POST-PROCESS, +or FILE." + (declare (indent 2)) + (if (not (file-writable-p file)) (error "Output file not writable") + (let ((encoding (or org-export-coding-system buffer-file-coding-system))) + (if async + (org-export-async-start + `(lambda (file) + (org-export-add-to-stack (expand-file-name file) ',backend)) + `(let ((output + (org-export-as + ',backend ,subtreep ,visible-only ,body-only + ',ext-plist))) + (with-temp-buffer + (insert output) + (let ((coding-system-for-write ',encoding)) + (write-file ,file))) + (or (ignore-errors (funcall ',post-process ,file)) ,file))) + (let ((output (org-export-as + backend subtreep visible-only body-only ext-plist))) + (with-temp-buffer + (insert output) + (let ((coding-system-for-write encoding)) + (write-file file))) + (when (and (org-export--copy-to-kill-ring-p) (org-string-nw-p output)) + (org-kill-new output)) + ;; Get proper return value. + (or (and (functionp post-process) (funcall post-process file)) + file)))))) + +(defun org-export-output-file-name (extension &optional subtreep pub-dir) + "Return output file's name according to buffer specifications. + +EXTENSION is a string representing the output file extension, +with the leading dot. + +With a non-nil optional argument SUBTREEP, try to determine +output file's name by looking for \"EXPORT_FILE_NAME\" property +of subtree at point. + +When optional argument PUB-DIR is set, use it as the publishing +directory. + +When optional argument VISIBLE-ONLY is non-nil, don't export +contents of hidden elements. + +Return file name as a string." + (let* ((visited-file (buffer-file-name (buffer-base-buffer))) + (base-name + ;; File name may come from EXPORT_FILE_NAME subtree + ;; property, assuming point is at beginning of said + ;; sub-tree. + (file-name-sans-extension + (or (and subtreep + (org-entry-get + (save-excursion + (ignore-errors (org-back-to-heading) (point))) + "EXPORT_FILE_NAME" t)) + ;; File name may be extracted from buffer's associated + ;; file, if any. + (and visited-file (file-name-nondirectory visited-file)) + ;; Can't determine file name on our own: Ask user. + (let ((read-file-name-function + (and org-completion-use-ido 'ido-read-file-name))) + (read-file-name + "Output file: " pub-dir nil nil nil + (lambda (name) + (string= (file-name-extension name t) extension))))))) + (output-file + ;; Build file name. Enforce EXTENSION over whatever user + ;; may have come up with. PUB-DIR, if defined, always has + ;; precedence over any provided path. + (cond + (pub-dir + (concat (file-name-as-directory pub-dir) + (file-name-nondirectory base-name) + extension)) + ((file-name-absolute-p base-name) (concat base-name extension)) + (t (concat (file-name-as-directory ".") base-name extension))))) + ;; If writing to OUTPUT-FILE would overwrite original file, append + ;; EXTENSION another time to final name. + (if (and visited-file (org-file-equal-p visited-file output-file)) + (concat output-file extension) + output-file))) + +(defun org-export-add-to-stack (source backend &optional process) + "Add a new result to export stack if not present already. + +SOURCE is a buffer or a file name containing export results. +BACKEND is a symbol representing export back-end used to generate +it. + +Entries already pointing to SOURCE and unavailable entries are +removed beforehand. Return the new stack." + (setq org-export-stack-contents + (cons (list source backend (or process (current-time))) + (org-export-stack-remove source)))) + +(defun org-export-stack () + "Menu for asynchronous export results and running processes." + (interactive) + (let ((buffer (get-buffer-create "*Org Export Stack*"))) + (set-buffer buffer) + (when (zerop (buffer-size)) (org-export-stack-mode)) + (org-export-stack-refresh) + (pop-to-buffer buffer)) + (message "Type \"q\" to quit, \"?\" for help")) + +(defun org-export--stack-source-at-point () + "Return source from export results at point in stack." + (let ((source (car (nth (1- (org-current-line)) org-export-stack-contents)))) + (if (not source) (error "Source unavailable, please refresh buffer") + (let ((source-name (if (stringp source) source (buffer-name source)))) + (if (save-excursion + (beginning-of-line) + (looking-at (concat ".* +" (regexp-quote source-name) "$"))) + source + ;; SOURCE is not consistent with current line. The stack + ;; view is outdated. + (error "Source unavailable; type `g' to update buffer")))))) + +(defun org-export-stack-clear () + "Remove all entries from export stack." + (interactive) + (setq org-export-stack-contents nil)) + +(defun org-export-stack-refresh (&rest dummy) + "Refresh the asynchronous export stack. +DUMMY is ignored. Unavailable sources are removed from the list. +Return the new stack." + (let ((inhibit-read-only t)) + (org-preserve-lc + (erase-buffer) + (insert (concat + (let ((counter 0)) + (mapconcat + (lambda (entry) + (let ((proc-p (processp (nth 2 entry)))) + (concat + ;; Back-end. + (format " %-12s " (or (nth 1 entry) "")) + ;; Age. + (let ((data (nth 2 entry))) + (if proc-p (format " %6s " (process-status data)) + ;; Compute age of the results. + (org-format-seconds + "%4h:%.2m " + (float-time (time-since data))))) + ;; Source. + (format " %s" + (let ((source (car entry))) + (if (stringp source) source + (buffer-name source))))))) + ;; Clear stack from exited processes, dead buffers or + ;; non-existent files. + (setq org-export-stack-contents + (org-remove-if-not + (lambda (el) + (if (processp (nth 2 el)) + (buffer-live-p (process-buffer (nth 2 el))) + (let ((source (car el))) + (if (bufferp source) (buffer-live-p source) + (file-exists-p source))))) + org-export-stack-contents)) "\n"))))))) + +(defun org-export-stack-remove (&optional source) + "Remove export results at point from stack. +If optional argument SOURCE is non-nil, remove it instead." + (interactive) + (let ((source (or source (org-export--stack-source-at-point)))) + (setq org-export-stack-contents + (org-remove-if (lambda (el) (equal (car el) source)) + org-export-stack-contents)))) + +(defun org-export-stack-view (&optional in-emacs) + "View export results at point in stack. +With an optional prefix argument IN-EMACS, force viewing files +within Emacs." + (interactive "P") + (let ((source (org-export--stack-source-at-point))) + (cond ((processp source) + (org-switch-to-buffer-other-window (process-buffer source))) + ((bufferp source) (org-switch-to-buffer-other-window source)) + (t (org-open-file source in-emacs))))) + +(defvar org-export-stack-mode-map + (let ((km (make-sparse-keymap))) + (define-key km " " 'next-line) + (define-key km "n" 'next-line) + (define-key km "\C-n" 'next-line) + (define-key km [down] 'next-line) + (define-key km "p" 'previous-line) + (define-key km "\C-p" 'previous-line) + (define-key km "\C-?" 'previous-line) + (define-key km [up] 'previous-line) + (define-key km "C" 'org-export-stack-clear) + (define-key km "v" 'org-export-stack-view) + (define-key km (kbd "RET") 'org-export-stack-view) + (define-key km "d" 'org-export-stack-remove) + km) + "Keymap for Org Export Stack.") + +(define-derived-mode org-export-stack-mode special-mode "Org-Stack" + "Mode for displaying asynchronous export stack. + +Type \\[org-export-stack] to visualize the asynchronous export +stack. + +In an Org Export Stack buffer, use \\\\[org-export-stack-view] to view export output +on current line, \\[org-export-stack-remove] to remove it from the stack and \\[org-export-stack-clear] to clear +stack completely. + +Removing entries in an Org Export Stack buffer doesn't affect +files or buffers, only the display. + +\\{org-export-stack-mode-map}" + (abbrev-mode 0) + (auto-fill-mode 0) + (setq buffer-read-only t + buffer-undo-list t + truncate-lines t + header-line-format + '(:eval + (format " %-12s | %6s | %s" "Back-End" "Age" "Source"))) + (org-add-hook 'post-command-hook 'org-export-stack-refresh nil t) + (set (make-local-variable 'revert-buffer-function) + 'org-export-stack-refresh)) + + + +;;; The Dispatcher +;; +;; `org-export-dispatch' is the standard interactive way to start an +;; export process. It uses `org-export--dispatch-ui' as a subroutine +;; for its interface, which, in turn, delegates response to key +;; pressed to `org-export--dispatch-action'. + +;;;###autoload +(defun org-export-dispatch (&optional arg) + "Export dispatcher for Org mode. + +It provides an access to common export related tasks in a buffer. +Its interface comes in two flavours: standard and expert. + +While both share the same set of bindings, only the former +displays the valid keys associations in a dedicated buffer. +Scrolling (resp. line-wise motion) in this buffer is done with +SPC and DEL (resp. C-n and C-p) keys. + +Set variable `org-export-dispatch-use-expert-ui' to switch to one +flavour or the other. + +When ARG is \\[universal-argument], repeat the last export action, with the same set +of options used back then, on the current buffer. + +When ARG is \\[universal-argument] \\[universal-argument], display the asynchronous export stack." + (interactive "P") + (let* ((input + (cond ((equal arg '(16)) '(stack)) + ((and arg org-export-dispatch-last-action)) + (t (save-window-excursion + (unwind-protect + (progn + ;; Remember where we are + (move-marker org-export-dispatch-last-position + (point) + (org-base-buffer (current-buffer))) + ;; Get and store an export command + (setq org-export-dispatch-last-action + (org-export--dispatch-ui + (list org-export-initial-scope + (and org-export-in-background 'async)) + nil + org-export-dispatch-use-expert-ui))) + (and (get-buffer "*Org Export Dispatcher*") + (kill-buffer "*Org Export Dispatcher*"))))))) + (action (car input)) + (optns (cdr input))) + (unless (memq 'subtree optns) + (move-marker org-export-dispatch-last-position nil)) + (case action + ;; First handle special hard-coded actions. + (template (org-export-insert-default-template nil optns)) + (stack (org-export-stack)) + (publish-current-file + (org-publish-current-file (memq 'force optns) (memq 'async optns))) + (publish-current-project + (org-publish-current-project (memq 'force optns) (memq 'async optns))) + (publish-choose-project + (org-publish (assoc (org-icompleting-read + "Publish project: " + org-publish-project-alist nil t) + org-publish-project-alist) + (memq 'force optns) + (memq 'async optns))) + (publish-all (org-publish-all (memq 'force optns) (memq 'async optns))) + (otherwise + (save-excursion + (when arg + ;; Repeating command, maybe move cursor to restore subtree + ;; context. + (if (eq (marker-buffer org-export-dispatch-last-position) + (org-base-buffer (current-buffer))) + (goto-char org-export-dispatch-last-position) + ;; We are in a different buffer, forget position. + (move-marker org-export-dispatch-last-position nil))) + (funcall action + ;; Return a symbol instead of a list to ease + ;; asynchronous export macro use. + (and (memq 'async optns) t) + (and (memq 'subtree optns) t) + (and (memq 'visible optns) t) + (and (memq 'body optns) t))))))) + +(defun org-export--dispatch-ui (options first-key expertp) + "Handle interface for `org-export-dispatch'. + +OPTIONS is a list containing current interactive options set for +export. It can contain any of the following symbols: +`body' toggles a body-only export +`subtree' restricts export to current subtree +`visible' restricts export to visible part of buffer. +`force' force publishing files. +`async' use asynchronous export process + +FIRST-KEY is the key pressed to select the first level menu. It +is nil when this menu hasn't been selected yet. + +EXPERTP, when non-nil, triggers expert UI. In that case, no help +buffer is provided, but indications about currently active +options are given in the prompt. Moreover, \[?] allows to switch +back to standard interface." + (let* ((fontify-key + (lambda (key &optional access-key) + ;; Fontify KEY string. Optional argument ACCESS-KEY, when + ;; non-nil is the required first-level key to activate + ;; KEY. When its value is t, activate KEY independently + ;; on the first key, if any. A nil value means KEY will + ;; only be activated at first level. + (if (or (eq access-key t) (eq access-key first-key)) + (org-propertize key 'face 'org-warning) + key))) + (fontify-value + (lambda (value) + ;; Fontify VALUE string. + (org-propertize value 'face 'font-lock-variable-name-face))) + ;; Prepare menu entries by extracting them from registered + ;; back-ends and sorting them by access key and by ordinal, + ;; if any. + (entries + (sort (sort (delq nil + (mapcar 'org-export-backend-menu + org-export--registered-backends)) + (lambda (a b) + (let ((key-a (nth 1 a)) + (key-b (nth 1 b))) + (cond ((and (numberp key-a) (numberp key-b)) + (< key-a key-b)) + ((numberp key-b) t))))) + 'car-less-than-car)) + ;; Compute a list of allowed keys based on the first key + ;; pressed, if any. Some keys + ;; (?^B, ?^V, ?^S, ?^F, ?^A, ?&, ?# and ?q) are always + ;; available. + (allowed-keys + (nconc (list 2 22 19 6 1) + (if (not first-key) (org-uniquify (mapcar 'car entries)) + (let (sub-menu) + (dolist (entry entries (sort (mapcar 'car sub-menu) '<)) + (when (eq (car entry) first-key) + (setq sub-menu (append (nth 2 entry) sub-menu)))))) + (cond ((eq first-key ?P) (list ?f ?p ?x ?a)) + ((not first-key) (list ?P))) + (list ?& ?#) + (when expertp (list ??)) + (list ?q))) + ;; Build the help menu for standard UI. + (help + (unless expertp + (concat + ;; Options are hard-coded. + (format "[%s] Body only: %s [%s] Visible only: %s +\[%s] Export scope: %s [%s] Force publishing: %s +\[%s] Async export: %s\n\n" + (funcall fontify-key "C-b" t) + (funcall fontify-value + (if (memq 'body options) "On " "Off")) + (funcall fontify-key "C-v" t) + (funcall fontify-value + (if (memq 'visible options) "On " "Off")) + (funcall fontify-key "C-s" t) + (funcall fontify-value + (if (memq 'subtree options) "Subtree" "Buffer ")) + (funcall fontify-key "C-f" t) + (funcall fontify-value + (if (memq 'force options) "On " "Off")) + (funcall fontify-key "C-a" t) + (funcall fontify-value + (if (memq 'async options) "On " "Off"))) + ;; Display registered back-end entries. When a key + ;; appears for the second time, do not create another + ;; entry, but append its sub-menu to existing menu. + (let (last-key) + (mapconcat + (lambda (entry) + (let ((top-key (car entry))) + (concat + (unless (eq top-key last-key) + (setq last-key top-key) + (format "\n[%s] %s\n" + (funcall fontify-key (char-to-string top-key)) + (nth 1 entry))) + (let ((sub-menu (nth 2 entry))) + (unless (functionp sub-menu) + ;; Split sub-menu into two columns. + (let ((index -1)) + (concat + (mapconcat + (lambda (sub-entry) + (incf index) + (format + (if (zerop (mod index 2)) " [%s] %-26s" + "[%s] %s\n") + (funcall fontify-key + (char-to-string (car sub-entry)) + top-key) + (nth 1 sub-entry))) + sub-menu "") + (when (zerop (mod index 2)) "\n")))))))) + entries "")) + ;; Publishing menu is hard-coded. + (format "\n[%s] Publish + [%s] Current file [%s] Current project + [%s] Choose project [%s] All projects\n\n\n" + (funcall fontify-key "P") + (funcall fontify-key "f" ?P) + (funcall fontify-key "p" ?P) + (funcall fontify-key "x" ?P) + (funcall fontify-key "a" ?P)) + (format "[%s] Export stack [%s] Insert template\n" + (funcall fontify-key "&" t) + (funcall fontify-key "#" t)) + (format "[%s] %s" + (funcall fontify-key "q" t) + (if first-key "Main menu" "Exit"))))) + ;; Build prompts for both standard and expert UI. + (standard-prompt (unless expertp "Export command: ")) + (expert-prompt + (when expertp + (format + "Export command (C-%s%s%s%s%s) [%s]: " + (if (memq 'body options) (funcall fontify-key "b" t) "b") + (if (memq 'visible options) (funcall fontify-key "v" t) "v") + (if (memq 'subtree options) (funcall fontify-key "s" t) "s") + (if (memq 'force options) (funcall fontify-key "f" t) "f") + (if (memq 'async options) (funcall fontify-key "a" t) "a") + (mapconcat (lambda (k) + ;; Strip control characters. + (unless (< k 27) (char-to-string k))) + allowed-keys ""))))) + ;; With expert UI, just read key with a fancy prompt. In standard + ;; UI, display an intrusive help buffer. + (if expertp + (org-export--dispatch-action + expert-prompt allowed-keys entries options first-key expertp) + ;; At first call, create frame layout in order to display menu. + (unless (get-buffer "*Org Export Dispatcher*") + (delete-other-windows) + (org-switch-to-buffer-other-window + (get-buffer-create "*Org Export Dispatcher*")) + (setq cursor-type nil + header-line-format "Use SPC, DEL, C-n or C-p to navigate.") + ;; Make sure that invisible cursor will not highlight square + ;; brackets. + (set-syntax-table (copy-syntax-table)) + (modify-syntax-entry ?\[ "w")) + ;; At this point, the buffer containing the menu exists and is + ;; visible in the current window. So, refresh it. + (with-current-buffer "*Org Export Dispatcher*" + ;; Refresh help. Maintain display continuity by re-visiting + ;; previous window position. + (let ((pos (window-start))) + (erase-buffer) + (insert help) + (set-window-start nil pos))) + (org-fit-window-to-buffer) + (org-export--dispatch-action + standard-prompt allowed-keys entries options first-key expertp)))) + +(defun org-export--dispatch-action + (prompt allowed-keys entries options first-key expertp) + "Read a character from command input and act accordingly. + +PROMPT is the displayed prompt, as a string. ALLOWED-KEYS is +a list of characters available at a given step in the process. +ENTRIES is a list of menu entries. OPTIONS, FIRST-KEY and +EXPERTP are the same as defined in `org-export--dispatch-ui', +which see. + +Toggle export options when required. Otherwise, return value is +a list with action as CAR and a list of interactive export +options as CDR." + (let (key) + ;; Scrolling: when in non-expert mode, act on motion keys (C-n, + ;; C-p, SPC, DEL). + (while (and (setq key (read-char-exclusive prompt)) + (not expertp) + (memq key '(14 16 ?\s ?\d))) + (case key + (14 (if (not (pos-visible-in-window-p (point-max))) + (ignore-errors (scroll-up 1)) + (message "End of buffer") + (sit-for 1))) + (16 (if (not (pos-visible-in-window-p (point-min))) + (ignore-errors (scroll-down 1)) + (message "Beginning of buffer") + (sit-for 1))) + (?\s (if (not (pos-visible-in-window-p (point-max))) + (scroll-up nil) + (message "End of buffer") + (sit-for 1))) + (?\d (if (not (pos-visible-in-window-p (point-min))) + (scroll-down nil) + (message "Beginning of buffer") + (sit-for 1))))) + (cond + ;; Ignore undefined associations. + ((not (memq key allowed-keys)) + (ding) + (unless expertp (message "Invalid key") (sit-for 1)) + (org-export--dispatch-ui options first-key expertp)) + ;; q key at first level aborts export. At second level, cancel + ;; first key instead. + ((eq key ?q) (if (not first-key) (error "Export aborted") + (org-export--dispatch-ui options nil expertp))) + ;; Help key: Switch back to standard interface if expert UI was + ;; active. + ((eq key ??) (org-export--dispatch-ui options first-key nil)) + ;; Send request for template insertion along with export scope. + ((eq key ?#) (cons 'template (memq 'subtree options))) + ;; Switch to asynchronous export stack. + ((eq key ?&) '(stack)) + ;; Toggle options: C-b (2) C-v (22) C-s (19) C-f (6) C-a (1). + ((memq key '(2 22 19 6 1)) + (org-export--dispatch-ui + (let ((option (case key (2 'body) (22 'visible) (19 'subtree) + (6 'force) (1 'async)))) + (if (memq option options) (remq option options) + (cons option options))) + first-key expertp)) + ;; Action selected: Send key and options back to + ;; `org-export-dispatch'. + ((or first-key (functionp (nth 2 (assq key entries)))) + (cons (cond + ((not first-key) (nth 2 (assq key entries))) + ;; Publishing actions are hard-coded. Send a special + ;; signal to `org-export-dispatch'. + ((eq first-key ?P) + (case key + (?f 'publish-current-file) + (?p 'publish-current-project) + (?x 'publish-choose-project) + (?a 'publish-all))) + ;; Return first action associated to FIRST-KEY + KEY + ;; path. Indeed, derived backends can share the same + ;; FIRST-KEY. + (t (catch 'found + (mapc (lambda (entry) + (let ((match (assq key (nth 2 entry)))) + (when match (throw 'found (nth 2 match))))) + (member (assq first-key entries) entries))))) + options)) + ;; Otherwise, enter sub-menu. + (t (org-export--dispatch-ui options key expertp))))) + + + +(provide 'ox) + +;; Local variables: +;; generated-autoload-file: "org-loaddefs.el" +;; End: + +;;; ox.el ends here