From a81e5de3a34d27cea43d49ffdfd9755f0eddb262 Mon Sep 17 00:00:00 2001 From: Bastien Guerry Date: Fri, 3 Oct 2014 10:13:51 +0200 Subject: [PATCH] Sync with Org 8.2.8. --- doc/misc/ChangeLog | 22 + doc/misc/org.texi | 382 ++++++++- etc/org/OrgOdtContentTemplate.xml | 12 + etc/org/OrgOdtStyles.xml | 76 +- lisp/org/ChangeLog | 595 +++++++++++++ lisp/org/ob-C.el | 2 + lisp/org/ob-R.el | 11 +- lisp/org/ob-core.el | 9 +- lisp/org/ob-exp.el | 1 + lisp/org/ob-haskell.el | 1 - lisp/org/ob-lilypond.el | 230 ++--- lisp/org/ob-python.el | 2 - lisp/org/ob-sh.el | 8 +- lisp/org/ob-tangle.el | 13 +- lisp/org/org-agenda.el | 402 ++++----- lisp/org/org-attach.el | 4 +- lisp/org/org-bbdb.el | 7 +- lisp/org/org-bibtex.el | 2 +- lisp/org/org-capture.el | 10 +- lisp/org/org-clock.el | 11 +- lisp/org/org-compat.el | 17 +- lisp/org/org-element.el | 247 +++--- lisp/org/org-entities.el | 6 +- lisp/org/org-habit.el | 13 +- lisp/org/org-list.el | 4 +- lisp/org/org-macs.el | 6 +- lisp/org/org-mobile.el | 2 +- lisp/org/org-mouse.el | 13 +- lisp/org/org-src.el | 37 +- lisp/org/org-table.el | 8 +- lisp/org/org-timer.el | 5 +- lisp/org/org-version.el | 4 +- lisp/org/org.el | 220 ++--- lisp/org/ox-ascii.el | 87 +- lisp/org/ox-beamer.el | 3 +- lisp/org/ox-html.el | 182 ++-- lisp/org/ox-icalendar.el | 35 +- lisp/org/ox-latex.el | 32 +- lisp/org/ox-md.el | 153 ++-- lisp/org/ox-odt.el | 54 +- lisp/org/ox-org.el | 50 +- lisp/org/ox-publish.el | 17 +- lisp/org/ox-texinfo.el | 1324 +++++++++++------------------ lisp/org/ox.el | 102 ++- 44 files changed, 2598 insertions(+), 1823 deletions(-) diff --git a/doc/misc/ChangeLog b/doc/misc/ChangeLog index 0ad35d3803a..6e0b164b72b 100644 --- a/doc/misc/ChangeLog +++ b/doc/misc/ChangeLog @@ -1,3 +1,25 @@ +2014-10-02 Bastien Guerry + + * org.texi (Key bindings and useful functions): Fix typo. Use the + correct function's name. + +2014-10-02 Michael Brand + + * org.texi (Formula syntax for Calc): Add `f-1' to TBLFM example + about `nan'. + +2014-10-02 Nicolas Goaziou + + * org.texi (Export settings): Be more explicit about how output + file name is built. + + * org.texi (Headings and sectioning structure): Document menus. + +2014-10-02 Nicolas Goaziou + + * org.texi (Include files, Publishing options): Remove reference + to inexistent variable. + 2014-07-25 Stephen Berman * todo-mode.texi (Marked Items): Correct omission of item deletion diff --git a/doc/misc/org.texi b/doc/misc/org.texi index 3800a41d239..d8a83fc18a4 100644 --- a/doc/misc/org.texi +++ b/doc/misc/org.texi @@ -2,7 +2,7 @@ @c %**start of header @setfilename ../../info/org @settitle The Org Manual -@set VERSION 8.2.6 +@set VERSION 8.2.8 @c Version and Contact Info @set MAINTAINERSITE @uref{http://orgmode.org,maintainers web page} @@ -584,8 +584,9 @@ Exporting * Markdown export:: Exporting to Markdown * OpenDocument Text export:: Exporting to OpenDocument Text * Org export:: Exporting to Org +* Texinfo export:: Exporting to Texinfo * iCalendar export:: Exporting to iCalendar -* Other built-in back-ends:: Exporting to @code{Texinfo} or a man page +* Other built-in back-ends:: Exporting to a man page * Export in foreign buffers:: Author tables and lists in Org syntax * Advanced configuration:: Fine-tuning the export output @@ -637,6 +638,16 @@ Advanced topics in ODT export * Customizing tables in ODT export:: How to define and use Table templates * Validating OpenDocument XML:: How to debug corrupt OpenDocument files +Texinfo export + +* Texinfo export commands:: How to invoke Texinfo export +* Document preamble:: File header, title and copyright page +* Headings and sectioning structure:: Building document structure +* Indices:: Creating indices +* Quoting Texinfo code:: Incorporating literal Texinfo code +* Texinfo specific attributes:: Controlling Texinfo output +* An example:: + Publishing * Configuration:: Defining projects @@ -2725,9 +2736,11 @@ Operations, , Logical Operations, calc, GNU Emacs Calc Manual}). For example @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 +@item if("$1" == "nan" || "$2" == "nan", string(""), $1 + $2); E f-1 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. +the Org table result field is set to empty. @samp{E} is required to not +convert empty fields to 0. @samp{f-1} is an optional Calc format string +similar to @samp{%.1f} but leaves empty results 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 @@ -4410,7 +4423,7 @@ To record a timestamp without a note for TODO keywords configured with @noindent @vindex org-log-done -you not only define global TODO keywords and fast access keys, but also +You not only define global TODO keywords and fast access keys, but also request that a time is recorded when the entry is set to DONE@footnote{It is possible that Org mode will record two timestamps when you are using both @code{org-log-done} and state change logging. @@ -9951,11 +9964,10 @@ include your @file{.emacs} file, you could use: @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 optional second and third parameter are the markup (i.e., @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. Contents of the included file will belong to the same structure (headline, item) containing the @code{INCLUDE} keyword. In particular, headlines within @@ -10364,8 +10376,9 @@ in the iCalendar format. * Markdown export:: Exporting to Markdown * OpenDocument Text export:: Exporting to OpenDocument Text * Org export:: Exporting to Org +* Texinfo export:: Exporting to Texinfo * iCalendar export:: Exporting to iCalendar -* Other built-in back-ends:: Exporting to @code{Texinfo} or a man page +* Other built-in back-ends:: Exporting to a man page * Export in foreign buffers:: Author tables and lists in Org syntax * Advanced configuration:: Fine-tuning the export output @end menu @@ -10690,16 +10703,12 @@ Toggle inclusion of TODO keywords into exported text Toggle inclusion of tables (@code{org-export-with-tables}). @end table -@cindex property, EXPORT_FILE_NAME When exporting only a subtree, each of the previous keywords@footnote{With the exception of @samp{SETUPFILE}.} can be overridden 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.}. +properties. @cindex #+BIND @vindex org-export-allow-bind-keywords @@ -10708,6 +10717,13 @@ 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. +@cindex property, EXPORT_FILE_NAME +The name of the output file to be generated is taken from the file associated +to the buffer, when possible, or asked to you otherwise. For subtree export, +you can also set @samp{EXPORT_FILE_NAME} property. In all cases, only the +base name of the file is retained, and a back-end specific extension is +added. + @node ASCII/Latin-1/UTF-8 export, Beamer export, Export settings, Exporting @section ASCII/Latin-1/UTF-8 export @cindex ASCII export @@ -12228,7 +12244,7 @@ height:width ratio, do the following @cindex #+ATTR_ODT You can control the manner in which an image is anchored by setting the @code{:anchor} property of it's @code{#+ATTR_ODT} line. You can specify one -of the the following three values for the @code{:anchor} property: +of the following three values for the @code{:anchor} property: @samp{"as-char"}, @samp{"paragraph"} and @samp{"page"}. To create an image that is anchored to a page, do the following: @@ -12834,7 +12850,324 @@ Export to a temporary buffer. Do not create a file. Export to an Org file, then open it. @end table -@node iCalendar export, Other built-in back-ends, Org export, Exporting +@node Texinfo export, iCalendar export, Org export, Exporting +@section Texinfo export +@cindex Texinfo export + +@samp{texinfo} export back-end generates Texinfo code and can compile it into +an Info file. + +@menu +* Texinfo export commands:: How to invoke Texinfo export +* Document preamble:: File header, title and copyright page +* Headings and sectioning structure:: Building document structure +* Indices:: Creating indices +* Quoting Texinfo code:: Incorporating literal Texinfo code +* Texinfo specific attributes:: Controlling Texinfo output +* An example:: +@end menu + +@node Texinfo export commands, Document preamble, Texinfo export, Texinfo export +@subsection Texinfo export commands + +@vindex org-texinfo-info-process +@table @kbd +@orgcmd{C-c C-e i t,org-texinfo-export-to-texinfo} +Export as a Texinfo file. For an Org file, @file{myfile.org}, the resulting +file will be @file{myfile.texi}. The file will be overwritten without +warning. +@orgcmd{C-c C-e i i,org-texinfo-export-to-info} +Export to Texinfo and then process to an Info file@footnote{By setting +@code{org-texinfo-info-process}, it is possible to generate other formats, +including DocBook.}. +@end table + +@node Document preamble, Headings and sectioning structure, Texinfo export commands, Texinfo export +@subsection Document preamble + +When processing a document, @samp{texinfo} back-end generates a minimal file +header along with a title page, a copyright page, and a menu. You control +the latter through the structure of the document (@pxref{Headings and +sectioning structure}). Various keywords allow to tweak the other parts. It +is also possible to give directions to install the document in the @samp{Top} +node. + +@subsubheading File header + +@cindex #+TEXINFO_FILENAME +Upon creating the header of a Texinfo file, the back-end guesses a name for +the Info file to be compiled. This may not be a sensible choice, e.g., if +you want to produce the final document in a different directory. Specify an +alternate path with @code{#+TEXINFO_FILENAME} keyword to override the default +destination. + +@vindex org-texinfo-coding-system +@vindex org-texinfo-classes +@cindex #+TEXINFO_HEADER +@cindex #+TEXINFO_CLASS +Along with the output file name, the header contains information about the +language (@pxref{Export settings}) and current encoding used@footnote{See +@code{org-texinfo-coding-system} for more information.}. Insert +a @code{#+TEXINFO_HEADER} keyword for each additional command needed, e.g., +@@code@{@@synindex@}. + +If you happen to regularly install the same set of commands, it may be easier +to define your own class in @code{org-texinfo-classes}, which see. Set +@code{#+TEXINFO_CLASS} keyword accordingly in your document to activate it. + +@subsubheading Title and copyright page + +@cindex #+TEXINFO_PRINTED_TITLE +@cindex #+SUBTITLE +The default template includes a title page for hard copy output. The title +and author displayed on this page are extracted from, respectively, +@code{#+TITLE} and @code{#+AUTHOR} keywords (@pxref{Export settings}). It is +also possible to print a different, more specific, title with +@code{#+TEXINFO_PRINTED_TITLE} keyword, and add subtitles with +@code{#+SUBTITLE} keyword. Both expect raw Texinfo code in their value. + +@cindex #+SUBAUTHOR +Likewise, information brought by @code{#+AUTHOR} may not be enough. You can +include other authors with several @code{#+SUBAUTHOR} keywords. Values are +also expected to be written in Texinfo code. + +@example +#+AUTHOR: Jane Smith +#+SUBAUTHOR: John Doe +#+TEXINFO_PRINTED_TITLE: This Long Title@@inlinefmt@{tex,@@*@} Is Broken in @@TeX@{@} +@end example + +@cindex property, COPYING +Copying material is defined in a dedicated headline with a non-nil +@code{:COPYING:} property. The contents are inserted within +a @code{@@copying} command at the beginning of the document whereas the +heading itself does not appear in the structure of the document. + +Copyright information is printed on the back of the title page. + +@example +* Copying + :PROPERTIES: + :COPYING: t + :END: + + This is a short example of a complete Texinfo file, version 1.0. + + Copyright \copy 2014 Free Software Foundation, Inc. +@end example + +@subsubheading The Top node + +@cindex #+TEXINFO_DIR_CATEGORY +@cindex #+TEXINFO_DIR_TITLE +@cindex #+TEXINFO_DIR_DESC +You may ultimately want to install your new Info file to your system. You +can write an appropriate entry in the top level directory specifying its +category and title with, respectively, @code{#+TEXINFO_DIR_CATEGORY} and +@code{#+TEXINFO_DIR_TITLE}. Optionally, you can add a short description +using @code{#+TEXINFO_DIR_DESC}. The following example would write an entry +similar to Org's in the @samp{Top} node. + +@example +#+TEXINFO_DIR_CATEGORY: Emacs +#+TEXINFO_DIR_TITLE: Org Mode: (org) +#+TEXINFO_DIR_DESC: Outline-based notes management and organizer +@end example + +@node Headings and sectioning structure, Indices, Document preamble, Texinfo export +@subsection Headings and sectioning structure + +@vindex org-texinfo-classes +@vindex org-texinfo-default-class +@cindex #+TEXINFO_CLASS +@samp{texinfo} uses a pre-defined scheme, or class, to convert headlines into +Texinfo structuring commands. For example, a top level headline appears as +@code{@@chapter} if it should be numbered or as @code{@@unnumbered} +otherwise. If you need to use a different set of commands, e.g., to start +with @code{@@part} instead of @code{@@chapter}, install a new class in +@code{org-texinfo-classes}, then activate it with @code{#+TEXINFO_CLASS} +keyword. Export process defaults to @code{org-texinfo-default-class} when +there is no such keyword in the document. + +If a headline's level has no associated structuring command, or is below +a certain threshold @pxref{Export settings}, that headline becomes a list in +Texinfo output. + +@cindex property, APPENDIX +As an exception, a headline with a non-nil @code{:APPENDIX:} property becomes +an appendix, independently on its level and the class used. + +@cindex property, DESCRIPTION +Each regular sectioning structure creates a menu entry, named after the +heading. You can provide a different, e.g., shorter, title in +@code{:ALT_TITLE:} property (@pxref{Table of contents}). Optionally, you can +specify a description for the item in @code{:DESCRIPTION:} property. E.g., + +@example +* Controlling Screen Display + :PROPERTIES: + :ALT_TITLE: Display + :DESCRIPTION: Controlling Screen Display + :END: +@end example + +@node Indices, Quoting Texinfo code, Headings and sectioning structure, Texinfo export +@subsection Indices + +@cindex #+CINDEX +@cindex #+FINDEX +@cindex #+KINDEX +@cindex #+PINDEX +@cindex #+TINDEX +@cindex #+VINDEX +Index entries are created using dedicated keywords. @samp{texinfo} back-end +provides one for each predefined type: @code{#+CINDEX}, @code{#+FINDEX}, +@code{#+KINDEX}, @code{#+PINDEX}, @code{#+TINDEX} and @code{#+VINDEX}. For +custom indices, you can write raw Texinfo code (@pxref{Quoting Texinfo +code}). + +@example +#+CINDEX: Defining indexing entries +@end example + +@cindex property, INDEX +To generate an index, you need to set the @code{:INDEX:} property of +a headline to an appropriate abbreviation (e.g., @samp{cp} or @samp{vr}). +The headline is then exported as an unnumbered chapter or section command and +the index is inserted after its contents. + +@example +* Concept Index + :PROPERTIES: + :INDEX: cp + :END: +@end example + +@node Quoting Texinfo code, Texinfo specific attributes, Indices, Texinfo export +@subsection Quoting Texinfo code + +It is possible to insert raw Texinfo code using any of the following +constructs + +@cindex #+TEXINFO +@cindex #+BEGIN_TEXINFO +@example +Richard @@@@texinfo:@@sc@{@@@@Stallman@@@@texinfo:@}@@@@ commence' GNU. + +#+TEXINFO: @@need800 +This paragraph is preceded by... + +#+BEGIN_TEXINFO +@@auindex Johnson, Mark +@@auindex Lakoff, George +#+END_TEXINFO +@end example + +@node Texinfo specific attributes, An example, Quoting Texinfo code, Texinfo export +@subsection Texinfo specific attributes + +@cindex #+ATTR_TEXINFO +@samp{texinfo} back-end understands several attributes in plain lists and +tables. They must be specified using an @code{#+ATTR_TEXINFO} keyword, +written just above the list or table. + +@subsubheading Plain lists + +In Texinfo output, description lists appear as two-column tables, using the +default command @code{@@table}. You can use @code{@@ftable} or +@code{@@vtable}@footnote{For more information, @inforef{Two-column +Tables,,texinfo}.} instead with @code{:table-type} attribute. + +@vindex org-texinfo-def-table-markup +In any case, these constructs require a highlighting command for entries in +the list. You can provide one with @code{:indic} attribute. If you do not, +it defaults to the value stored in @code{org-texinfo-def-table-markup}, which +see. + +@example +#+ATTR_TEXINFO: :indic @@asis +- foo :: This is the text for /foo/, with no highlighting. +@end example + +@subsubheading Tables + +When exporting a table, column widths are deduced from the longest cell in +each column. You can also define them explicitly as fractions of the line +length, using @code{:columns} attribute. + +@example +#+ATTR_TEXINFO: :columns .5 .5 +| a cell | another cell | +@end example + +@node An example, , Texinfo specific attributes, Texinfo export +@subsection An example + +Here is a thorough example, taken from @inforef{GNU Sample Texts,,texinfo}. + +@smallexample +#+MACRO: version 2.0 +#+MACRO: updated last updated 4 March 2014 + +#+OPTIONS: ':t toc:t author:t email:t +#+TITLE: GNU Sample @{@{@{version@}@}@} +#+AUTHOR: A.U. Thor +#+EMAIL: bug-sample@@gnu.org +#+LANGUAGE: en + +#+TEXINFO_FILENAME: sample.info +#+TEXINFO_HEADER: @@syncodeindex pg cp + +#+TEXINFO_DIR_CATEGORY: Texinfo documentation system +#+TEXINFO_DIR_TITLE: sample: (sample) +#+TEXINFO_DIR_DESC: Invoking sample + +#+TEXINFO_PRINTED_TITLE: GNU Sample +#+SUBTITLE: for version 2.0, last updated 4 March 2014 + +* Copying + :PROPERTIES: + :COPYING: t + :END: + + This manual is for GNU Sample (version @{@{@{version@}@}@}, + @{@{@{updated@}@}@}), which is an example in the Texinfo documentation. + + Copyright @@@@texinfo:@@copyright@{@}@@@@ 2013 Free Software Foundation, + Inc. + + #+BEGIN_QUOTE + Permission is granted to copy, distribute and/or modify this + document under the terms of the GNU Free Documentation License, + Version 1.3 or any later version published by the Free Software + Foundation; with no Invariant Sections, with no Front-Cover Texts, + and with no Back-Cover Texts. A copy of the license is included in + the section entitled "GNU Free Documentation License". + #+END_QUOTE + +* Invoking sample + + #+PINDEX: sample + #+CINDEX: invoking @@command@{sample@} + + This is a sample manual. There is no sample program to invoke, but + if there were, you could see its basic usage and command line + options here. + +* GNU Free Documentation License + :PROPERTIES: + :APPENDIX: t + :END: + + #+TEXINFO: @@include fdl.texi + +* Index + :PROPERTIES: + :INDEX: cp + :END: +@end smallexample + +@node iCalendar export, Other built-in back-ends, Texinfo export, Exporting @section iCalendar export @cindex iCalendar export @@ -12912,12 +13245,11 @@ On top of the aforementioned 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. @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}). +load them directly with e.g., @code{(require 'ox-man)}. 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. @@ -13334,7 +13666,6 @@ string of these options for details. @item @code{:headline-levels} @tab @code{org-export-headline-levels} @item @code{:language} @tab @code{org-export-default-language} @item @code{:preserve-breaks} @tab @code{org-export-preserve-breaks} -@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{:with-author} @tab @code{org-export-with-author} @@ -15473,10 +15804,10 @@ are active: @item @kbd{C-c C-c} @tab @code{org-babel-execute-src-block} @kindex C-c C-o @item @kbd{C-c C-o} @tab @code{org-babel-open-src-block-result} -@kindex C-up -@item @kbd{C-@key{up}} @tab @code{org-babel-load-in-session} +@kindex M-up +@item @kbd{M-@key{up}} @tab @code{org-babel-load-in-session} @kindex M-down -@item @kbd{M-@key{down}} @tab @code{org-babel-pop-to-session} +@item @kbd{M-@key{down}} @tab @code{org-babel-switch-to-session} @end multitable In an Org mode buffer, the following key bindings are active: @@ -18208,7 +18539,6 @@ org-customize @key{RET}} and then click yourself through the tree. @bye @c Local variables: -@c coding: utf-8 @c fill-column: 77 @c indent-tabs-mode: nil @c paragraph-start: "\\|^@[a-zA-Z]*[ \n]\\|^@x?org\\(key\\|cmd\\)\\|\f\\|[ ]*$" diff --git a/etc/org/OrgOdtContentTemplate.xml b/etc/org/OrgOdtContentTemplate.xml index 55e1b787066..d0c98a3e51c 100644 --- a/etc/org/OrgOdtContentTemplate.xml +++ b/etc/org/OrgOdtContentTemplate.xml @@ -46,7 +46,19 @@ + + + + + + + + + + + diff --git a/etc/org/OrgOdtStyles.xml b/etc/org/OrgOdtStyles.xml index 5dfcfa83890..f41d9840cbe 100644 --- a/etc/org/OrgOdtStyles.xml +++ b/etc/org/OrgOdtStyles.xml @@ -86,7 +86,11 @@ - + + + + + @@ -252,26 +256,44 @@ + + + + - + + + + + + + + - + - + + + + + + + + @@ -279,6 +301,9 @@ + + + @@ -325,9 +350,10 @@ - + + @@ -349,23 +375,41 @@ - - - - - - + + + - + - - + + + + + + + + + + + - + + + + + + + + + / + + / + + @@ -441,7 +485,7 @@ - + diff --git a/lisp/org/ChangeLog b/lisp/org/ChangeLog index a74388b7d71..0e2838e6469 100644 --- a/lisp/org/ChangeLog +++ b/lisp/org/ChangeLog @@ -1,3 +1,598 @@ +2014-10-02 Achim Gratz + + * ob-sh.el (org-babel-sh-initiate-session): After initiating a + session, initialize the marker `comint-last-output-start' since it + is going to be used by the ANSI color filter without further + checks in Emacs 23 and throws an error. + + * ob-lilypond.el, testing/lisp/test-ob-lilypond.el: Change prefix + from `ly-' to `org-babel-lilypond-' throughout. + + * org-footnote.el: Forward declare `org-element-context', + `org-element-property' and `org-element-type'. + + * org.el: Add forward declarations for a number of functions that + the compiler otherwise warns about as potentially undefined at + runtime. + + * ob-core.el: Add comment to forward declaration of + 'org-src-preserve-indentations'. + + * ob-exp.el: Require org-src to import + 'org-src-preserve-indentations'. + + * ob-haskell.el, lisp/ob-python.el: Remove superfluous forward + declaration of 'org-src-preserve-indentations', since it gets + imported by other requires. + + * ob-core.el (org-every): Forward declare 'org-every'. + + * ob-C.el: Require cl during compilation so that lexical-let is + known. + + * org-entities.el: Remove superfluous require of org-macs. + Forward declare 'org-toggle-pretty-entities' and + 'org-pretty-entities'. + + * ox.el (org-export-get-parent): Move definition of + 'org-export-get-parent' before first use. Leave comment at original + place of definition. + + * org.el (org-uniquify): Move definition of 'org-uniquify' before + first use. Leave comment at original place of definition. + + * ob-tangle.el (org-babel-tangle): When `file-name-directory' + returns nil, do not run make-directory. Remove superfluous when + clauses by using short-circuiting `and' instead. + +2014-10-02 Alex Kosorukoff (tiny change) + + * org-capture.el (org-capture-fill-template): Set `mark-active' to + nil. + +2014-10-02 Bastien Guerry + + * org-agenda.el (org-agenda-prepare): Reset preset filters when + using sticky agendas. + + * org-agenda.el (org-agenda-get-sexps): Don't add tags as text + properties. + + * org-capture.el (org-capture-fill-template): Take + `org-extend-today-until' into account when setting the format time + string. + + * org.el (org-paste-subtree): Fix match subexpression. + + * org.el (org-fix-ellipsis-at-bol): Delete. + (org-mode, org-show-context, org-isearch-end): Don't use + `org-fix-ellipsis-at-bol'. + + * org-agenda.el (org-agenda-filter-apply): Fix setting of + `org-agenda-filtered-by-category'. + + * org.el (org-fontify-meta-lines-and-blocks-1): Fix handling + of `org-hidden-keywords'. + + * org-agenda.el (org-cmp-ts): Fix agenda entry type checking. + + * org-agenda.el (org-entries-lessp): Fix inactive timestamp + comparison. + + * org-agenda.el (org-agenda-mode): Let `org-agenda-redo' DTRT + when agenda are sticky. + (org-agenda-tag-filter-while-redo): Delete. + (org-agenda-list, org-agenda-redo, org-agenda-filter-by-tag): + Remove unused code. + (org-agenda-clockreport-mode, org-agenda-set-mode-name): Don't + consider tag filters. + + * org.el (org-fix-ellipsis-at-bol) + (org-first-headline-recenter): Use `set-window-start' instead + of `recenter'. + + * org-agenda.el (org-recenter-heading): Delete. + + * org.el (org-insert-heading): With one universal prefix argument + or `org-insert-heading-respect-content' set to `t', always respect + the content, i.e. don't insert a list item and don't convert + normal lines into headings. Update docstring. + (org-insert-heading-respect-content): Remove unused arg. + (org-insert-todo-heading-respect-content): Don't use + `org-insert-todo-heading-respect-content', use the second argument + of `org-insert-todo-heading' instead. + + * org-mobile.el (org-mobile-edit): Use only one arg. + + * org.el (org-overview): Don't call `recenter'. + + * org-agenda.el (org-agenda-custom-commands-local-options): Fix + misquoted values. + + * org.el (org-property-re): Also match null properties by default. + (org-entry-delete): Also delete null properties. + (org-read-property-value): Allow the empty string as a new value. + (org-delete-property): Throw a message when there is not property + to delete. + + * org-agenda.el (org-agenda-insert-diary-make-new-entry): Fix + docstring. + + * org.el (org-re-property): New parameter `allow-null' to match + property with a null value. + (org-entry-put): Correctly update a property with a null + value. + + * ox-md.el (org-md-headline): When exporting with a HTML table of + contents, add HTML anchors to Markdown headlines. + + * org.el (org-insert-heading): Don't insert an item when called + with two universal prefix arguments. + + * org-agenda.el (org-agenda-finalize): Remove duplicate check for + 'org-hd-marker. + + * org-agenda.el (org-agenda-prepare-window): New parameter + `filter-alist' to set the filters correctly when + `org-agenda-persistent-filter' is on. + (org-agenda-prepare): Use the new parameter for + `org-agenda-prepare-window'. + + * org-compat.el (org-in-invisibility-spec-p): Tiny code cleanup. + (org-move-to-column): Only remove '(org-filtered) from + `buffer-invisibility-spec'. + + * org-agenda.el (org-agenda-mode): Add buffer invisibility specs. + (org-agenda-filter-hide-line, org-agenda-remove-filter): Set + the 'invisible text property to 'org-filtered. + (org-agenda-show-new-time): Add the default face to avoid the + foreground of the last character on the line to leak into the + timestamp notification. + + * org-agenda.el (org-get-time-of-day): Don't return time string + from within links. + + * org-timer.el (org-timer-value-string): Always return a positive + value. Add docstring. + + * org-capture.el (org-capture-steal-local-variables): Don't steal + `mark-active', which should be nil in the target buffer. + + * org-agenda.el (org-agenda-remove-filter): Use `save-excursion'. + + * org.el (org-move-subtree-down): Use `org-end-of-subtree' instead + of `outline-end-of-subtree'. + (outline-end-of-subtree): Remove advice. + + * org-mouse.el (org-mouse-move-tree, org-mouse-do-remotely): Use + `org-end-of-subtree' instead of `outline-end-of-subtree'. + + * org-agenda.el (org-cmp-ts): Argument `type' is not optional. + Don't quote it. + + * org-habit.el (org-habit-insert-consistency-graphs): Don't remove + filter overlays as we don't use overlays for filters anymore. + + * org-agenda.el (org-agenda-local-vars): Add + `org-agenda-top-headline-filter'. + (org-agenda-filter-by-category): Fix syntax. + (org-agenda-filter-show-all-top-filter): New function. + (org-agenda-filter-by-top-headline) + (org-agenda-filter-remove-all): Use the new function. + (org-agenda-filter-top-headline-apply): Use a dedicated symbol + `top-headline'. + + * org.el (org-entry-properties): Ensure the special property is + not commented out when matched. + + * org-agenda.el (org-agenda-write): Code cleanup. + (org-agenda-mark-filtered-text) + (org-agenda-unmark-filtered-text) + (org-agenda-fix-tags-filter-overlays-at): Delete. + (org-agenda-remove-marked-text): Use the `property' argument + instead of hard-coding 'org-filtered. + (org-agenda-filter-remove-all): Use `org-agenda-finalize'. + (org-agenda-filter-hide-line): Rewrite using text properties + instead of overlays. + (org-agenda-remove-filter): New function. + (org-agenda-filter-show-all-tag) + (org-agenda-filter-show-all-cat) + (org-agenda-filter-show-all-re): Rewrite using + `org-agenda-remove-filter'. + + * org-attach.el (org-attach-dir): When the property is "inherited" + from a variable outside of the file, do not use + `org-entry-property-inherited-from' to find the attachment + position, assume we need to go back to the current headline. + + * ob-R.el (org-babel-R-assign-elisp): Fix parsing of a + one-dimensional value. + + * org.el (org-insert-heading): Fix bug when trying to insert a + heading when point is before the first headline and not at the + beginning of a line. + + * org-table.el (org-table-eval-formula): Fix conversion of + inactive timestamps to active ones. + + * org.el (org-set-regexps-and-options): Allow + `org-complex-heading-regexp-format' to match [/] and [%] cookies + when they are both before and after the heading. + + * org-agenda.el (org-agenda-max-todos, org-agenda-max-tags) + (org-agenda-max-effort): Fix type strings. + + * org-capture.el (org-capture-fill-template): Deactivate region + while trying to align tags on the current headline. + + * org-agenda.el (org-agenda-finalize): Filter by top headline if + `org-agenda-top-headline-filter' is set. + +2014-10-02 Bernt Hansen + + * org-macs.el: Remove restriction when locating markers. + +2014-10-02 Dmitry Gorbik (tiny change) + + * org.el (org-fast-tag-selection): Fix window splitting. + +2014-10-02 Eric Schulte + + * ob-screen.el (org-babel-screen-test): Use unpredictable name for + temporary file. + + * ob-screen.el (org-babel-screen-session-write-temp-file): Use + unpredictable temp file name, fixes bug#17416. + +2014-10-02 Ian Kelling + + * ob-core.el (org-babel-insert-result): Test all list elements + against listp and (eq element 'hline) instead of checking just the + first. + +2014-10-02 Konstantin Kliakhandler (tiny change) + + * org-agenda.el (org-agenda-redo): Reapply the filters correctly. + +2014-10-02 Kyle Meyer (tiny change) + + * ox.el (org-export-show-temporary-export-buffer): Fix typo. + +2014-10-02 Matt Lundin + + * ox-publish.el (org-publish-find-title, org-publish-find-date): + Make sure to call org-export-get-environment in copy of buffer if + emacs is already visiting. Otherwise, #+bind variables meant for + export can be set in live buffers. + + * org.el (org-agenda-inhibit-startup): fix docstring to reflect + default value + + * ox-publish.el (org-publish-find-title, org-publish-find-date): + Fix unnecessary invocations of org-mode with org-inhibit-startup. + +2014-10-02 Nick Dokos + + * org-table.el (org-table-clean-before-export): The regexes match + spaces in addition to the special characters that might be used in + the first column as special marking characters. Remove the space + from the character class. + + * ox-ascii.el (org-ascii-superscript): Change _ to ^ in the + output. + +2014-10-02 Nick Dokos + + * org-table.el (org-table-show-reference): Call `set-window-start' + with the calculated values `min' and `max', not with + (point-min) and (point-max). + +2014-10-02 Nicolas Goaziou + + * ox-latex.el (org-latex-link): Improve test for unnumbered + headlines. + + * ox-ascii.el (org-ascii--fill-string): Allow filling even when + `org-export-preserve-breaks' is non-nil. + + * org.el (org-N-empty-lines-before-current): Make sure to delete + only empty lines, not trailing whitespaces. + + * ox-html.el (org-html-headline): Make sure even listified + headlines have proper anchors so internal links can refer to them. + Small refactoring. + + * org-src.el (org-edit-src-code): Fix regexp. + (org-edit-src-exit): Do not remove auto-save timer. This is + handled by the timer itself. + + * org.el (org-re-property): Fix regexp. Improve docstring. + + * org-element.el (org-element-property-drawer-parser) + (org-element-node-property-parser): Ignore lines that are not node + properties. + (org-element-node-property-interpreter): Allow nil properties. + + * org.el (org-re-property): Fix regexp to match properties with + empty values. + + * org-element.el (org-element-headline-interpreter): Take into + consideration `org-odd-levels-only' value. Small refactoring. + + * ox-texinfo.el (org-texinfo--get-node): Return a node or anchor + name. + (org-texinfo--sanitize-content): Fix regexp. + (org-texinfo-link): Fix various bugs in link export. + + * ox-beamer.el (org-beamer-link): + * ox-html.el (org-html-link): + * ox-latex.el (org-latex-link): + * ox-odt.el (org-odt-link): When radio link has no valid + target (e.g., this is a subtree export and the radio target is not + in the exported subtree), simply return contents. + + * org.el (org-called-with-limited-levels): Initialize variable. + + * org-agenda.el (org-agenda-write): Write headings in proper + order. + + * org-element.el (org-element-table-interpreter): Enhance + docstring. + + * ox-md.el (org-md-link): Allow custom link type export function. + + * ox-texinfo.el (org-texinfo-template): Fix language and encoding + case. + + * ox-md.el (org-md-separate-elements): Outside of lists, preserve + blank lines between paragraphs and plain lists. + + * org-element.el (org-element-normalize-contents): Fix indentation + removal when there is an empty line within a verse block. + + * ox-texinfo.el (org-texinfo--normalize-headlines): Properly add a + section to the contents. + + * ox-texinfo.el (org-texinfo--normalize-headlines): Do not set pre + blanks since the value is now hard-coded. + (org-texinfo-headline): Force one blank line before contents, when non + empty. Refactoring. + (org-texinfo-src-block): Refactor code. Comply to predicate naming. + + * ox-texinfo.el (org-texinfo--sanitize-node): Handle + " (not)allowed" case. + + * ox-texinfo.el (org-texinfo-headline): Remove wrong code + comments. + + * ox-texinfo.el (org-texinfo-headline): Remove `not-in-toc' + special case for tags. + + * ox-texinfo.el (org-texinfo-headline): Remove LaTeXism (optional + arguments within square brackets). + + * ox-texinfo.el (org-texinfo-info-process): Fix docstring. + (org-texinfo-compile): Do not check for impossible cases (e.g., if the + previous variable contains a function). + + * ox-texinfo.el (org-texinfo-max-toc-depth): Fix docstring. + + * ox-texinfo.el (org-texinfo--make-option-string, + org-texinfo--sanitize-headline, + org-texinfo--sanitize-headline-contents): Remove. + + * ox-texinfo.el (org-texinfo--sanitize-node): "@", "{" and "}" + characters are allowed in a node name. So are "(" and ")" unless + "(" starts the name and there is ")" somewhere in the name. Also + trim and collapse whitespace characters. Renamed from + `org-texinfo--sanitize-menu'. + (org-texinfo--get-node): Do not sanitize node names over zealously. + Ensure returned node names are unique. + (org-texinfo-headline): Only add @node command where it makes sense. + + * ox-texinfo.el (org-texinfo--sanitize-menu) + (org-texinfo--sanitize-content): Fix docstrings. + + * ox-texinfo.el (org-texinfo--normalize-headlines): Make sure a + blank line always follows nodes. + + * ox-texinfo.el (org-texinfo-make-menu): Change signature. Remove + some intermediate functions. Generate the full master menu when + asked. + (org-texinfo--build-menu): Use a simpler algorithm. + (org-texinfo--format-entries): Fix entries when both node and title + are different. + (org-texinfo--menu-entries): Renamed from `org-texinfo--generate-menu-list'. + (org-texinfo-headline): Move menu handling to next function. + (org-texinfo-section): Handle menu for current parent. + (org-texinfo--menu-headlines, org-texinfo--generate-detailed): Remove + functions. + (org-texinfo--normalize-headlines): New function. + + * ox-texinfo.el (org-texinfo-headline): Fix @appendix command. + + * ox-texinfo.el (org-texinfo-headline): Do not sanitize heading + text for sectioning command. + + * ox-texinfo.el (org-texinfo--generate-menu-list): ":COPYING: nil" + is expected to be equivalent to no COPYING property at all. + + * ox-texinfo.el (org-texinfo-item): Fix blank lines between items. + + * ox-texinfo.el (org-texinfo-plain-list): Fix format string. + Small refactoring. + + * ox-texinfo.el (texinfo): Provide new export property. + (org-texinfo-template): Use dedicated title for hard copy, when + available. + + * ox-texinfo.el (org-texinfo-headline): Always obey to a non-nil + :APPENDIX: property. Small refactoring. + + * ox-texinfo.el (org-texinfo-verse-block): Generate somewhat + meaningful Texinfo code instead of LaTeX. + + * ox-texinfo.el (org-texinfo-table): Remove reference to + "verbatim" attribute. Handle table.el tables. Tiny refactoring. + (org-texinfo-table--org-table, org-texinfo-table--table.el-table): + Remove functions. + (org-texinfo-table-column-widths): Indent code correctly. Ignore + special column, if any. Add a comment about the limitation on the + width computation. + (org-texinfo-table-row): Small refactoring. + + * ox-texinfo.el (texinfo): Do not provide a default value for + @setfilename value. + (org-texinfo-filename): Remove variable. + (org-texinfo-template): Correctly find value for @setfilename command. + If none is possible, do not provide the command at all. + + * ox.el (org-export-to-file): Provide output file name in + communication channel, through :output-file property. + + * ox-texinfo.el (org-texinfo-template): Do not hardcode "Manual" + in top node. + + * ox-texinfo.el (org-texinfo-classes): Change default value. + Update docstring. + (org-texinfo-template): Insert header string from current class after + "@settitle" command. Always provide "\input texinfo" at the beginning + of the output. + + * ox-texinfo.el (org-texinfo-template): Remove spurious blank + lines in output. Refactor code. + + * ox-texinfo.el (org-texinfo-template): Fix multi-line subtitles. + + * ox-texinfo.el (org-texinfo-template): Make sure table of + contents are allowed before inserting them. + + * ox-texinfo.el (org-texinfo-template): Check if copying data is + not nil before using it. + + * ox-texinfo.el (org-texinfo-template): Fix multi-line subauthors. + Correctly add email, when provided. Check if author info is + wanted first. + + * ox-texinfo.el (org-texinfo-node-description-column) + (org-texinfo-format-drawer-function): Fix docstrings. + + * ox-texinfo.el (texinfo): Make sure comments are ignored. + (org-texinfo-comment, org-texinfo-comment-block): Remove functions. + + * ox-texinfo.el (org-texinfo-template): Properly pad @direntry + description. + + * org-element.el (org-element-headline-parser): Add missing + `:post-blank' property in docstring. + + * ox-latex.el (org-latex-table-scientific-notation): Set + appropriate value. + (org-latex-listings-options): Fix docstring. + + * ox.el (org-export-raw-special-block-p): New function. + + * org-element.el (org-element-link-parser): Properly handle + multi-line links according to RFC 3986 when enclosed within square + brackets. + + * org-element.el (org-element-parse-secondary-string): Clone all + local variables from current buffer before parsing a secondary + string. Small refactoring. + (org-element-object-variables): Remove variable. + + * ox-odt.el (org-odt--format-paragraph): Change signature to + include info. + (org-odt-footnote-reference, org-odt-paragraph): Apply signature + change. + + * org-clock.el (org-clocktable-indent-string): Use "\emsp" instead + of "\__", which is not supported anymore since Org 8.0. + + * ox-odt.el (org-odt--paragraph-style): New function. + (org-odt--format-paragraph): Use new function to get proper style + to apply. + + * org-element.el (org-element--current-element): Fix regexp. + + * org-element.el (org-element--current-element): Fix regexp + matching latex environments. Discrepancy with regexp used in + `org-element-latex-environment-parser' introduced matching errors. + + * ox-ascii.el (org-ascii--table-cell-width): Correctly export + tables with width cookies. + + * org.el (org-insert-heading): Fix error when inserting a headline + before first headline, with point not at bol. Remove source block + check for consistency with behavior after first headline. Tiny + fix to docstring. + + * org.el (org-scan-tags): Fix typo in docstring. + + * ox.el (org-export--get-inbuffer-options): Return the empty + string instead of nil when TITLE keywords has no value. + (org-export--get-buffer-attributes): Do not set :title property + early. + (org-export--get-global-options): Do not ignore anymore nil values. + Small refactoring. + (org-export-as): Correctly set :title here. + + * org-list.el (org-list-repair): Fix typo in docstring. + + * ox-ascii.el (org-ascii--current-text-width): Tiny fix. + + * ox-org.el (org-org-section): Tiny refactoring. Use appropriate + property. + + * ox-org.el (org-org-headline): Ignore footnote sections. + (org-org-section): New function. + + * ox-beamer.el (org-beamer-select-environment): Ignore persistent + tags when displaying environments. + + * ox-ascii.el (org-ascii-indented-line-width): Update docstring. + (org-ascii-paragraph): Do not apply indentation to the very first line + of a section. + + * ox-latex.el (org-latex-inlinetask): Skip body if contents are + empty. + + * ox-html.el (org-html-standalone-image-p): Ensure paragraph + contains at least a link before return a non-nil value. Clarify + docstring. + + * ox.el (org-export-data): Always return a string, as specified + by the docstring. + + * ox-ascii.el (org-ascii--indent-string): Fix regexp to avoid + stack overflow in regexp matcher on very long lines. + + * org-element.el (org-element-timestamp-parser): Fix docstring. + + * ox-icalendar.el (org-icalendar-include-sexps, + org-icalendar-blocked-headline-p): Fix docstrings. + (org-icalendar-clear-blank-lines): Fix docstring and regexp. + + * ox-icalendar.el (org-icalendar-entry): Use + `org-icalendar-with-timestamps'. + +2014-10-02 Nicolas Richard + + * org.el (org-cycle-internal-local): Don't show a trailing + character when cycling a subtree that ends with a non-newline + character at the end of the buffer or the narrowed region. + +2014-10-02 Sebastien Vauban + + * ox-ascii.el (org-ascii--box-string): Choose more universal + Unicode characters for boxquote corners. + +2014-10-02 marcowahlsoft@gmail.com (tiny change) + + * org-agenda.el (org-agenda-bulk-mark) + (org-agenda-bulk-mark-regexp, org-agenda-bulk-toggle-all): Fix + org-agenda-bulk-mark-all when time-grid is shown. + 2014-05-12 Eric Schulte * ob-screen.el (org-babel-screen-session-write-temp-file) diff --git a/lisp/org/ob-C.el b/lisp/org/ob-C.el index c460be326f8..2fcec790c43 100644 --- a/lisp/org/ob-C.el +++ b/lisp/org/ob-C.el @@ -30,6 +30,8 @@ ;; - not much in the way of error feedback ;;; Code: +(eval-when-compile + (require 'cl)) (require 'ob) (require 'cc-mode) diff --git a/lisp/org/ob-R.el b/lisp/org/ob-R.el index 93d6fe284f5..b97fd912eae 100644 --- a/lisp/org/ob-R.el +++ b/lisp/org/ob-R.el @@ -173,12 +173,11 @@ This function is called by `org-babel-execute-src-block'." (defun org-babel-R-assign-elisp (name value colnames-p rownames-p) "Construct R code assigning the elisp VALUE to a variable named NAME." (if (listp value) - (let ((max (apply #'max (mapcar #'length (org-remove-if-not - #'sequencep value)))) - (min (apply #'min (mapcar #'length (org-remove-if-not - #'sequencep value)))) - (transition-file (org-babel-temp-file "R-import-"))) - ;; ensure VALUE has an orgtbl structure (depth of at least 2) + (let* ((lengths (mapcar 'length (org-remove-if-not 'sequencep value))) + (max (if lengths (apply 'max lengths) 0)) + (min (if lengths (apply 'min lengths) 0)) + (transition-file (org-babel-temp-file "R-import-"))) + ;; Ensure VALUE has an orgtbl structure (depth of at least 2). (unless (listp (car value)) (setq value (list value))) (with-temp-file transition-file (insert diff --git a/lisp/org/ob-core.el b/lisp/org/ob-core.el index e8943c66561..eef408fd44f 100644 --- a/lisp/org/ob-core.el +++ b/lisp/org/ob-core.el @@ -38,6 +38,7 @@ (defvar org-src-lang-modes) (defvar org-babel-library-of-babel) (declare-function show-all "outline" ()) +(declare-function org-every "org" (pred seq)) (declare-function org-reduce "org" (CL-FUNC CL-SEQ &rest CL-KEYS)) (declare-function org-mark-ring-push "org" (&optional pos buffer)) (declare-function tramp-compat-make-temp-file "tramp-compat" @@ -1348,7 +1349,7 @@ specified in the properties of the current outline entry." (org-entry-get org-babel-current-src-block-location (concat "header-args:" lang) 'inherit)))))) -(defvar org-src-preserve-indentation) +(defvar org-src-preserve-indentation) ;; declare defcustom from org-src (defun org-babel-parse-src-block-match () "Parse the results from a match of the `org-babel-src-block-regexp'." (let* ((block-indentation (length (match-string 1))) @@ -2100,9 +2101,9 @@ code ---- the results are extracted in the syntax of the source ((funcall proper-list-p result) (goto-char beg) (insert (concat (orgtbl-to-orgtbl - (if (or (eq 'hline (car result)) - (and (listp (car result)) - (listp (cdr (car result))))) + (if (org-every + (lambda (el) (or (listp el) (eq el 'hline))) + result) result (list result)) '(:fmt (lambda (cell) (format "%s" cell)))) "\n")) (goto-char beg) (when (org-at-table-p) (org-table-align))) diff --git a/lisp/org/ob-exp.el b/lisp/org/ob-exp.el index 6d65496dbd4..761c9f17ad0 100644 --- a/lisp/org/ob-exp.el +++ b/lisp/org/ob-exp.el @@ -24,6 +24,7 @@ ;;; Code: (require 'ob-core) +(require 'org-src) (eval-when-compile (require 'cl)) diff --git a/lisp/org/ob-haskell.el b/lisp/org/ob-haskell.el index 22240addd8a..00066702a51 100644 --- a/lisp/org/ob-haskell.el +++ b/lisp/org/ob-haskell.el @@ -147,7 +147,6 @@ specifying a variable of the same value." (concat "[" (mapconcat #'org-babel-haskell-var-to-haskell var ", ") "]") (format "%S" var))) -(defvar org-src-preserve-indentation) (defvar org-export-copy-to-kill-ring) (declare-function org-export-to-file "ox" (backend file diff --git a/lisp/org/ob-lilypond.el b/lisp/org/ob-lilypond.el index 9b575464ea9..00a951d32d1 100644 --- a/lisp/org/ob-lilypond.el +++ b/lisp/org/ob-lilypond.el @@ -39,62 +39,62 @@ (defvar org-babel-default-header-args:lilypond '() "Default header arguments for lilypond code blocks. NOTE: The arguments are determined at lilypond compile time. -See (ly-set-header-args)") +See (org-babel-lilypond-set-header-args)") -(defvar ly-compile-post-tangle t +(defvar org-babel-lilypond-compile-post-tangle t "Following the org-babel-tangle (C-c C-v t) command, -ly-compile-post-tangle determines whether ob-lilypond should +org-babel-lilypond-compile-post-tangle determines whether ob-lilypond should automatically attempt to compile the resultant tangled file. If the value is nil, no automated compilation takes place. Default value is t") -(defvar ly-display-pdf-post-tangle t +(defvar org-babel-lilypond-display-pdf-post-tangle t "Following a successful LilyPond compilation -ly-display-pdf-post-tangle determines whether to automate the +org-babel-lilypond-display-pdf-post-tangle determines whether to automate the drawing / redrawing of the resultant pdf. If the value is nil, the pdf is not automatically redrawn. Default value is t") -(defvar ly-play-midi-post-tangle t +(defvar org-babel-lilypond-play-midi-post-tangle t "Following a successful LilyPond compilation -ly-play-midi-post-tangle determines whether to automate the +org-babel-lilypond-play-midi-post-tangle determines whether to automate the playing of the resultant midi file. If the value is nil, the midi file is not automatically played. Default value is t") -(defvar ly-OSX-ly-path +(defvar org-babel-lilypond-OSX-ly-path "/Applications/lilypond.app/Contents/Resources/bin/lilypond") -(defvar ly-OSX-pdf-path "open") -(defvar ly-OSX-midi-path "open") +(defvar org-babel-lilypond-OSX-pdf-path "open") +(defvar org-babel-lilypond-OSX-midi-path "open") -(defvar ly-nix-ly-path "/usr/bin/lilypond") -(defvar ly-nix-pdf-path "evince") -(defvar ly-nix-midi-path "timidity") +(defvar org-babel-lilypond-nix-ly-path "/usr/bin/lilypond") +(defvar org-babel-lilypond-nix-pdf-path "evince") +(defvar org-babel-lilypond-nix-midi-path "timidity") -(defvar ly-w32-ly-path "lilypond") -(defvar ly-w32-pdf-path "") -(defvar ly-w32-midi-path "") +(defvar org-babel-lilypond-w32-ly-path "lilypond") +(defvar org-babel-lilypond-w32-pdf-path "") +(defvar org-babel-lilypond-w32-midi-path "") -(defvar ly-gen-png nil +(defvar org-babel-lilypond-gen-png nil "Image generation (png) can be turned on by default by setting -LY-GEN-PNG to t") +ORG-BABEL-LILYPOND-GEN-PNG to t") -(defvar ly-gen-svg nil +(defvar org-babel-lilypond-gen-svg nil "Image generation (SVG) can be turned on by default by setting -LY-GEN-SVG to t") +ORG-BABEL-LILYPOND-GEN-SVG to t") -(defvar ly-gen-html nil +(defvar org-babel-lilypond-gen-html nil "HTML generation can be turned on by default by setting -LY-GEN-HTML to t") +ORG-BABEL-LILYPOND-GEN-HTML to t") -(defvar ly-gen-pdf nil +(defvar org-babel-lilypond-gen-pdf nil "PDF generation can be turned on by default by setting -LY-GEN-PDF to t") +ORG-BABEL-LILYPOND-GEN-PDF to t") -(defvar ly-use-eps nil +(defvar org-babel-lilypond-use-eps nil "You can force the compiler to use the EPS backend by setting -LY-USE-EPS to t") +ORG-BABEL-LILYPOND-USE-EPS to t") -(defvar ly-arrange-mode nil - "Arrange mode is turned on by setting LY-ARRANGE-MODE +(defvar org-babel-lilypond-arrange-mode nil + "Arrange mode is turned on by setting ORG-BABEL-LILYPOND-ARRANGE-MODE to t. In Arrange mode the following settings are altered from default... :tangle yes, :noweb yes @@ -123,20 +123,20 @@ Depending on whether we are in arrange mode either: 1. Attempt to execute lilypond block according to header settings (This is the default basic mode) 2. Tangle all lilypond blocks and process the result (arrange mode)" - (ly-set-header-args ly-arrange-mode) - (if ly-arrange-mode - (ly-tangle) - (ly-process-basic body params))) + (org-babel-lilypond-set-header-args org-babel-lilypond-arrange-mode) + (if org-babel-lilypond-arrange-mode + (org-babel-lilypond-tangle) + (org-babel-lilypond-process-basic body params))) -(defun ly-tangle () +(defun org-babel-lilypond-tangle () "ob-lilypond specific tangle, attempts to invoke =ly-execute-tangled-ly= if tangle is successful. Also passes specific arguments to =org-babel-tangle=" (interactive) (if (org-babel-tangle nil "yes" "lilypond") - (ly-execute-tangled-ly) nil)) + (org-babel-lilypond-execute-tangled-ly) nil)) -(defun ly-process-basic (body params) +(defun org-babel-lilypond-process-basic (body params) "Execute a lilypond block in basic mode." (let* ((result-params (cdr (assoc :result-params params))) (out-file (cdr (assoc :file params))) @@ -148,7 +148,7 @@ specific arguments to =org-babel-tangle=" (insert (org-babel-expand-body:generic body params))) (org-babel-eval (concat - (ly-determine-ly-path) + (org-babel-lilypond-determine-ly-path) " -dbackend=eps " "-dno-gs-load-fonts " "-dinclude-eps-fonts " @@ -167,45 +167,45 @@ specific arguments to =org-babel-tangle=" "Return an error because LilyPond exporter does not support sessions." (error "Sorry, LilyPond does not currently support sessions!")) -(defun ly-execute-tangled-ly () +(defun org-babel-lilypond-execute-tangled-ly () "Compile result of block tangle with lilypond. If error in compilation, attempt to mark the error in lilypond org file" - (when ly-compile-post-tangle - (let ((ly-tangled-file (ly-switch-extension + (when org-babel-lilypond-compile-post-tangle + (let ((org-babel-lilypond-tangled-file (org-babel-lilypond-switch-extension (buffer-file-name) ".lilypond")) - (ly-temp-file (ly-switch-extension + (org-babel-lilypond-temp-file (org-babel-lilypond-switch-extension (buffer-file-name) ".ly"))) - (if (file-exists-p ly-tangled-file) + (if (file-exists-p org-babel-lilypond-tangled-file) (progn - (when (file-exists-p ly-temp-file) - (delete-file ly-temp-file)) - (rename-file ly-tangled-file - ly-temp-file)) + (when (file-exists-p org-babel-lilypond-temp-file) + (delete-file org-babel-lilypond-temp-file)) + (rename-file org-babel-lilypond-tangled-file + org-babel-lilypond-temp-file)) (error "Error: Tangle Failed!") t) (switch-to-buffer-other-window "*lilypond*") (erase-buffer) - (ly-compile-lilyfile ly-temp-file) + (org-babel-lilypond-compile-lilyfile org-babel-lilypond-temp-file) (goto-char (point-min)) - (if (not (ly-check-for-compile-error ly-temp-file)) + (if (not (org-babel-lilypond-check-for-compile-error org-babel-lilypond-temp-file)) (progn (other-window -1) - (ly-attempt-to-open-pdf ly-temp-file) - (ly-attempt-to-play-midi ly-temp-file)) + (org-babel-lilypond-attempt-to-open-pdf org-babel-lilypond-temp-file) + (org-babel-lilypond-attempt-to-play-midi org-babel-lilypond-temp-file)) (error "Error in Compilation!")))) nil) -(defun ly-compile-lilyfile (file-name &optional test) +(defun org-babel-lilypond-compile-lilyfile (file-name &optional test) "Compile lilypond file and check for compile errors FILE-NAME is full path to lilypond (.ly) file" (message "Compiling LilyPond...") - (let ((arg-1 (ly-determine-ly-path)) ;program + (let ((arg-1 (org-babel-lilypond-determine-ly-path)) ;program (arg-2 nil) ;infile (arg-3 "*lilypond*") ;buffer (arg-4 t) ;display - (arg-5 (if ly-gen-png "--png" "")) ;&rest... - (arg-6 (if ly-gen-html "--html" "")) - (arg-7 (if ly-gen-pdf "--pdf" "")) - (arg-8 (if ly-use-eps "-dbackend=eps" "")) - (arg-9 (if ly-gen-svg "-dbackend=svg" "")) + (arg-5 (if org-babel-lilypond-gen-png "--png" "")) ;&rest... + (arg-6 (if org-babel-lilypond-gen-html "--html" "")) + (arg-7 (if org-babel-lilypond-gen-pdf "--pdf" "")) + (arg-8 (if org-babel-lilypond-use-eps "-dbackend=eps" "")) + (arg-9 (if org-babel-lilypond-gen-svg "-dbackend=svg" "")) (arg-10 (concat "--output=" (file-name-sans-extension file-name))) (arg-11 file-name)) (if test @@ -215,7 +215,7 @@ FILE-NAME is full path to lilypond (.ly) file" arg-1 arg-2 arg-3 arg-4 arg-5 arg-6 arg-7 arg-8 arg-9 arg-10 arg-11)))) -(defun ly-check-for-compile-error (file-name &optional test) +(defun org-babel-lilypond-check-for-compile-error (file-name &optional test) "Check for compile error. This is performed by parsing the *lilypond* buffer containing the output message from the compilation. @@ -226,24 +226,24 @@ nil as file-name since it is unused in this context" (if (not test) (if (not is-error) nil - (ly-process-compile-error file-name)) + (org-babel-lilypond-process-compile-error file-name)) is-error))) -(defun ly-process-compile-error (file-name) +(defun org-babel-lilypond-process-compile-error (file-name) "Process the compilation error that has occurred. FILE-NAME is full path to lilypond file" - (let ((line-num (ly-parse-line-num))) - (let ((error-lines (ly-parse-error-line file-name line-num))) - (ly-mark-error-line file-name error-lines) + (let ((line-num (org-babel-lilypond-parse-line-num))) + (let ((error-lines (org-babel-lilypond-parse-error-line file-name line-num))) + (org-babel-lilypond-mark-error-line file-name error-lines) (error "Error: Compilation Failed!")))) -(defun ly-mark-error-line (file-name line) +(defun org-babel-lilypond-mark-error-line (file-name line) "Mark the erroneous lines in the lilypond org buffer. FILE-NAME is full path to lilypond file. LINE is the erroneous line" (switch-to-buffer-other-window (concat (file-name-nondirectory - (ly-switch-extension file-name ".org")))) + (org-babel-lilypond-switch-extension file-name ".org")))) (let ((temp (point))) (goto-char (point-min)) (setq case-fold-search nil) @@ -254,7 +254,7 @@ LINE is the erroneous line" (goto-char (- (point) (length line)))) (goto-char temp)))) -(defun ly-parse-line-num (&optional buffer) +(defun org-babel-lilypond-parse-line-num (&optional buffer) "Extract error line number." (when buffer (set-buffer buffer)) @@ -276,12 +276,12 @@ LINE is the erroneous line" nil))) nil))) -(defun ly-parse-error-line (file-name lineNo) +(defun org-babel-lilypond-parse-error-line (file-name lineNo) "Extract the erroneous line from the tangled .ly file FILE-NAME is full path to lilypond file. LINENO is the number of the erroneous line" (with-temp-buffer - (insert-file-contents (ly-switch-extension file-name ".ly") + (insert-file-contents (org-babel-lilypond-switch-extension file-name ".ly") nil nil nil t) (if (> lineNo 0) (progn @@ -290,128 +290,128 @@ LINENO is the number of the erroneous line" (buffer-substring (point) (point-at-eol))) nil))) -(defun ly-attempt-to-open-pdf (file-name &optional test) +(defun org-babel-lilypond-attempt-to-open-pdf (file-name &optional test) "Attempt to display the generated pdf file FILE-NAME is full path to lilypond file If TEST is non-nil, the shell command is returned and is not run" - (when ly-display-pdf-post-tangle - (let ((pdf-file (ly-switch-extension file-name ".pdf"))) + (when org-babel-lilypond-display-pdf-post-tangle + (let ((pdf-file (org-babel-lilypond-switch-extension file-name ".pdf"))) (if (file-exists-p pdf-file) (let ((cmd-string - (concat (ly-determine-pdf-path) " " pdf-file))) + (concat (org-babel-lilypond-determine-pdf-path) " " pdf-file))) (if test cmd-string (start-process "\"Audition pdf\"" "*lilypond*" - (ly-determine-pdf-path) + (org-babel-lilypond-determine-pdf-path) pdf-file))) (message "No pdf file generated so can't display!"))))) -(defun ly-attempt-to-play-midi (file-name &optional test) +(defun org-babel-lilypond-attempt-to-play-midi (file-name &optional test) "Attempt to play the generated MIDI file FILE-NAME is full path to lilypond file If TEST is non-nil, the shell command is returned and is not run" - (when ly-play-midi-post-tangle - (let ((midi-file (ly-switch-extension file-name ".midi"))) + (when org-babel-lilypond-play-midi-post-tangle + (let ((midi-file (org-babel-lilypond-switch-extension file-name ".midi"))) (if (file-exists-p midi-file) (let ((cmd-string - (concat (ly-determine-midi-path) " " midi-file))) + (concat (org-babel-lilypond-determine-midi-path) " " midi-file))) (if test cmd-string (start-process "\"Audition midi\"" "*lilypond*" - (ly-determine-midi-path) + (org-babel-lilypond-determine-midi-path) midi-file))) (message "No midi file generated so can't play!"))))) -(defun ly-determine-ly-path (&optional test) +(defun org-babel-lilypond-determine-ly-path (&optional test) "Return correct path to ly binary depending on OS If TEST is non-nil, it contains a simulation of the OS for test purposes" (let ((sys-type (or test system-type))) (cond ((string= sys-type "darwin") - ly-OSX-ly-path) + org-babel-lilypond-OSX-ly-path) ((string= sys-type "windows-nt") - ly-w32-ly-path) - (t ly-nix-ly-path)))) + org-babel-lilypond-w32-ly-path) + (t org-babel-lilypond-nix-ly-path)))) -(defun ly-determine-pdf-path (&optional test) +(defun org-babel-lilypond-determine-pdf-path (&optional test) "Return correct path to pdf viewer depending on OS If TEST is non-nil, it contains a simulation of the OS for test purposes" (let ((sys-type (or test system-type))) (cond ((string= sys-type "darwin") - ly-OSX-pdf-path) + org-babel-lilypond-OSX-pdf-path) ((string= sys-type "windows-nt") - ly-w32-pdf-path) - (t ly-nix-pdf-path)))) + org-babel-lilypond-w32-pdf-path) + (t org-babel-lilypond-nix-pdf-path)))) -(defun ly-determine-midi-path (&optional test) +(defun org-babel-lilypond-determine-midi-path (&optional test) "Return correct path to midi player depending on OS If TEST is non-nil, it contains a simulation of the OS for test purposes" (let ((sys-type (or test test system-type))) (cond ((string= sys-type "darwin") - ly-OSX-midi-path) + org-babel-lilypond-OSX-midi-path) ((string= sys-type "windows-nt") - ly-w32-midi-path) - (t ly-nix-midi-path)))) + org-babel-lilypond-w32-midi-path) + (t org-babel-lilypond-nix-midi-path)))) -(defun ly-toggle-midi-play () +(defun org-babel-lilypond-toggle-midi-play () "Toggle whether midi will be played following a successful compilation." (interactive) - (setq ly-play-midi-post-tangle - (not ly-play-midi-post-tangle)) + (setq org-babel-lilypond-play-midi-post-tangle + (not org-babel-lilypond-play-midi-post-tangle)) (message (concat "Post-Tangle MIDI play has been " - (if ly-play-midi-post-tangle + (if org-babel-lilypond-play-midi-post-tangle "ENABLED." "DISABLED.")))) -(defun ly-toggle-pdf-display () +(defun org-babel-lilypond-toggle-pdf-display () "Toggle whether pdf will be displayed following a successful compilation." (interactive) - (setq ly-display-pdf-post-tangle - (not ly-display-pdf-post-tangle)) + (setq org-babel-lilypond-display-pdf-post-tangle + (not org-babel-lilypond-display-pdf-post-tangle)) (message (concat "Post-Tangle PDF display has been " - (if ly-display-pdf-post-tangle + (if org-babel-lilypond-display-pdf-post-tangle "ENABLED." "DISABLED.")))) -(defun ly-toggle-png-generation () +(defun org-babel-lilypond-toggle-png-generation () "Toggle whether png image will be generated by compilation." (interactive) - (setq ly-gen-png (not ly-gen-png)) + (setq org-babel-lilypond-gen-png (not org-babel-lilypond-gen-png)) (message (concat "PNG image generation has been " - (if ly-gen-png "ENABLED." "DISABLED.")))) + (if org-babel-lilypond-gen-png "ENABLED." "DISABLED.")))) -(defun ly-toggle-html-generation () +(defun org-babel-lilypond-toggle-html-generation () "Toggle whether html will be generated by compilation." (interactive) - (setq ly-gen-html (not ly-gen-html)) + (setq org-babel-lilypond-gen-html (not org-babel-lilypond-gen-html)) (message (concat "HTML generation has been " - (if ly-gen-html "ENABLED." "DISABLED.")))) + (if org-babel-lilypond-gen-html "ENABLED." "DISABLED.")))) -(defun ly-toggle-pdf-generation () +(defun org-babel-lilypond-toggle-pdf-generation () "Toggle whether pdf will be generated by compilation." (interactive) - (setq ly-gen-pdf (not ly-gen-pdf)) + (setq org-babel-lilypond-gen-pdf (not org-babel-lilypond-gen-pdf)) (message (concat "PDF generation has been " - (if ly-gen-pdf "ENABLED." "DISABLED.")))) + (if org-babel-lilypond-gen-pdf "ENABLED." "DISABLED.")))) -(defun ly-toggle-arrange-mode () +(defun org-babel-lilypond-toggle-arrange-mode () "Toggle whether in Arrange mode or Basic mode." (interactive) - (setq ly-arrange-mode - (not ly-arrange-mode)) + (setq org-babel-lilypond-arrange-mode + (not org-babel-lilypond-arrange-mode)) (message (concat "Arrange mode has been " - (if ly-arrange-mode "ENABLED." "DISABLED.")))) + (if org-babel-lilypond-arrange-mode "ENABLED." "DISABLED.")))) -(defun ly-switch-extension (file-name ext) +(defun org-babel-lilypond-switch-extension (file-name ext) "Utility command to swap current FILE-NAME extension with EXT" (concat (file-name-sans-extension file-name) ext)) -(defun ly-get-header-args (mode) +(defun org-babel-lilypond-get-header-args (mode) "Default arguments to use when evaluating a lilypond source block. These depend upon whether we are in arrange mode i.e. ARRANGE-MODE is t" @@ -425,11 +425,11 @@ mode i.e. ARRANGE-MODE is t" '((:results . "file") (:exports . "results"))))) -(defun ly-set-header-args (mode) +(defun org-babel-lilypond-set-header-args (mode) "Set org-babel-default-header-args:lilypond -dependent on LY-ARRANGE-MODE" +dependent on ORG-BABEL-LILYPOND-ARRANGE-MODE" (setq org-babel-default-header-args:lilypond - (ly-get-header-args mode))) + (org-babel-lilypond-get-header-args mode))) (provide 'ob-lilypond) diff --git a/lisp/org/ob-python.el b/lisp/org/ob-python.el index baa5764ac42..7cee1046690 100644 --- a/lisp/org/ob-python.el +++ b/lisp/org/ob-python.el @@ -56,8 +56,6 @@ This will typically be either 'python or 'python-mode." :package-version '(Org . "8.0") :type 'symbol) -(defvar org-src-preserve-indentation) - (defcustom org-babel-python-hline-to "None" "Replace hlines in incoming tables with this when translating to python." :group 'org-babel diff --git a/lisp/org/ob-sh.el b/lisp/org/ob-sh.el index 96f275bc87a..856c7a01c88 100644 --- a/lisp/org/ob-sh.el +++ b/lisp/org/ob-sh.el @@ -123,7 +123,13 @@ Emacs-lisp table, otherwise return the results as a string." (when (and session (not (string= session "none"))) (save-window-excursion (or (org-babel-comint-buffer-livep session) - (progn (shell session) (get-buffer (current-buffer))))))) + (progn + (shell session) + ;; Needed for Emacs 23 since the marker is initially + ;; undefined and the filter functions try to use it without + ;; checking. + (set-marker comint-last-output-start (point)) + (get-buffer (current-buffer))))))) (defvar org-babel-sh-eoe-indicator "echo 'org_babel_sh_eoe'" "String to indicate that evaluation has completed.") diff --git a/lisp/org/ob-tangle.el b/lisp/org/ob-tangle.el index 37b2d92a8cf..3a43b42e3ad 100644 --- a/lisp/org/ob-tangle.el +++ b/lisp/org/ob-tangle.el @@ -225,13 +225,14 @@ used to limit the exported source code blocks by language." (concat base-name "." ext) base-name)))) (when file-name ;; Possibly create the parent directories for file. - (when (let ((m (funcall get-spec :mkdirp))) - (and m (not (string= m "no")))) - (make-directory (file-name-directory file-name) 'parents)) + (let ((m (funcall get-spec :mkdirp)) + (fnd (file-name-directory file-name))) + (and m fnd (not (string= m "no")) + (make-directory fnd 'parents))) ;; delete any old versions of file - (when (and (file-exists-p file-name) - (not (member file-name (mapcar #'car path-collector)))) - (delete-file file-name)) + (and (file-exists-p file-name) + (not (member file-name (mapcar #'car path-collector))) + (delete-file file-name)) ;; drop source-block to file (with-temp-buffer (when (fboundp lang-f) (ignore-errors (funcall lang-f))) diff --git a/lisp/org/org-agenda.el b/lisp/org/org-agenda.el index 18fada15de8..6f9db514d43 100644 --- a/lisp/org/org-agenda.el +++ b/lisp/org/org-agenda.el @@ -390,32 +390,36 @@ the daily/weekly agenda, see `org-agenda-skip-function'.") (repeat :inline t :tag "Conditions for skipping" (choice :tag "Condition type" - (list :tag "Regexp matches" :inline t (const :format "" regexp) (regexp)) - (list :tag "Regexp does not match" :inline t (const :format "" notregexp) (regexp)) + (list :tag "Regexp matches" :inline t + (const :format "" 'regexp) + (regexp)) + (list :tag "Regexp does not match" :inline t + (const :format "" 'notregexp) + (regexp)) (list :tag "TODO state is" :inline t - (const todo) + (const 'todo) (choice - (const :tag "any not-done state" todo) - (const :tag "any done state" done) - (const :tag "any state" any) + (const :tag "Any not-done state" 'todo) + (const :tag "Any done state" 'done) + (const :tag "Any state" 'any) (list :tag "Keyword list" (const :format "" quote) (repeat (string :tag "Keyword"))))) (list :tag "TODO state is not" :inline t - (const nottodo) + (const 'nottodo) (choice - (const :tag "any not-done state" todo) - (const :tag "any done state" done) - (const :tag "any state" any) + (const :tag "Any not-done state" 'todo) + (const :tag "Any done state" 'done) + (const :tag "Any state" 'any) (list :tag "Keyword list" (const :format "" quote) (repeat (string :tag "Keyword"))))) - (const :tag "scheduled" scheduled) - (const :tag "not scheduled" notscheduled) - (const :tag "deadline" deadline) - (const :tag "no deadline" notdeadline) - (const :tag "timestamp" timestamp) - (const :tag "no timestamp" nottimestamp)))))) + (const :tag "scheduled" 'scheduled) + (const :tag "not scheduled" 'notscheduled) + (const :tag "deadline" 'deadline) + (const :tag "no deadline" 'notdeadline) + (const :tag "timestamp" 'timestamp) + (const :tag "no timestamp" 'nottimestamp)))))) (list :tag "Non-standard skipping condition" :value (org-agenda-skip-function) (const org-agenda-skip-function) @@ -2092,11 +2096,9 @@ When nil, `q' will kill the single agenda buffer." org-agenda-info org-agenda-pre-window-conf org-agenda-columns-active - org-agenda-tag-filter-overlays org-agenda-tag-filter - org-agenda-cat-filter-overlays org-agenda-category-filter - org-agenda-re-filter-overlays + org-agenda-top-headline-filter org-agenda-regexp-filter org-agenda-markers org-agenda-last-search-view-search-was-boolean @@ -2158,10 +2160,11 @@ The following commands are available: nil t) (unless org-agenda-keep-modes (setq org-agenda-follow-mode org-agenda-start-with-follow-mode - org-agenda-entry-text-mode org-agenda-start-with-entry-text-mode - org-agenda-clockreport-mode org-agenda-start-with-clockreport-mode - org-agenda-show-log org-agenda-start-with-log-mode)) - + org-agenda-entry-text-mode org-agenda-start-with-entry-text-mode)) + (setq org-agenda-show-log org-agenda-start-with-log-mode) + (setq org-agenda-clockreport-mode org-agenda-start-with-clockreport-mode) + (add-to-invisibility-spec '(org-filtered)) + (add-to-invisibility-spec '(org-link)) (easy-menu-change '("Agenda") "Agenda Files" (append @@ -2604,7 +2607,7 @@ type." :package-version '(Org . "8.0") :group 'org-agenda-custom-commands :type '(choice (symbol :tag "No limit" nil) - (integer :tag "Max number of entries") + (integer :tag "Max number of TODOs") (repeat (cons (choice :tag "Agenda type" (const agenda) @@ -2612,7 +2615,7 @@ type." (const tags) (const search) (const timeline)) - (integer :tag "Max number of entries"))))) + (integer :tag "Max number of TODOs"))))) (defcustom org-agenda-max-tags nil "Maximum number of tagged entries to display in an agenda. @@ -2623,7 +2626,7 @@ type." :package-version '(Org . "8.0") :group 'org-agenda-custom-commands :type '(choice (symbol :tag "No limit" nil) - (integer :tag "Max number of entries") + (integer :tag "Max number of tagged entries") (repeat (cons (choice :tag "Agenda type" (const agenda) @@ -2631,7 +2634,7 @@ type." (const tags) (const search) (const timeline)) - (integer :tag "Max number of entries"))))) + (integer :tag "Max number of tagged entries"))))) (defcustom org-agenda-max-effort nil "Maximum cumulated effort duration for the agenda. @@ -2642,7 +2645,7 @@ to limit entries to in this type." :package-version '(Org . "8.0") :group 'org-agenda-custom-commands :type '(choice (symbol :tag "No limit" nil) - (integer :tag "Max number of entries") + (integer :tag "Max number of minutes") (repeat (cons (choice :tag "Agenda type" (const agenda) @@ -2650,7 +2653,7 @@ to limit entries to in this type." (const tags) (const search) (const timeline)) - (integer :tag "Max number of entries"))))) + (integer :tag "Max number of minutes"))))) (defvar org-keys nil) (defvar org-match nil) @@ -3324,19 +3327,12 @@ If AGENDA-BUFFER-NAME, use this as the buffer name for the agenda to write." (org-let (if nosettings nil org-agenda-exporter-settings) '(save-excursion (save-window-excursion - (org-agenda-mark-filtered-text) (let ((bs (copy-sequence (buffer-string))) beg content) - (org-agenda-unmark-filtered-text) (with-temp-buffer (rename-buffer org-agenda-write-buffer-name t) (set-buffer-modified-p nil) (insert bs) (org-agenda-remove-marked-text 'org-filtered) - (while (setq beg (text-property-any (point-min) (point-max) - 'org-filtered t)) - (delete-region - beg (or (next-single-property-change beg 'org-filtered) - (point-max)))) (run-hooks 'org-agenda-before-write-hook) (cond ((org-bound-and-true-p org-mobile-creating-agendas) @@ -3356,7 +3352,7 @@ If AGENDA-BUFFER-NAME, use this as the buffer name for the agenda to write." content))) (find-file file) (erase-buffer) - (mapcar (lambda (s) (org-paste-subtree 1 s)) (reverse content)) + (dolist (s content) (org-paste-subtree 1 s)) (write-file file) (kill-buffer (current-buffer)) (message "Org file written to %s" file))) @@ -3402,28 +3398,6 @@ If AGENDA-BUFFER-NAME, use this as the buffer name for the agenda to write." org-agenda-buffer-name))) (when open (org-open-file file))) -(defvar org-agenda-tag-filter-overlays nil) -(defvar org-agenda-cat-filter-overlays nil) -(defvar org-agenda-re-filter-overlays nil) - -(defun org-agenda-mark-filtered-text () - "Mark all text hidden by filtering with a text property." - (let ((inhibit-read-only t)) - (mapc - (lambda (o) - (when (equal (overlay-buffer o) (current-buffer)) - (put-text-property - (overlay-start o) (overlay-end o) - 'org-filtered t))) - (append org-agenda-tag-filter-overlays - org-agenda-cat-filter-overlays - org-agenda-re-filter-overlays)))) - -(defun org-agenda-unmark-filtered-text () - "Remove the filtering text property." - (let ((inhibit-read-only t)) - (remove-text-properties (point-min) (point-max) '(org-filtered t)))) - (defun org-agenda-remove-marked-text (property &optional value) "Delete all text marked with VALUE of PROPERTY. VALUE defaults to t." @@ -3432,7 +3406,7 @@ VALUE defaults to t." (while (setq beg (text-property-any (point-min) (point-max) property value)) (delete-region - beg (or (next-single-property-change beg 'org-filtered) + beg (or (next-single-property-change beg property) (point-max)))))) (defun org-agenda-add-entry-text () @@ -3557,7 +3531,6 @@ removed from the entry content. Currently only `planning' is allowed here." (defvar org-agenda-category-filter nil) (defvar org-agenda-regexp-filter nil) (defvar org-agenda-top-headline-filter nil) -(defvar org-agenda-tag-filter-while-redo nil) (defvar org-agenda-tag-filter-preset nil "A preset of the tags filter used for secondary agenda filtering. This must be a list of strings, each string must be a single tag preceded @@ -3609,10 +3582,12 @@ generating a new one." ;; does not have org variables local org-agenda-this-buffer-is-sticky)))) -(defun org-agenda-prepare-window (abuf) - "Setup agenda buffer in the window." - (let* ((awin (get-buffer-window abuf)) - wconf) +(defun org-agenda-prepare-window (abuf filter-alist) + "Setup agenda buffer in the window. +ABUF is the buffer for the agenda window. +FILTER-ALIST is an alist of filters we need to apply when +`org-agenda-persistent-filter' is non-nil." + (let* ((awin (get-buffer-window abuf)) wconf) (cond ((equal (current-buffer) abuf) nil) (awin (select-window awin)) @@ -3626,68 +3601,76 @@ generating a new one." ((equal org-agenda-window-setup 'reorganize-frame) (delete-other-windows) (org-switch-to-buffer-other-window abuf))) - ;; additional test in case agenda is invoked from within agenda - ;; buffer via elisp link + (setq org-agenda-tag-filter (cdr (assoc 'tag filter-alist))) + (setq org-agenda-category-filter (cdr (assoc 'cat filter-alist))) + (setq org-agenda-regexp-filter (cdr (assoc 're filter-alist))) + ;; Additional test in case agenda is invoked from within agenda + ;; buffer via elisp link. (unless (equal (current-buffer) abuf) (org-pop-to-buffer-same-window abuf)) (setq org-agenda-pre-window-conf (or org-agenda-pre-window-conf wconf)))) (defun org-agenda-prepare (&optional name) - (if (org-agenda-use-sticky-p) - (progn - ;; Popup existing buffer - (org-agenda-prepare-window (get-buffer org-agenda-buffer-name)) - (message "Sticky Agenda buffer, use `r' to refresh") - (or org-agenda-multi (org-agenda-fit-window-to-buffer)) - (throw 'exit "Sticky Agenda buffer, use `r' to refresh")) - (setq org-todo-keywords-for-agenda nil) - (setq org-drawers-for-agenda nil) - (unless org-agenda-persistent-filter - (setq org-agenda-tag-filter nil - org-agenda-category-filter nil - org-agenda-regexp-filter nil)) - (put 'org-agenda-tag-filter :preset-filter - org-agenda-tag-filter-preset) - (put 'org-agenda-category-filter :preset-filter - org-agenda-category-filter-preset) - (put 'org-agenda-regexp-filter :preset-filter - org-agenda-regexp-filter-preset) - (if org-agenda-multi + (let ((filter-alist (if org-agenda-persistent-filter + (list `(tag . ,org-agenda-tag-filter) + `(re . ,org-agenda-regexp-filter) + `(car . ,org-agenda-category-filter))))) + (if (org-agenda-use-sticky-p) (progn - (setq buffer-read-only nil) - (goto-char (point-max)) - (unless (or (bobp) org-agenda-compact-blocks - (not org-agenda-block-separator)) - (insert "\n" - (if (stringp org-agenda-block-separator) - org-agenda-block-separator - (make-string (window-width) org-agenda-block-separator)) - "\n")) - (narrow-to-region (point) (point-max))) - (setq org-done-keywords-for-agenda nil) - - ;; Setting any org variables that are in org-agenda-local-vars - ;; list need to be done after the prepare call - (org-agenda-prepare-window (get-buffer-create org-agenda-buffer-name)) - (setq buffer-read-only nil) - (org-agenda-reset-markers) - (let ((inhibit-read-only t)) (erase-buffer)) - (org-agenda-mode) - (setq org-agenda-buffer (current-buffer)) - (setq org-agenda-contributing-files nil) - (setq org-agenda-columns-active nil) - (org-agenda-prepare-buffers (org-agenda-files nil 'ifmode)) - (setq org-todo-keywords-for-agenda - (org-uniquify org-todo-keywords-for-agenda)) - (setq org-done-keywords-for-agenda - (org-uniquify org-done-keywords-for-agenda)) - (setq org-drawers-for-agenda (org-uniquify org-drawers-for-agenda)) - (setq org-agenda-last-prefix-arg current-prefix-arg) - (setq org-agenda-this-buffer-name org-agenda-buffer-name) - (and name (not org-agenda-name) - (org-set-local 'org-agenda-name name))) - (setq buffer-read-only nil))) + (put 'org-agenda-tag-filter :preset-filter nil) + (put 'org-agenda-category-filter :preset-filter nil) + (put 'org-agenda-regexp-filter :preset-filter nil) + ;; Popup existing buffer + (org-agenda-prepare-window (get-buffer org-agenda-buffer-name) + filter-alist) + (message "Sticky Agenda buffer, use `r' to refresh") + (or org-agenda-multi (org-agenda-fit-window-to-buffer)) + (throw 'exit "Sticky Agenda buffer, use `r' to refresh")) + (setq org-todo-keywords-for-agenda nil) + (setq org-drawers-for-agenda nil) + (put 'org-agenda-tag-filter :preset-filter + org-agenda-tag-filter-preset) + (put 'org-agenda-category-filter :preset-filter + org-agenda-category-filter-preset) + (put 'org-agenda-regexp-filter :preset-filter + org-agenda-regexp-filter-preset) + (if org-agenda-multi + (progn + (setq buffer-read-only nil) + (goto-char (point-max)) + (unless (or (bobp) org-agenda-compact-blocks + (not org-agenda-block-separator)) + (insert "\n" + (if (stringp org-agenda-block-separator) + org-agenda-block-separator + (make-string (window-width) org-agenda-block-separator)) + "\n")) + (narrow-to-region (point) (point-max))) + (setq org-done-keywords-for-agenda nil) + + ;; Setting any org variables that are in org-agenda-local-vars + ;; list need to be done after the prepare call + (org-agenda-prepare-window + (get-buffer-create org-agenda-buffer-name) filter-alist) + (setq buffer-read-only nil) + (org-agenda-reset-markers) + (let ((inhibit-read-only t)) (erase-buffer)) + (org-agenda-mode) + (setq org-agenda-buffer (current-buffer)) + (setq org-agenda-contributing-files nil) + (setq org-agenda-columns-active nil) + (org-agenda-prepare-buffers (org-agenda-files nil 'ifmode)) + (setq org-todo-keywords-for-agenda + (org-uniquify org-todo-keywords-for-agenda)) + (setq org-done-keywords-for-agenda + (org-uniquify org-done-keywords-for-agenda)) + (setq org-drawers-for-agenda (org-uniquify org-drawers-for-agenda)) + (setq org-agenda-last-prefix-arg current-prefix-arg) + (setq org-agenda-this-buffer-name org-agenda-buffer-name) + (and name (not org-agenda-name) + (org-set-local 'org-agenda-name name))) + (setq buffer-read-only nil)))) (defvar org-agenda-overriding-columns-format) ; From org-colview.el (defun org-agenda-finalize () @@ -3739,13 +3722,15 @@ generating a new one." (save-excursion (goto-char (point-min)) (while (equal (forward-line) 0) - (when (setq mrk (or (get-text-property (point) 'org-hd-marker) - (get-text-property (point) 'org-hd-marker))) + (when (setq mrk (get-text-property (point) 'org-hd-marker)) (put-text-property (point-at-bol) (point-at-eol) 'tags (org-with-point-at mrk (delete-dups (mapcar 'downcase (org-get-tags-at)))))))))) (run-hooks 'org-agenda-finalize-hook) + (when org-agenda-top-headline-filter + (org-agenda-filter-top-headline-apply + org-agenda-top-headline-filter)) (when org-agenda-tag-filter (org-agenda-filter-apply org-agenda-tag-filter 'tag)) (when (get 'org-agenda-tag-filter :preset-filter) @@ -4326,14 +4311,6 @@ items if they have an hour specification like [h]h:mm." (setq p (plist-put p :tstart clocktable-start)) (setq p (plist-put p :tend clocktable-end)) (setq p (plist-put p :scope 'agenda)) - (when (and (eq org-agenda-clockreport-mode 'with-filter) - (setq filter (or org-agenda-tag-filter-while-redo - (get 'org-agenda-tag-filter :preset-filter)))) - (setq p (plist-put p :tags (mapconcat (lambda (x) - (if (string-match "[<>=]" x) - "" - x)) - filter "")))) (setq tbl (apply 'org-clock-get-clocktable p)) (insert tbl))) (goto-char (point-min)) @@ -5703,7 +5680,7 @@ This function is invoked if `org-agenda-todo-ignore-deadlines', (setq txt (org-agenda-format-item extra txt level category tags 'time)) (org-add-props txt props 'org-marker marker 'org-category category 'date date 'todo-state todo-state - 'org-category-position category-pos 'tags tags + 'org-category-position category-pos 'level level 'type "sexp" 'warntime warntime) (push txt ee))))) @@ -6781,8 +6758,10 @@ The optional STRING argument forces conversion into a 5 character wide string HH:MM." (save-match-data (when - (or (string-match "\\<\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)\\([AaPp][Mm]\\)?\\> *" s) - (string-match "\\<\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)?\\([AaPp][Mm]\\)\\> *" s)) + (and + (or (string-match "\\<\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)\\([AaPp][Mm]\\)?\\> *" s) + (string-match "\\<\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)?\\([AaPp][Mm]\\)\\> *" s)) + (not (eq (get-text-property 1 'face s) 'org-link))) (let* ((h (string-to-number (match-string 1 s))) (m (if (match-end 3) (string-to-number (match-string 3 s)) 0)) (ampm (if (match-end 4) (downcase (match-string 4 s)))) @@ -7010,7 +6989,7 @@ The optional argument TYPE tells the agenda type." (cond ((< ta tb) -1) ((< tb ta) +1)))) -(defsubst org-cmp-ts (a b &optional type) +(defsubst org-cmp-ts (a b type) "Compare the timestamps values of entries A and B. When TYPE is \"scheduled\", \"deadline\", \"timestamp\" or \"timestamp_ia\", compare within each of these type. When TYPE @@ -7018,9 +6997,11 @@ is the empty string, compare all timestamps without respect of their type." (let* ((def (if org-sort-agenda-notime-is-late most-positive-fixnum -1)) (ta (or (and (string-match type (or (get-text-property 1 'type a) "")) - (get-text-property 1 'ts-date a)) def)) + (get-text-property 1 'ts-date a)) + def)) (tb (or (and (string-match type (or (get-text-property 1 'type b) "")) - (get-text-property 1 'ts-date b)) def))) + (get-text-property 1 'ts-date b)) + def))) (cond ((< ta tb) -1) ((< tb ta) +1)))) @@ -7046,7 +7027,7 @@ their type." (org-cmp-ts a b "deadline"))) (deadline-down (if deadline-up (- deadline-up) nil)) (tsia-up (and (org-em 'tsia-up 'tsia-down ss) - (org-cmp-ts a b "iatimestamp_ia"))) + (org-cmp-ts a b "timestamp_ia"))) (tsia-down (if tsia-up (- tsia-up) nil)) (ts-up (and (org-em 'ts-up 'ts-down ss) (org-cmp-ts a b "timestamp"))) @@ -7283,7 +7264,6 @@ in the agenda." (cat-preset (get 'org-agenda-category-filter :preset-filter)) (re-filter org-agenda-regexp-filter) (re-preset (get 'org-agenda-regexp-filter :preset-filter)) - (org-agenda-tag-filter-while-redo (or tag-filter tag-preset)) (cols org-agenda-columns-active) (line (org-current-line)) (window-line (- line (org-current-line (window-start)))) @@ -7316,9 +7296,12 @@ in the agenda." (put 'org-agenda-tag-filter :preset-filter tag-preset) (put 'org-agenda-category-filter :preset-filter cat-preset) (put 'org-agenda-regexp-filter :preset-filter re-preset) - (and (or tag-filter tag-preset) (org-agenda-filter-apply tag-filter 'tag)) - (and (or cat-filter cat-preset) (org-agenda-filter-apply cat-filter 'category)) - (and (or re-filter re-preset) (org-agenda-filter-apply re-filter 'regexp)) + (let ((tag (or tag-filter tag-preset)) + (cat (or cat-filter cat-preset)) + (re (or re-filter re-preset))) + (when tag (org-agenda-filter-apply tag 'tag)) + (when cat (org-agenda-filter-apply cat 'category)) + (when re (org-agenda-filter-apply re 'regexp))) (and top-hl-filter (org-agenda-filter-top-headline-apply top-hl-filter)) (and cols (org-called-interactively-p 'any) (org-agenda-columns)) (org-goto-line line) @@ -7344,7 +7327,7 @@ The category is that of the current line." (org-agenda-filter-apply (setq org-agenda-category-filter (list (concat "+" cat))) 'category)) - ((error "No category at point")))))) + (t (error "No category at point")))))) (defun org-find-top-headline (&optional pos) "Find the topmost parent headline and return it." @@ -7365,10 +7348,10 @@ The top headline is that of the current line." (progn (setq org-agenda-filtered-by-top-headline nil org-agenda-top-headline-filter nil) - (org-agenda-filter-show-all-cat)) - (let ((cat (org-find-top-headline (org-get-at-bol 'org-hd-marker)))) - (if cat (org-agenda-filter-top-headline-apply cat strip) - (error "No top-level category at point"))))) + (org-agenda-filter-show-all-top-filter)) + (let ((toph (org-find-top-headline (org-get-at-bol 'org-hd-marker)))) + (if toph (org-agenda-filter-top-headline-apply toph strip) + (error "No top-level headline at point"))))) (defvar org-agenda-regexp-filter nil) (defun org-agenda-filter-by-regexp (strip) @@ -7397,7 +7380,10 @@ With two prefix arguments, remove the regexp filters." (when org-agenda-category-filter (org-agenda-filter-show-all-cat)) (when org-agenda-regexp-filter - (org-agenda-filter-show-all-re))) + (org-agenda-filter-show-all-re)) + (when org-agenda-top-headline-filter + (org-agenda-filter-show-all-top-filter)) + (org-agenda-finalize)) (defun org-agenda-filter-by-tag (strip &optional char narrow) "Keep only those lines in the agenda buffer that have a specific tag. @@ -7500,8 +7486,7 @@ to switch to narrowing." (org-agenda-filter-apply org-agenda-tag-filter 'tag) (setq maybe-refresh t)) (t (error "Invalid tag selection character %c" char))) - (when (and maybe-refresh - (eq org-agenda-clockreport-mode 'with-filter)) + (when maybe-refresh (org-agenda-redo)))) (defun org-agenda-get-represented-tags () @@ -7622,13 +7607,12 @@ When NO-OPERATOR is non-nil, do not add the + operator to returned tags." ;; Deactivate `org-agenda-entry-text-mode' when filtering (if org-agenda-entry-text-mode (org-agenda-entry-text-mode)) (let (tags cat txt) - (setq org-agenda-filter-form - (org-agenda-filter-make-matcher filter type)) - (if (and (eq type 'category) - (not (equal (substring (car filter) 0 1) "-"))) - ;; Only set `org-agenda-filtered-by-category' to t - ;; when a unique category is used as the filter - (setq org-agenda-filtered-by-category t)) + (setq org-agenda-filter-form (org-agenda-filter-make-matcher filter type)) + ;; Only set `org-agenda-filtered-by-category' to t when a unique + ;; category is used as the filter: + (setq org-agenda-filtered-by-category + (and (eq type 'category) + (not (equal (substring (car filter) 0 1) "-")))) (org-agenda-set-mode-name) (save-excursion (goto-char (point-min)) @@ -7659,7 +7643,7 @@ When NO-OPERATOR is non-nil, do not add the + operator to returned tags." (tophl (and pos (org-find-top-headline pos)))) (if (and tophl (funcall (if negative 'identity 'not) (string= hl tophl))) - (org-agenda-filter-hide-line 'category))) + (org-agenda-filter-hide-line 'top-headline))) (beginning-of-line 2))) (if (get-char-property (point) 'invisible) (org-agenda-previous-line)) @@ -7669,50 +7653,35 @@ When NO-OPERATOR is non-nil, do not add the + operator to returned tags." (defun org-agenda-filter-hide-line (type) "Hide lines with TYPE in the agenda buffer." (let* ((b (max (point-min) (1- (point-at-bol)))) - (e (point-at-eol)) - (ov (make-overlay b e))) - (overlay-put ov 'invisible t) - (overlay-put ov 'intangible t) - (overlay-put ov 'type type) - (cond ((eq type 'tag) (push ov org-agenda-tag-filter-overlays)) - ((eq type 'category) (push ov org-agenda-cat-filter-overlays)) - ((eq type 'regexp) (push ov org-agenda-re-filter-overlays))))) - -(defun org-agenda-fix-tags-filter-overlays-at (&optional pos) - (setq pos (or pos (point))) + (e (point-at-eol))) + (let ((inhibit-read-only t)) + (add-text-properties + b e `(invisible org-filtered org-filter-type ,type))))) + +(defun org-agenda-remove-filter (type) + (interactive) + "Remove filter of type TYPE from the agenda buffer." (save-excursion - (dolist (ov (overlays-at pos)) - (when (and (overlay-get ov 'invisible) - (eq (overlay-get ov 'type) 'tag)) + (goto-char (point-min)) + (let ((inhibit-read-only t) pos) + (while (setq pos (text-property-any (point) (point-max) 'org-filter-type type)) (goto-char pos) - (if (< (overlay-start ov) (point-at-eol)) - (move-overlay ov (point-at-eol) - (overlay-end ov))))))) + (remove-text-properties + (point) (next-single-property-change (point) 'org-filter-type) + `(invisible org-filtered org-filter-type ,type)))) + (set (intern (format "org-agenda-%s-filter" (intern-soft type))) nil) + (setq org-agenda-filter-form nil) + (org-agenda-set-mode-name) + (org-agenda-finalize))) (defun org-agenda-filter-show-all-tag nil - "Remove tag filter overlays from the agenda buffer." - (mapc 'delete-overlay org-agenda-tag-filter-overlays) - (setq org-agenda-tag-filter-overlays nil - org-agenda-tag-filter nil - org-agenda-filter-form nil) - (org-agenda-set-mode-name)) - + (org-agenda-remove-filter 'tag)) (defun org-agenda-filter-show-all-re nil - "Remove regexp filter overlays from the agenda buffer." - (mapc 'delete-overlay org-agenda-re-filter-overlays) - (setq org-agenda-re-filter-overlays nil - org-agenda-regexp-filter nil - org-agenda-filter-form nil) - (org-agenda-set-mode-name)) - + (org-agenda-remove-filter 'regexp)) (defun org-agenda-filter-show-all-cat nil - "Remove category filter overlays from the agenda buffer." - (mapc 'delete-overlay org-agenda-cat-filter-overlays) - (setq org-agenda-cat-filter-overlays nil - org-agenda-filtered-by-category nil - org-agenda-category-filter nil - org-agenda-filter-form nil) - (org-agenda-set-mode-name)) + (org-agenda-remove-filter 'category)) +(defun org-agenda-filter-show-all-top-filter nil + (org-agenda-remove-filter 'top-headline)) (defun org-agenda-manipulate-query-add () "Manipulate the query by adding a search term with positive selection. @@ -8106,15 +8075,12 @@ so that the date SD will be in that range." (format " (maximum number of lines is %d)" (if (integerp arg) arg org-agenda-entry-text-maxlines)))))) -(defun org-agenda-clockreport-mode (&optional with-filter) - "Toggle clocktable mode in an agenda buffer. -With prefix arg WITH-FILTER, make the clocktable respect the current -agenda filter." - (interactive "P") +(defun org-agenda-clockreport-mode () + "Toggle clocktable mode in an agenda buffer." + (interactive) (org-agenda-check-type t 'agenda) - (if with-filter - (setq org-agenda-clockreport-mode 'with-filter) - (setq org-agenda-clockreport-mode (not org-agenda-clockreport-mode))) + (setq org-agenda-clockreport-mode (not org-agenda-clockreport-mode)) + (setq org-agenda-start-with-clockreport-mode org-agenda-clockreport-mode) (org-agenda-set-mode-name) (org-agenda-redo) (message "Clocktable mode is %s" @@ -8135,6 +8101,7 @@ With a double `C-u' prefix arg, show *only* log items, nothing else." nil 'clockcheck)) (special '(closed clock state)) (t (not org-agenda-show-log)))) + (setq org-agenda-start-with-log-mode org-agenda-show-log) (org-agenda-set-mode-name) (org-agenda-redo) (message "Log mode is %s" @@ -8252,10 +8219,7 @@ When called with a prefix argument, include all archive files as well." " Archives" (format " :%s:" org-archive-tag)) "") - (if org-agenda-clockreport-mode - (if (eq org-agenda-clockreport-mode 'with-filter) - " Clock{}" " Clock") - ""))) + (if org-agenda-clockreport-mode " Clock" ""))) (force-mode-line-update)) (define-obsolete-function-alias @@ -8623,7 +8587,8 @@ if it was hidden in the outline." (interactive "p") (let ((win (selected-window))) (org-agenda-goto t) - (org-recenter-heading 1) + (org-back-to-heading) + (set-window-start (selected-window) (point-at-bol)) (cond ((= more 0) (hide-subtree) @@ -8662,11 +8627,6 @@ if it was hidden in the outline." (message "Remote: SUBTREE AND ALL DRAWERS"))) (select-window win))) -(defun org-recenter-heading (n) - (save-excursion - (org-back-to-heading) - (recenter n))) - (defvar org-agenda-cycle-counter nil) (defun org-agenda-cycle-show (&optional n) "Show the current entry in another window, with default settings. @@ -9177,8 +9137,6 @@ Called with a universal prefix arg, show the priority instead of setting it." (when (equal marker (org-get-at-bol 'org-marker)) (remove-text-properties (point-at-bol) (point-at-eol) '(display)) (org-move-to-column (- (window-width) (length stamp)) t) - - (org-agenda-fix-tags-filter-overlays-at (point)) (if (featurep 'xemacs) ;; Use `duplicable' property to trigger undo recording (let ((ex (make-extent nil nil)) @@ -9190,7 +9148,7 @@ Called with a universal prefix arg, show the priority instead of setting it." (add-text-properties (1- (point)) (point-at-eol) (list 'display (org-add-props stamp nil - 'face 'secondary-selection)))) + 'face '(secondary-selection default))))) (beginning-of-line 1)) (beginning-of-line 0))))) @@ -9478,9 +9436,9 @@ a timestamp can be added there." (if org-adapt-indentation (org-indent-to-column 2))) (defun org-agenda-insert-diary-make-new-entry (text) - "Make new entry as last child of current entry. -Add TEXT as headline, and position the cursor in the second line so that -a timestamp can be added there." + "Make a new entry with TEXT as the first child of the current subtree. +Position the point in the line right after the new heading so +that a timestamp can be added there." (let ((org-show-following-heading t) (org-show-siblings t) (org-show-hierarchy-above t) @@ -9669,7 +9627,7 @@ This is a command that has to be installed in `calendar-mode-map'." (overlay-put ov 'type 'org-marked-entry-overlay)) (end-of-line 1) (or (ignore-errors - (goto-char (next-single-property-change (point) 'txt))) + (goto-char (next-single-property-change (point) 'org-hd-marker))) (beginning-of-line 2)) (while (and (get-char-property (point) 'invisible) (not (eobp))) (beginning-of-line 2)) @@ -9687,7 +9645,7 @@ This is a command that has to be installed in `calendar-mode-map'." (let ((entries-marked 0) txt-at-point) (save-excursion (goto-char (point-min)) - (goto-char (next-single-property-change (point) 'txt)) + (goto-char (next-single-property-change (point) 'org-hd-marker)) (while (and (re-search-forward regexp nil t) (setq txt-at-point (get-text-property (point) 'txt))) (when (string-match regexp txt-at-point) @@ -9723,7 +9681,7 @@ This is a command that has to be installed in `calendar-mode-map'." (save-excursion (goto-char (point-min)) (while (ignore-errors - (goto-char (next-single-property-change (point) 'txt))) + (goto-char (next-single-property-change (point) 'org-hd-marker))) (org-agenda-bulk-toggle)))) (defun org-agenda-bulk-toggle () diff --git a/lisp/org/org-attach.el b/lisp/org/org-attach.el index 07307e68f6f..bcf7ba736fd 100644 --- a/lisp/org/org-attach.el +++ b/lisp/org/org-attach.el @@ -208,7 +208,9 @@ the directory and (if necessary) the corresponding ID will be created." (save-excursion (save-restriction (widen) - (goto-char org-entry-property-inherited-from) + (if (marker-position org-entry-property-inherited-from) + (goto-char org-entry-property-inherited-from) + (org-back-to-heading t)) (let (org-attach-allow-inheritance) (org-attach-dir create-if-not-exists-p))))) (org-attach-check-absolute-path attach-dir) diff --git a/lisp/org/org-bbdb.el b/lisp/org/org-bbdb.el index b9841a65b84..cfd5b3b6a8c 100644 --- a/lisp/org/org-bbdb.el +++ b/lisp/org/org-bbdb.el @@ -400,8 +400,11 @@ This is used by Org to re-create the anniversary hash table." (defun org-bbdb-complete-link () "Read a bbdb link with name completion." (require 'bbdb-com) - (concat "bbdb:" - (bbdb-record-name (car (bbdb-completing-read-record "Name: "))))) + (let ((rec (bbdb-completing-read-record "Name: "))) + (concat "bbdb:" + (bbdb-record-name (if (listp rec) + (car rec) + rec))))) (defun org-bbdb-anniv-export-ical () "Extract anniversaries from BBDB and convert them to icalendar format." diff --git a/lisp/org/org-bibtex.el b/lisp/org/org-bibtex.el index b6557108845..75ac69ba704 100644 --- a/lisp/org/org-bibtex.el +++ b/lisp/org/org-bibtex.el @@ -203,7 +203,7 @@ (:pages . "One or more page numbers or range of numbers, such as 42-111 or 7,41,73-97 or 43+ (the ‘+’ in this last example indicates pages following that don’t form simple range). BibTEX requires double dashes for page ranges (--).") (:publisher . "The publisher’s name.") (:school . "The name of the school where a thesis was written.") - (:series . "The name of a series or set of books. When citing an entire book, the the title field gives its title and an optional series field gives the name of a series or multi-volume set in which the book is published.") + (:series . "The name of a series or set of books. When citing an entire book, the title field gives its title and an optional series field gives the name of a series or multi-volume set in which the book is published.") (:title . "The work’s title, typed as explained in the LaTeX book.") (:type . "The type of a technical report for example, 'Research Note'.") (:volume . "The volume of a journal or multi-volume book.") diff --git a/lisp/org/org-capture.el b/lisp/org/org-capture.el index 0433306a909..c7086837437 100644 --- a/lisp/org/org-capture.el +++ b/lisp/org/org-capture.el @@ -1529,8 +1529,8 @@ The template may still contain \"%?\" for cursor positioning." (v-x (or (org-get-x-clipboard 'PRIMARY) (org-get-x-clipboard 'CLIPBOARD) (org-get-x-clipboard 'SECONDARY))) - (v-t (format-time-string (car org-time-stamp-formats) ct)) - (v-T (format-time-string (cdr org-time-stamp-formats) ct)) + (v-t (format-time-string (car org-time-stamp-formats) ct1)) + (v-T (format-time-string (cdr org-time-stamp-formats) ct1)) (v-u (concat "[" (substring v-t 1 -1) "]")) (v-U (concat "[" (substring v-T 1 -1) "]")) ;; `initial' and `annotation' might habe been passed. @@ -1587,7 +1587,7 @@ The template may still contain \"%?\" for cursor positioning." (insert template) (goto-char (point-min)) (org-capture-steal-local-variables buffer) - (setq buffer-file-name nil) + (setq buffer-file-name nil mark-active nil) ;; %[] Insert contents of a file. (goto-char (point-min)) @@ -1674,7 +1674,9 @@ The template may still contain \"%?\" for cursor positioning." (or (equal (char-before) ?:) (insert ":")) (insert ins) (or (equal (char-after) ?:) (insert ":")) - (and (org-at-heading-p) (org-set-tags nil 'align))))) + (and (org-at-heading-p) + (let ((org-ignore-region t)) + (org-set-tags nil 'align)))))) ((equal char "C") (cond ((= (length clipboards) 1) (insert (car clipboards))) ((> (length clipboards) 1) diff --git a/lisp/org/org-clock.el b/lisp/org/org-clock.el index f2a37484cc0..892ae18108a 100644 --- a/lisp/org/org-clock.el +++ b/lisp/org/org-clock.el @@ -2556,13 +2556,10 @@ from the dynamic block definition." total-time)) (defun org-clocktable-indent-string (level) - (if (= level 1) - "" - (let ((str "\\__")) - (while (> level 2) - (setq level (1- level) - str (concat str "___"))) - (concat str " ")))) + (if (= level 1) "" + (let ((str " ")) + (dotimes (k (1- level) str) + (setq str (concat "\\emsp" str)))))) (defun org-clocktable-steps (params) "Step through the range to make a number of clock tables." diff --git a/lisp/org/org-compat.el b/lisp/org/org-compat.el index 70c41d53cd9..90380a8806c 100644 --- a/lisp/org/org-compat.el +++ b/lisp/org/org-compat.el @@ -312,8 +312,7 @@ Works on both Emacs and XEmacs." (defun org-in-invisibility-spec-p (arg) "Is ARG a member of `buffer-invisibility-spec'?" (if (consp buffer-invisibility-spec) - (member arg buffer-invisibility-spec) - nil)) + (member arg buffer-invisibility-spec))) (defmacro org-xemacs-without-invisibility (&rest body) "Turn off extents with invisibility while executing BODY." @@ -347,18 +346,8 @@ Works on both Emacs and XEmacs." "Move to column COLUMN. Pass COLUMN and FORCE to `move-to-column'. Pass BUFFER to the XEmacs version of `move-to-column'." - (let* ((with-bracket-link - (save-excursion - (forward-line 0) - (looking-at (concat "^.*" org-bracket-link-regexp)))) - (buffer-invisibility-spec - (cond - ((or (not (derived-mode-p 'org-mode)) - (and with-bracket-link (org-invisible-p2))) - (remove '(org-link) buffer-invisibility-spec)) - (with-bracket-link - (remove t buffer-invisibility-spec)) - (t buffer-invisibility-spec)))) + (let ((buffer-invisibility-spec + (remove '(org-filtered) buffer-invisibility-spec))) (if (featurep 'xemacs) (org-xemacs-without-invisibility (move-to-column column force buffer)) diff --git a/lisp/org/org-element.el b/lisp/org/org-element.el index b44466e53df..eb8ff415861 100644 --- a/lisp/org/org-element.el +++ b/lisp/org/org-element.el @@ -360,11 +360,6 @@ still has an entry since one of its properties (`:title') does.") (footnote-reference . :inline-definition)) "Alist between element types and location of secondary value.") -(defconst org-element-object-variables '(org-link-abbrev-alist-local) - "List of buffer-local variables used when parsing objects. -These variables are copied to the temporary buffer created by -`org-export-secondary-string'.") - ;;; Accessors and Setters @@ -732,11 +727,11 @@ CONTENTS is the contents of the footnote-definition." Return a list whose CAR is `headline' and CDR is a plist containing `:raw-value', `:title', `:alt-title', `:begin', -`:end', `:pre-blank', `:hiddenp', `:contents-begin' and +`:end', `:pre-blank', `:hiddenp', `:contents-begin', `:contents-end', `:level', `:priority', `:tags', `:todo-keyword',`:todo-type', `:scheduled', `:deadline', -`:closed', `:quotedp', `:archivedp', `:commentedp' and -`:footnote-section-p' keywords. +`:closed', `:quotedp', `:archivedp', `:commentedp', +`:footnote-section-p' and `:post-blank' keywords. The plist also contains any property set in the property drawer, with its name in upper cases and colons added at the @@ -875,38 +870,40 @@ CONTENTS is the contents of the element." (org-element-property :tags headline)) (org-element-property :tags headline)))) (and tag-list - (format ":%s:" (mapconcat 'identity tag-list ":"))))) + (format ":%s:" (mapconcat #'identity tag-list ":"))))) (commentedp (org-element-property :commentedp headline)) (quotedp (org-element-property :quotedp headline)) (pre-blank (or (org-element-property :pre-blank headline) 0)) - (heading (concat (make-string (org-reduced-level level) ?*) - (and todo (concat " " todo)) - (and quotedp (concat " " org-quote-string)) - (and commentedp (concat " " org-comment-string)) - (and priority - (format " [#%s]" (char-to-string priority))) - (cond ((and org-footnote-section - (org-element-property - :footnote-section-p headline)) - (concat " " org-footnote-section)) - (title (concat " " title)))))) - (concat heading - ;; Align tags. - (when tags - (cond - ((zerop org-tags-column) (format " %s" tags)) - ((< org-tags-column 0) - (concat - (make-string - (max (- (+ org-tags-column (length heading) (length tags))) 1) - ? ) - tags)) - (t - (concat - (make-string (max (- org-tags-column (length heading)) 1) ? ) - tags)))) - (make-string (1+ pre-blank) 10) - contents))) + (heading + (concat (make-string (if org-odd-levels-only (1- (* level 2)) level) + ?*) + (and todo (concat " " todo)) + (and quotedp (concat " " org-quote-string)) + (and commentedp (concat " " org-comment-string)) + (and priority (format " [#%s]" (char-to-string priority))) + " " + (if (and org-footnote-section + (org-element-property :footnote-section-p headline)) + org-footnote-section + title)))) + (concat + heading + ;; Align tags. + (when tags + (cond + ((zerop org-tags-column) (format " %s" tags)) + ((< org-tags-column 0) + (concat + (make-string + (max (- (+ org-tags-column (length heading) (length tags))) 1) + ?\s) + tags)) + (t + (concat + (make-string (max (- org-tags-column (length heading)) 1) ?\s) + tags)))) + (make-string (1+ pre-blank) ?\n) + contents))) ;;;; Inlinetask @@ -1315,36 +1312,36 @@ containing `:begin', `:end', `:hiddenp', `:contents-begin', `:contents-end', `:post-blank' and `:post-affiliated' keywords. Assume point is at the beginning of the property drawer." - (save-excursion - (let ((case-fold-search t)) - (if (not (save-excursion - (re-search-forward "^[ \t]*:END:[ \t]*$" limit t))) - ;; Incomplete drawer: parse it as a paragraph. - (org-element-paragraph-parser limit affiliated) - (save-excursion - (let* ((drawer-end-line (match-beginning 0)) - (begin (car affiliated)) - (post-affiliated (point)) - (contents-begin (progn (forward-line) - (and (< (point) drawer-end-line) - (point)))) - (contents-end (and contents-begin drawer-end-line)) - (hidden (org-invisible-p2)) - (pos-before-blank (progn (goto-char drawer-end-line) - (forward-line) - (point))) - (end (progn (skip-chars-forward " \r\t\n" limit) - (if (eobp) (point) (line-beginning-position))))) - (list 'property-drawer - (nconc - (list :begin begin - :end end - :hiddenp hidden - :contents-begin contents-begin - :contents-end contents-end - :post-blank (count-lines pos-before-blank end) - :post-affiliated post-affiliated) - (cdr affiliated))))))))) + (let ((case-fold-search t)) + (if (not (save-excursion (re-search-forward "^[ \t]*:END:[ \t]*$" limit t))) + ;; Incomplete drawer: parse it as a paragraph. + (org-element-paragraph-parser limit affiliated) + (save-excursion + (let* ((drawer-end-line (match-beginning 0)) + (begin (car affiliated)) + (post-affiliated (point)) + (contents-begin + (progn + (forward-line) + (and (re-search-forward org-property-re drawer-end-line t) + (line-beginning-position)))) + (contents-end (and contents-begin drawer-end-line)) + (hidden (org-invisible-p2)) + (pos-before-blank (progn (goto-char drawer-end-line) + (forward-line) + (point))) + (end (progn (skip-chars-forward " \r\t\n" limit) + (if (eobp) (point) (line-beginning-position))))) + (list 'property-drawer + (nconc + (list :begin begin + :end end + :hiddenp hidden + :contents-begin contents-begin + :contents-end contents-end + :post-blank (count-lines pos-before-blank end) + :post-affiliated post-affiliated) + (cdr affiliated)))))))) (defun org-element-property-drawer-interpreter (property-drawer contents) "Interpret PROPERTY-DRAWER element as Org syntax. @@ -2099,28 +2096,28 @@ LIMIT bounds the search. Return a list whose CAR is `node-property' and CDR is a plist containing `:key', `:value', `:begin', `:end' and `:post-blank' keywords." - (save-excursion - (looking-at org-property-re) - (let ((case-fold-search t) - (begin (point)) - (key (org-match-string-no-properties 2)) - (value (org-match-string-no-properties 3)) - (pos-before-blank (progn (forward-line) (point))) - (end (progn (skip-chars-forward " \r\t\n" limit) - (if (eobp) (point) (point-at-bol))))) - (list 'node-property - (list :key key - :value value - :begin begin - :end end - :post-blank (count-lines pos-before-blank end)))))) + (looking-at org-property-re) + (let ((begin (point)) + (key (org-match-string-no-properties 2)) + (value (org-match-string-no-properties 3)) + (end (save-excursion + (end-of-line) + (if (re-search-forward org-property-re limit t) + (line-beginning-position) + limit)))) + (list 'node-property + (list :key key + :value value + :begin begin + :end end + :post-blank 0)))) (defun org-element-node-property-interpreter (node-property contents) "Interpret NODE-PROPERTY element as Org syntax. CONTENTS is nil." (format org-property-format (format ":%s:" (org-element-property :key node-property)) - (org-element-property :value node-property))) + (or (org-element-property :value node-property) ""))) ;;;; Paragraph @@ -2486,7 +2483,7 @@ Assume point is at the beginning of the table." (defun org-element-table-interpreter (table contents) "Interpret TABLE element as Org syntax. -CONTENTS is nil." +CONTENTS is a string, if table's type is `org', or nil." (if (eq (org-element-property :type table) 'table.el) (org-remove-indentation (org-element-property :value table)) (concat (with-temp-buffer (insert contents) @@ -3112,16 +3109,20 @@ Assume point is at the beginning of the link." (cond ;; File type. ((or (file-name-absolute-p raw-link) - (string-match "^\\.\\.?/" raw-link)) + (string-match "\\`\\.\\.?/" raw-link)) (setq type "file" path raw-link)) ;; Explicit type (http, irc, bbdb...). See `org-link-types'. - ((string-match org-link-re-with-space3 raw-link) - (setq type (match-string 1 raw-link) path (match-string 2 raw-link))) + ((string-match org-link-types-re raw-link) + (setq type (match-string 1 raw-link) + ;; According to RFC 3986, extra whitespace should be + ;; ignored when a URI is extracted. + path (replace-regexp-in-string + "[ \t]*\n[ \t]*" "" (substring raw-link (match-end 0))))) ;; Id type: PATH is the id. - ((string-match "^id:\\([-a-f0-9]+\\)" raw-link) + ((string-match "\\`id:\\([-a-f0-9]+\\)" raw-link) (setq type "id" path (match-string 1 raw-link))) ;; Code-ref type: PATH is the name of the reference. - ((string-match "^(\\(.*\\))$" raw-link) + ((string-match "\\`(\\(.*\\))\\'" raw-link) (setq type "coderef" path (match-string 1 raw-link))) ;; Custom-id type: PATH is the name of the custom id. ((= (aref raw-link 0) ?#) @@ -3541,7 +3542,7 @@ Return a list whose CAR is `timestamp', and CDR a plist with `:month-end', `:day-end', `:hour-end', `:minute-end', `:repeater-type', `:repeater-value', `:repeater-unit', `:warning-type', `:warning-value', `:warning-unit', `:begin', -`:end', `:value' and `:post-blank' keywords. +`:end' and `:post-blank' keywords. Assume point is at the beginning of the timestamp." (save-excursion @@ -3890,8 +3891,7 @@ element it has to parse." (goto-char (car affiliated)) (org-element-keyword-parser limit nil)) ;; LaTeX Environment. - ((looking-at - "[ \t]*\\\\begin{[A-Za-z0-9*]+}\\(\\[.*?\\]\\|{.*?}\\)*[ \t]*$") + ((looking-at "[ \t]*\\\\begin{\\([A-Za-z0-9]+\\*?\\)}\\(\\[.*?\\]\\|{.*?}\\)*[ \t]*$") (org-element-latex-environment-parser limit affiliated)) ;; Drawer and Property Drawer. ((looking-at org-drawer-regexp) @@ -4090,21 +4090,18 @@ looked after. Optional argument PARENT, when non-nil, is the element or object containing the secondary string. It is used to set correctly `:parent' property within the string." - ;; Copy buffer-local variables listed in - ;; `org-element-object-variables' into temporary buffer. This is - ;; required since object parsing is dependent on these variables. - (let ((pairs (delq nil (mapcar (lambda (var) - (when (boundp var) - (cons var (symbol-value var)))) - org-element-object-variables)))) + (let ((local-variables (buffer-local-variables))) (with-temp-buffer - (mapc (lambda (pair) (org-set-local (car pair) (cdr pair))) pairs) + (dolist (v local-variables) + (ignore-errors + (if (symbolp v) (makunbound v) + (org-set-local (car v) (cdr v))))) (insert string) + (restore-buffer-modified-p nil) (let ((secondary (org-element--parse-objects (point-min) (point-max) nil restriction))) (when parent - (mapc (lambda (obj) (org-element-put-property obj :parent parent)) - secondary)) + (dolist (o secondary) (org-element-put-property o :parent parent))) secondary)))) (defun org-element-map @@ -4617,29 +4614,29 @@ indentation is not done with TAB characters." (let* ((min-ind most-positive-fixnum) find-min-ind ; For byte-compiler. (find-min-ind - (function - ;; Return minimal common indentation within BLOB. This is - ;; done by walking recursively BLOB and updating MIN-IND - ;; along the way. FIRST-FLAG is non-nil when the first - ;; string hasn't been seen yet. It is required as this - ;; string is the only one whose indentation doesn't happen - ;; after a newline character. - (lambda (blob first-flag) - (dolist (object (org-element-contents blob)) - (when (and first-flag (stringp object)) - (setq first-flag nil) - (string-match "\\`\\( *\\)" object) - (let ((len (length (match-string 1 object)))) - ;; An indentation of zero means no string will be - ;; modified. Quit the process. - (if (zerop len) (throw 'zero (setq min-ind 0)) - (setq min-ind (min len min-ind))))) - (cond - ((stringp object) - (dolist (line (delq "" (cdr (org-split-string object " *\n")))) - (setq min-ind (min (org-get-indentation line) min-ind)))) - ((memq (org-element-type object) org-element-recursive-objects) - (funcall find-min-ind object first-flag)))))))) + ;; Return minimal common indentation within BLOB. This is + ;; done by walking recursively BLOB and updating MIN-IND + ;; along the way. FIRST-FLAG is non-nil when the first + ;; string hasn't been seen yet. It is required as this + ;; string is the only one whose indentation doesn't happen + ;; after a newline character. + (lambda (blob first-flag) + (dolist (object (org-element-contents blob)) + (when (and first-flag (stringp object)) + (setq first-flag nil) + (string-match "\\` *" object) + (let ((len (match-end 0))) + ;; An indentation of zero means no string will be + ;; modified. Quit the process. + (if (zerop len) (throw 'zero (setq min-ind 0)) + (setq min-ind (min len min-ind))))) + (cond + ((stringp object) + (dolist (line (cdr (org-split-string object " *\n"))) + (unless (string= line "") + (setq min-ind (min (org-get-indentation line) min-ind))))) + ((memq (org-element-type object) org-element-recursive-objects) + (funcall find-min-ind object first-flag))))))) ;; Find minimal indentation in ELEMENT. (catch 'zero (funcall find-min-ind element (not ignore-first))) (if (or (zerop min-ind) (= min-ind most-positive-fixnum)) element diff --git a/lisp/org/org-entities.el b/lisp/org/org-entities.el index ba1eed12bdb..6324a625dbd 100644 --- a/lisp/org/org-entities.el +++ b/lisp/org/org-entities.el @@ -27,9 +27,8 @@ ;;; Code: -(require 'org-macs) - -(declare-function org-table-align "org-table" ()) +(declare-function org-toggle-pretty-entities "org" ()) +(declare-function org-table-align "org-table" ()) (eval-when-compile (require 'cl)) @@ -568,6 +567,7 @@ Kind can be any of `latex', `html', `ascii', `latin1', or `utf8'." (goto-char pos) (org-table-align))) +(defvar org-pretty-entities) ;; declare defcustom from org (defun org-entities-help () "Create a Help buffer with all available entities." (interactive) diff --git a/lisp/org/org-habit.el b/lisp/org/org-habit.el index 721718d2b6c..60137568c00 100644 --- a/lisp/org/org-habit.el +++ b/lisp/org/org-habit.el @@ -351,14 +351,7 @@ current time." (let ((inhibit-read-only t) l c (buffer-invisibility-spec '(org-link)) (moment (time-subtract (current-time) - (list 0 (* 3600 org-extend-today-until) 0))) - disabled-overlays) - ;; Disable filters; this helps with alignment if there are links. - (mapc (lambda (ol) - (when (overlay-get ol 'invisible) - (overlay-put ol 'invisible nil) - (setq disabled-overlays (cons ol disabled-overlays)))) - (overlays-in (point-min) (point-max))) + (list 0 (* 3600 org-extend-today-until) 0)))) (save-excursion (goto-char (if line (point-at-bol) (point-min))) (while (not (eobp)) @@ -374,9 +367,7 @@ current time." (time-subtract moment (days-to-time org-habit-preceding-days)) moment (time-add moment (days-to-time org-habit-following-days)))))) - (forward-line))) - (mapc (lambda (ol) (overlay-put ol 'invisible t)) - disabled-overlays))) + (forward-line))))) (defun org-habit-toggle-habits () "Toggle display of habits in an agenda buffer." diff --git a/lisp/org/org-list.el b/lisp/org/org-list.el index d24dad28363..a00e557371c 100644 --- a/lisp/org/org-list.el +++ b/lisp/org/org-list.el @@ -1254,7 +1254,7 @@ some heuristics to guess the result." If POS is before first character after bullet of the item, the new item will be created before the current one. -STRUCT is the list structure. PREVS is the the alist of previous +STRUCT is the list structure. PREVS is the alist of previous items, as returned by `org-list-prevs-alist'. Insert a checkbox if CHECKBOX is non-nil, and string AFTER-BULLET @@ -2237,7 +2237,7 @@ item is invisible." t))))) (defun org-list-repair () - "Fix indentation, bullets and checkboxes is the list at point." + "Fix indentation, bullets and checkboxes in the list at point." (interactive) (unless (org-at-item-p) (error "This is not a list")) (let* ((struct (org-list-struct)) diff --git a/lisp/org/org-macs.el b/lisp/org/org-macs.el index ddd6e2e90f5..96265ec02fe 100644 --- a/lisp/org/org-macs.el +++ b/lisp/org/org-macs.el @@ -154,9 +154,9 @@ We use a macro so that the test can happen at compilation time." `(let ((,mpom ,pom)) (save-excursion (if (markerp ,mpom) (set-buffer (marker-buffer ,mpom))) - (save-excursion - (goto-char (or ,mpom (point))) - ,@body))))) + (org-with-wide-buffer + (goto-char (or ,mpom (point))) + ,@body))))) (def-edebug-spec org-with-point-at (form body)) (put 'org-with-point-at 'lisp-indent-function 1) diff --git a/lisp/org/org-mobile.el b/lisp/org/org-mobile.el index f59d1c47911..41a99586742 100644 --- a/lisp/org/org-mobile.el +++ b/lisp/org/org-mobile.el @@ -1074,7 +1074,7 @@ be returned that indicates what went wrong." ;; which prevents correct insertion when point is invisible (org-show-subtree) (end-of-line 1) - (org-insert-heading-respect-content '(16) t) + (org-insert-heading-respect-content t) (org-demote)) (beginning-of-line) (insert "* ")) diff --git a/lisp/org/org-mouse.el b/lisp/org/org-mouse.el index 27dc0e070fc..74046c73fe3 100644 --- a/lisp/org/org-mouse.el +++ b/lisp/org/org-mouse.el @@ -953,20 +953,23 @@ This means, between the beginning of line and the point." (point) (save-excursion (goto-char start) (org-back-to-heading) (point)))) - (outline-end-of-subtree) + (progn (org-end-of-subtree nil t) + (unless (eobp) (backward-char))) (end-of-line) (if (eobp) (newline) (forward-char))) (when (looking-at org-outline-regexp) (let ((level (- (match-end 0) (match-beginning 0)))) (when (> end (match-end 0)) - (outline-end-of-subtree) + (progn (org-end-of-subtree nil t) + (unless (eobp) (backward-char))) (end-of-line) (if (eobp) (newline) (forward-char)) (setq level (1+ level))) (org-paste-subtree level) (save-excursion - (outline-end-of-subtree) + (progn (org-end-of-subtree nil t) + (unless (eobp) (backward-char))) (when (bolp) (delete-char -1)))))))))) @@ -1003,8 +1006,8 @@ This means, between the beginning of line and the point." (org-mouse-main-buffer (current-buffer))) (when (eq (with-current-buffer buffer major-mode) 'org-mode) (let ((endmarker (with-current-buffer buffer - (outline-end-of-subtree) - (forward-char 1) + (org-end-of-subtree nil t) + (unless (eobp) (forward-char 1)) (copy-marker (point))))) (org-with-remote-undo buffer (with-current-buffer buffer diff --git a/lisp/org/org-src.el b/lisp/org/org-src.el index f870b2c714d..752fa30bd12 100644 --- a/lisp/org/org-src.el +++ b/lisp/org/org-src.el @@ -376,23 +376,21 @@ the display of windows containing the Org buffer and the code buffer." (when (fboundp edit-prep-func) (funcall edit-prep-func full-info))) (or org-edit-src-code-timer + (zerop org-edit-src-auto-save-idle-delay) (setq org-edit-src-code-timer - (unless (zerop org-edit-src-auto-save-idle-delay) - (run-with-idle-timer - org-edit-src-auto-save-idle-delay t - (lambda () - (cond - ((and (string-match "\*Org Src" (buffer-name)) - (buffer-modified-p)) - (org-edit-src-save)) - ((not - (delq nil (mapcar - (lambda (b) - (string-match "\*Org Src" (buffer-name b))) - (buffer-list)))) - (cancel-timer org-edit-src-code-timer) - (setq org-edit-src-code-timer))))))))) - t))) + (run-with-idle-timer + org-edit-src-auto-save-idle-delay t + (lambda () + (cond + ((org-string-match-p "\\`\\*Org Src" (buffer-name)) + (when (buffer-modified-p) (org-edit-src-save))) + ((not (org-some (lambda (b) + (org-string-match-p "\\`\\*Org Src" + (buffer-name b))) + (buffer-list))) + (cancel-timer org-edit-src-code-timer) + (setq org-edit-src-code-timer nil)))))))) + t))) (defun org-edit-src-continue (e) "Continue editing source blocks." ;; Fixme: be more accurate @@ -757,8 +755,8 @@ with \",*\", \",#+\", \",,*\" and \",,#+\"." (delete-region beg (max beg end)) (unless (string-match "\\`[ \t]*\\'" code) (insert code)) - ;; Make sure the overlay stays in place - (when (eq context 'save) (move-overlay ovl beg (point))) + ;; Make sure the overlay stays in place + (when (eq context 'save) (move-overlay ovl beg (point))) (goto-char beg) (if single (just-one-space))) (if (memq t (mapcar (lambda (overlay) @@ -774,9 +772,6 @@ with \",*\", \",#+\", \",,*\" and \",,#+\"." (unless (eq context 'save) (move-marker beg nil) (move-marker end nil))) - (when org-edit-src-code-timer - (cancel-timer org-edit-src-code-timer) - (setq org-edit-src-code-timer nil)) (unless (eq context 'save) (when org-edit-src-saved-temp-window-config (set-window-configuration org-edit-src-saved-temp-window-config) diff --git a/lisp/org/org-table.el b/lisp/org/org-table.el index c9522341106..30a66c9c234 100644 --- a/lisp/org/org-table.el +++ b/lisp/org/org-table.el @@ -2712,7 +2712,8 @@ not overwrite the stored one." (or (fboundp 'calc-eval) (user-error "Calc does not seem to be installed, and is needed to evaluate the formula")) ;; Use <...> time-stamps so that Calc can handle them - (setq form (replace-regexp-in-string org-ts-regexp3 "<\\1>" form)) + (while (string-match (concat "\\[" org-ts-regexp1 "\\]") form) + (setq form (replace-match "<\\1>" nil nil form))) ;; I18n-ize local time-stamps by setting (system-time-locale "C") (when (string-match org-ts-regexp2 form) (let* ((ts (match-string 0 form)) @@ -3862,9 +3863,10 @@ With prefix ARG, apply the new formulas to the table." (push org-table-current-begin-pos org-show-positions) (let ((min (apply 'min org-show-positions)) (max (apply 'max org-show-positions))) - (goto-char min) (recenter 0) + (set-window-start (selected-window) min) (goto-char max) - (or (pos-visible-in-window-p max) (recenter -1)))) + (or (pos-visible-in-window-p max) + (set-window-start (selected-window) max)))) (select-window win)))) (defun org-table-force-dataline () diff --git a/lisp/org/org-timer.el b/lisp/org/org-timer.el index 1a86ffa7488..8161699f316 100644 --- a/lisp/org/org-timer.el +++ b/lisp/org/org-timer.el @@ -186,7 +186,10 @@ it in the buffer." (insert (org-timer-value-string)))) (defun org-timer-value-string () - (format org-timer-format (org-timer-secs-to-hms (floor (org-timer-seconds))))) + "Set the timer string." + (format org-timer-format + (org-timer-secs-to-hms + (abs (floor (org-timer-seconds)))))) (defvar org-timer-timer-is-countdown nil) (defun org-timer-seconds () diff --git a/lisp/org/org-version.el b/lisp/org/org-version.el index 4909d45530a..b96025785c2 100644 --- a/lisp/org/org-version.el +++ b/lisp/org/org-version.el @@ -5,13 +5,13 @@ (defun org-release () "The release version of org-mode. Inserted by installing org-mode or when a release is made." - (let ((org-release "8.2.6")) + (let ((org-release "8.2.8")) org-release)) ;;;###autoload (defun org-git-version () "The Git version of org-mode. Inserted by installing org-mode or when a release is made." - (let ((org-git-version "release_8.2.6-1")) + (let ((org-git-version "release_8.2.8")) org-git-version)) (provide 'org-version) diff --git a/lisp/org/org.el b/lisp/org/org.el index 2a451ed5456..c42102cac37 100644 --- a/lisp/org/org.el +++ b/lisp/org/org.el @@ -111,6 +111,8 @@ Stars are put in group 1 and the trimmed body in group 2.") (unless (boundp 'diary-fancy-buffer) (org-defvaralias 'diary-fancy-buffer 'fancy-diary-buffer)) +(declare-function org-add-archive-files "org-archive" (files)) + (declare-function org-inlinetask-at-task-p "org-inlinetask" ()) (declare-function org-inlinetask-outline-regexp "org-inlinetask" ()) (declare-function org-inlinetask-toggle-visibility "org-inlinetask" ()) @@ -118,7 +120,10 @@ Stars are put in group 1 and the trimmed body in group 2.") (declare-function org-clock-get-last-clock-out-time "org-clock" ()) (declare-function org-clock-timestamps-up "org-clock" (&optional n)) (declare-function org-clock-timestamps-down "org-clock" (&optional n)) +(declare-function org-clock-remove-overlays "org-clock" (&optional beg end noremove)) (declare-function org-clock-sum-current-item "org-clock" (&optional tstart)) +(declare-function org-clock-update-time-maybe "org-clock" ()) +(declare-function org-clocktable-shift "org-clock" (dir n)) (declare-function orgtbl-mode "org-table" (&optional arg)) (declare-function org-clock-out "org-clock" (&optional switch-to-state fail-quietly at-time)) @@ -133,6 +138,10 @@ Stars are put in group 1 and the trimmed body in group 2.") (declare-function org-agenda-list "org-agenda" (&optional arg start-day span)) (declare-function org-agenda-redo "org-agenda" (&optional all)) (declare-function org-table-align "org-table" ()) +(declare-function org-table-begin "org-table" (&optional table-type)) +(declare-function org-table-blank-field "org-table" ()) +(declare-function org-table-end "org-table" (&optional table-type)) +(declare-function org-table-insert-row "org-table" (&optional arg)) (declare-function org-table-paste-rectangle "org-table" ()) (declare-function org-table-maybe-eval-formula "org-table" ()) (declare-function org-table-maybe-recalculate-line "org-table" ()) @@ -179,6 +188,7 @@ Stars are put in group 1 and the trimmed body in group 2.") (intern (concat "org-babel-expand-body:" lang))))))) org-babel-load-languages)) +(declare-function org-babel-tangle-file "ob-tangle" (file &optional target-file lang)) ;;;###autoload (defun org-babel-load-file (file &optional compile) "Load Emacs Lisp source code blocks in the Org-mode FILE. @@ -5109,9 +5119,9 @@ Support for group tags is controlled by the option "\\(?: +\\(\\[#.\\]\\)\\)?" "\\(?: +" ;; Stats cookies can be stuck to body. - "\\(?:\\[[0-9%%/]+\\] *\\)?" + "\\(?:\\[[0-9%%/]+\\] *\\)*" "\\(%s\\)" - "\\(?: *\\[[0-9%%/]+\\]\\)?" + "\\(?: *\\[[0-9%%/]+\\]\\)*" "\\)" (org-re "\\(?:[ \t]+\\(:[[:alnum:]_@#%%:]+:\\)\\)?") "[ \t]*$") @@ -5417,8 +5427,7 @@ The following commands are available: (org-add-hook 'isearch-mode-end-hook 'org-isearch-end 'append 'local) ;; Emacs 22 deals with this through a special variable (org-set-local 'outline-isearch-open-invisible-function - (lambda (&rest ignore) (org-show-context 'isearch))) - (org-add-hook 'isearch-mode-end-hook 'org-fix-ellipsis-at-bol 'append 'local)) + (lambda (&rest ignore) (org-show-context 'isearch)))) ;; Setup the pcomplete hooks (set (make-local-variable 'pcomplete-command-completion-function) @@ -5473,9 +5482,6 @@ The following commands are available: (put 'org-mode 'flyspell-mode-predicate 'org-mode-flyspell-verify) -(defsubst org-fix-ellipsis-at-bol () - (save-excursion (goto-char (window-start)) (recenter 0))) - (defun org-find-invisible-foreground () (let ((candidates (remove "unspecified-bg" @@ -5881,7 +5887,7 @@ by a #." ((member dc1 '("+title:" "+author:" "+email:" "+date:")) (add-text-properties beg (match-end 3) - (if (member (intern (substring dc1 0 -1)) org-hidden-keywords) + (if (member (intern (substring dc1 1 -1)) org-hidden-keywords) '(font-lock-fontified t invisible t) '(font-lock-fontified t face org-document-info-keyword))) (add-text-properties @@ -6145,15 +6151,25 @@ Use `org-reduced-level' to remove the effect of `org-odd-levels'." (defvar org-font-lock-keywords nil) -(defsubst org-re-property (property &optional literal) +(defsubst org-re-property (property &optional literal allow-null) "Return a regexp matching a PROPERTY line. -Match group 3 will be set to the value if it exists." - (concat "^\\(?4:[ \t]*\\)\\(?1::\\(?2:" - (if literal property (regexp-quote property)) - "\\):\\)[ \t]+\\(?3:[^ \t\r\n].*?\\)\\(?5:[ \t]*\\)$")) + +When optional argument LITERAL is non-nil, do not quote PROPERTY. +This is useful when PROPERTY is a regexp. When ALLOW-NULL is +non-nil, match properties even without a value. + +Match group 3 is set to the value when it exists. If there is no +value and ALLOW-NULL is non-nil, it is set to the empty string." + (concat + "^\\(?4:[ \t]*\\)" + (format "\\(?1::\\(?2:%s\\):\\)" + (if literal property (regexp-quote property))) + (if allow-null + "\\(?:\\(?3:$\\)\\|[ \t]+\\(?3:.*?\\)\\)\\(?5:[ \t]*\\)$" + "[ \t]+\\(?3:[^ \r\t\n]+.*?\\)\\(?5:[ \t]*\\)$"))) (defconst org-property-re - (org-re-property ".*?" 'literal) + (org-re-property ".*?" 'literal t) "Regular expression matching a property line. There are four matching groups: 1: :PROPKEY: including the leading and trailing colon, @@ -6712,7 +6728,8 @@ in special contexts. (setq org-cycle-global-status 'overview) (run-hook-with-args 'org-cycle-hook 'overview))))) -(defvar org-called-with-limited-levels);Dyn-bound in ̀org-with-limited-levels'. +(defvar org-called-with-limited-levels nil + "Non-nil when `org-with-limited-levels' is currently active.") (defun org-cycle-internal-local () "Do the local cycling action." @@ -6729,7 +6746,8 @@ in special contexts. (setq has-children (org-list-has-child-p (point) struct))) (org-back-to-heading) (setq eoh (save-excursion (outline-end-of-heading) (point))) - (setq eos (save-excursion (1- (org-end-of-subtree t t)))) + (setq eos (save-excursion (org-end-of-subtree t t) + (when (bolp) (backward-char)) (point))) (setq has-children (or (save-excursion (let ((level (funcall outline-level))) @@ -6894,21 +6912,20 @@ With a numeric prefix, show all headlines up to that level." ;; buffers, where outline-regexp is needed. (defun org-overview () "Switch to overview mode, showing only top-level headlines. -Really, this shows all headlines with level equal or greater than the level +This shows all headlines with a level equal or greater than the level of the first headline in the buffer. This is important, because if the first headline is not level one, then (hide-sublevels 1) gives confusing results." (interactive) - (let ((pos (point)) - (level (save-excursion - (goto-char (point-min)) - (if (re-search-forward (concat "^" outline-regexp) nil t) - (progn - (goto-char (match-beginning 0)) - (funcall outline-level)))))) - (and level (hide-sublevels level)) - (recenter '(4)) - (goto-char pos))) + (save-excursion + (let ((level + (save-excursion + (goto-char (point-min)) + (if (re-search-forward (concat "^" outline-regexp) nil t) + (progn + (goto-char (match-beginning 0)) + (funcall outline-level)))))) + (and level (hide-sublevels level))))) (defun org-content (&optional arg) "Show all headlines in the buffer, like a table of contents. @@ -7105,13 +7122,11 @@ Otherwise make it visible." (pos-visible-in-window-p (save-excursion (org-end-of-subtree t) (point)))) -(defun org-first-headline-recenter (&optional N) - "Move cursor to the first headline and recenter the headline. -Optional argument N means put the headline into the Nth line of the window." +(defun org-first-headline-recenter () + "Move cursor to the first headline and recenter the headline." (goto-char (point-min)) (when (re-search-forward (concat "^\\(" org-outline-regexp "\\)") nil t) - (beginning-of-line) - (recenter (prefix-numeric-value N)))) + (set-window-start (selected-window) (point-at-bol)))) ;;; Saving and restoring visibility @@ -7545,23 +7560,22 @@ When NEXT is non-nil, check the next line instead." (looking-at "[ \t]*$"))))) (defun org-insert-heading (&optional arg invisible-ok) - "Insert a new heading or item with same depth at point. + "Insert a new heading or an item with the same depth at point. If point is at the beginning of a heading or a list item, insert -a heading or a list item before it. - -If point is at the beginning of a normal line, turn this line -into a heading. +a new heading or a new item above the current one. If point is +at the beginning of a normal line, turn the line into a heading. If point is in the middle of a headline or a list item, split the headline or the item and create a new headline/item with the text in the current line after point \(see `org-M-RET-may-split-line' on how to modify this behavior). -With one universal prefix argument: If point is within a list, -insert a heading instead of a list item. Otherwise, set the -value of `org-insert-heading-respect-content' to `t' for the -duration of the command. +With one universal prefirx argument, set the user option +`org-insert-heading-respect-content' to t for the duration of +the command. This modifies the behavior described above in this +ways: on list items and at the beginning of normal lines, force +the insertion of a heading after the current subtree. With two universal prefix arguments, insert the heading at the end of the grandparent subtree. For example, if point is within @@ -7589,12 +7603,19 @@ command." (or arg (not itemp)))) ;; At beginning of buffer or so high up that only a heading ;; makes sense. - (insert - (if (or (bobp) (org-previous-line-empty-p)) "" "\n") - (if (org-in-src-block-p) ",* " "* ")) + (cond ((and (bolp) (not respect-content)) (insert "* ")) + ((not respect-content) + (unless may-split (end-of-line)) + (insert "\n* ")) + ((re-search-forward org-outline-regexp-bol nil t) + (beginning-of-line) + (insert "* \n") + (backward-char)) + (t (goto-char (point-max)) + (insert "\n* "))) (run-hooks 'org-insert-heading-hook)) - ((and itemp (not (equal arg '(4)))) + ((and itemp (not (member arg '((4) (16))))) ;; Insert an item (org-insert-item)) @@ -7614,11 +7635,12 @@ command." nil)) ;; Get a level string to fall back on (fix-level - (save-excursion - (org-back-to-heading t) - (if (org-previous-line-empty-p) (setq empty-line-p t)) - (looking-at org-outline-regexp) - (make-string (1- (length (match-string 0))) ?*))) + (if (org-before-first-heading-p) "*" + (save-excursion + (org-back-to-heading t) + (if (org-previous-line-empty-p) (setq empty-line-p t)) + (looking-at org-outline-regexp) + (make-string (1- (length (match-string 0))) ?*)))) (stars (save-excursion (condition-case nil @@ -7650,8 +7672,12 @@ command." pos hide-previous previous-pos) ;; If we insert after content, move there and clean up whitespace - (when (and respect-content (not (org-on-heading-p))) - (org-end-of-subtree nil t) + (when (and respect-content + (not (org-looking-at-p org-outline-regexp-bol))) + (if (not (org-before-first-heading-p)) + (org-end-of-subtree nil t) + (re-search-forward org-outline-regexp-bol) + (beginning-of-line 0)) (skip-chars-backward " \r\n") (and (not (looking-back "^\*+")) (looking-at "[ \t]+") (replace-match "")) @@ -7680,10 +7706,9 @@ command." (setq initial-content (org-trim initial-content))) (goto-char pos)) ;; a normal line - (unless (bolp) - (setq initial-content (buffer-substring (point) (point-at-eol))) - (delete-region (point) (point-at-eol)) - (setq initial-content (org-trim initial-content))))) + (setq initial-content + (org-trim (buffer-substring (point) (point-at-eol)))) + (delete-region (point) (point-at-eol)))) ;; If we are at the beginning of the line, insert before it. Else after (cond @@ -7708,13 +7733,12 @@ command." "Make the number of empty lines before current exactly N. So this will delete or add empty lines." (save-excursion - (goto-char (point-at-bol)) - (if (looking-back "\\s-+" nil 'greedy) - (replace-match "")) - (or (bobp) (insert "\n")) - (while (> N 0) - (insert "\n") - (setq N (1- N))))) + (beginning-of-line) + (let ((p (point))) + (skip-chars-backward " \r\t\n") + (unless (bolp) (forward-line)) + (delete-region (point) p)) + (when (> N 0) (insert (make-string N ?\n))))) (defun org-get-heading (&optional no-tags no-todo) "Return the heading of the current entry, without the stars. @@ -7783,17 +7807,15 @@ This is a list with the following elements: (org-move-subtree-down) (end-of-line 1)) -(defun org-insert-heading-respect-content (&optional arg invisible-ok) +(defun org-insert-heading-respect-content (&optional invisible-ok) "Insert heading with `org-insert-heading-respect-content' set to t." - (interactive "P") - (let ((org-insert-heading-respect-content t)) - (org-insert-heading '(4) invisible-ok))) + (interactive) + (org-insert-heading '(4) invisible-ok)) (defun org-insert-todo-heading-respect-content (&optional force-state) "Insert TODO heading with `org-insert-heading-respect-content' set to t." - (interactive "P") - (let ((org-insert-heading-respect-content t)) - (org-insert-todo-heading force-state '(4)))) + (interactive) + (org-insert-todo-heading force-state '(4))) (defun org-insert-todo-heading (arg &optional force-heading) "Insert a new heading with the same level and TODO state as current heading. @@ -8150,7 +8172,8 @@ case." (save-match-data (save-excursion (outline-end-of-heading) (setq folded (outline-invisible-p))) - (outline-end-of-subtree)) + (progn (org-end-of-subtree nil t) + (unless (eobp) (backward-char)))) (outline-next-heading) (setq ne-end (org-back-over-empty-lines)) (setq end (point)) @@ -8303,7 +8326,7 @@ the inserted text when done." (string-match "^\\*+$" (buffer-substring (point-at-bol) (point)))) - (- (match-end 1) (match-beginning 1))) + (- (match-end 0) (match-beginning 0))) ((and (bolp) (looking-at org-outline-regexp)) (- (match-end 0) (point) 1)))) @@ -10592,6 +10615,10 @@ application the system uses for this file type." (move-marker org-open-link-marker nil) (run-hook-with-args 'org-follow-link-hook))) +(defsubst org-uniquify (list) + "Non-destructively remove duplicate elements from LIST." + (let ((res (copy-sequence list))) (delete-dups res))) + (defun org-offer-links-in-entry (buffer marker &optional nth zero) "Offer links in the current entry and return the selected link. If there is only one link, return it. @@ -13640,8 +13667,7 @@ How much context is shown depends upon the variables (error nil)) (not (bobp))) (org-flag-heading nil) - (when siblings-p (org-show-siblings))))) - (unless (eq key 'agenda) (org-fix-ellipsis-at-bol)))) + (when siblings-p (org-show-siblings))))))) (defvar org-reveal-start-hook nil "Hook run before revealing a location.") @@ -13836,7 +13862,7 @@ a file becomes an N^2 operation - but with this variable set, it scales as N.") (defun org-scan-tags (action matcher todo-only &optional start-level) - "Sca headline tags with inheritance and produce output ACTION. + "Scan headline tags with inheritance and produce output ACTION. ACTION can be `sparse-tree' to produce a sparse tree in the current buffer, or `agenda' to produce an entry list for an agenda view. It can also be @@ -14744,8 +14770,8 @@ Returns the new tags string, or nil to not change the current settings." (if expert (set-buffer (get-buffer-create " *Org tags*")) (delete-other-windows) - (split-window-vertically) - (org-switch-to-buffer-other-window (get-buffer-create " *Org tags*"))) + (set-window-buffer (split-window-vertically) (get-buffer-create " *Org tags*")) + (org-switch-to-buffer-other-window " *Org tags*")) (erase-buffer) (org-set-local 'org-done-keywords done-keywords) (org-fast-tag-insert "Inherited" inherited i-face "\n") @@ -15269,7 +15295,10 @@ things up because then unnecessary parsing is avoided." '("SCHEDULED" "DEADLINE" "CLOCK" "CLOSED" "TIMESTAMP" "TIMESTAMP_IA"))) (catch 'match - (while (re-search-forward org-maybe-keyword-time-regexp end t) + (while (and (re-search-forward org-maybe-keyword-time-regexp end t) + (not (text-property-any 0 (length (match-string 0)) + 'face 'font-lock-comment-face + (match-string 0)))) (setq key (if (match-end 1) (substring (org-match-string-no-properties 1) 0 -1)) @@ -15397,7 +15426,7 @@ an empty drawer to delete." (if (and range (goto-char (car range)) (re-search-forward - (org-re-property property) + (org-re-property property nil t) (cdr range) t)) (progn (delete-region (match-beginning 0) (1+ (point-at-eol))) @@ -15562,7 +15591,7 @@ If it is not a string, an error is raised." (setq range (org-get-property-block beg end 'force)) (goto-char (car range)) (if (re-search-forward - (org-re-property property) (cdr range) t) + (org-re-property property nil t) (cdr range) t) (progn (delete-region (match-beginning 0) (match-end 0)) (goto-char (match-beginning 0))) @@ -15773,9 +15802,7 @@ This is computed according to `org-property-set-functions-alist'." (funcall set-function prompt (mapcar 'list (org-property-values property)) nil nil "" nil cur))))) - (if (equal val "") - cur - val))) + (org-trim val))) (defvar org-last-set-property nil) (defvar org-last-set-property-value nil) @@ -15853,8 +15880,10 @@ an empty drawer to delete." (org-icompleting-read "Property: " props nil t) (caar props)))) (list prop))) - (if (org-entry-delete nil property delete-empty-drawer) - (message "Property %s deleted" property))) + (if (not property) + (message "No property to delete in this entry") + (org-entry-delete nil property delete-empty-drawer) + (message "Property \"%s\" deleted" property))) (defun org-delete-property-globally (property) "Remove PROPERTY globally, from all entries." @@ -17743,9 +17772,9 @@ This requires Emacs >= 24.1, build with imagemagick support." (defcustom org-agenda-inhibit-startup nil "Inhibit startup when preparing agenda buffers. -When this variable is `t' (the default), the initialization of -the Org agenda buffers is inhibited: e.g. the visibility state -is not set, the tables are not re-aligned, etc." +When this variable is `t', the initialization of the Org agenda +buffers is inhibited: e.g. the visibility state is not set, the +tables are not re-aligned, etc." :type 'boolean :version "24.3" :group 'org-agenda) @@ -21819,9 +21848,7 @@ for the search purpose." "Return the reverse of STRING." (apply 'string (reverse (string-to-list string)))) -(defsubst org-uniquify (list) - "Non-destructively remove duplicate elements from LIST." - (let ((res (copy-sequence list))) (delete-dups res))) +;; defsubst org-uniquify must be defined before first use (defun org-uniquify-alist (alist) "Merge elements of ALIST with the same key. @@ -23273,14 +23300,6 @@ If there is no such heading, return nil." (forward-char -1)))))) (point)) -(defadvice outline-end-of-subtree (around prefer-org-version activate compile) - "Use Org version in org-mode, for dramatic speed-up." - (if (derived-mode-p 'org-mode) - (progn - (org-end-of-subtree nil t) - (unless (eobp) (backward-char 1))) - ad-do-it)) - (defun org-end-of-meta-data-and-drawers () "Jump to the first text after meta data and drawers in the current entry. This will move over empty lines, lines with planning time stamps, @@ -23777,8 +23796,7 @@ Show the heading too, if it is currently invisible." isearch-mode-end-hook-quit) ;; Only when the isearch was not quitted. (org-add-hook 'post-command-hook 'org-isearch-post-command - 'append 'local))) - (org-fix-ellipsis-at-bol))) + 'append 'local))))) (defun org-isearch-post-command () "Remove self from hook, and show context." diff --git a/lisp/org/ox-ascii.el b/lisp/org/ox-ascii.el index 6208cdbe065..cd2a9af10ac 100644 --- a/lisp/org/ox-ascii.el +++ b/lisp/org/ox-ascii.el @@ -192,8 +192,10 @@ original Org buffer at the same place." (defcustom org-ascii-indented-line-width 'auto "Additional indentation width for the first line in a paragraph. If the value is an integer, indent the first line of each -paragraph by this number. If it is the symbol `auto' preserve -indentation from original document." +paragraph by this width, unless it is located at the beginning of +a section, in which case indentation is removed from that line. +If it is the symbol `auto' preserve indentation from original +document." :group 'org-export-ascii :version "24.4" :package-version '(Org . "8.0") @@ -421,17 +423,17 @@ equivalent to `left'. For a justification that doesn't also fill string, see `org-ascii--justify-string'. Return nil if S isn't a string." - ;; Don't fill paragraph when break should be preserved. - (cond ((not (stringp s)) nil) - ((plist-get info :preserve-breaks) s) - (t (let ((double-space-p sentence-end-double-space)) - (with-temp-buffer - (let ((fill-column text-width) - (use-hard-newlines t) - (sentence-end-double-space double-space-p)) - (insert s) - (fill-region (point-min) (point-max) justify)) - (buffer-string)))))) + (when (stringp s) + (let ((double-space-p sentence-end-double-space)) + (with-temp-buffer + (let ((fill-column text-width) + (use-hard-newlines t) + (sentence-end-double-space double-space-p)) + (insert (if (plist-get info :preserve-breaks) + (replace-regexp-in-string "\n" hard-newline s) + s)) + (fill-region (point-min) (point-max) justify)) + (buffer-string))))) (defun org-ascii--justify-string (s text-width how) "Justify string S. @@ -455,13 +457,13 @@ HOW determines the type of justification: it can be `left', Empty lines are not indented." (when (stringp s) (replace-regexp-in-string - "\\(^\\)\\(?:.*\\S-\\)" (make-string width ? ) s nil nil 1))) + "\\(^\\)[ \t]*\\S-" (make-string width ?\s) s nil nil 1))) (defun org-ascii--box-string (s info) "Return string S with a partial box to its left. INFO is a plist used as a communication channel." (let ((utf8p (eq (plist-get info :ascii-charset) 'utf-8))) - (format (if utf8p "╭────\n%s\n╰────" ",----\n%s\n`----") + (format (if utf8p "┌────\n%s\n└────" ",----\n%s\n`----") (replace-regexp-in-string "^" (if utf8p "│ " "| ") ;; Remove last newline character. @@ -473,7 +475,7 @@ INFO is a plist used as a communication channel." (case (org-element-type element) ;; Elements with an absolute width: `headline' and `inlinetask'. (inlinetask org-ascii-inlinetask-width) - ('headline + (headline (- org-ascii-text-width (let ((low-level-rank (org-export-low-level-p element info))) (if low-level-rank (* low-level-rank 2) org-ascii-global-margin)))) @@ -1418,12 +1420,16 @@ INFO is a plist holding contextual information." "Transcode a PARAGRAPH element from Org to ASCII. CONTENTS is the contents of the paragraph, as a string. INFO is the plist used as a communication channel." - (let ((contents (if (not (wholenump org-ascii-indented-line-width)) contents - (concat - (make-string org-ascii-indented-line-width ? ) - (replace-regexp-in-string "\\`[ \t]+" "" contents))))) - (org-ascii--fill-string - contents (org-ascii--current-text-width paragraph info) info))) + (org-ascii--fill-string + (if (not (wholenump org-ascii-indented-line-width)) contents + (concat + ;; Do not indent first paragraph in a section. + (unless (and (not (org-export-get-previous-element paragraph info)) + (eq (org-element-type (org-export-get-parent paragraph)) + 'section)) + (make-string org-ascii-indented-line-width ?\s)) + (replace-regexp-in-string "\\`[ \t]+" "" contents))) + (org-ascii--current-text-width paragraph info) info)) ;;;; Plain List @@ -1591,8 +1597,8 @@ contextual information." CONTENTS is the contents of the object. INFO is a plist holding contextual information." (if (org-element-property :use-brackets-p superscript) - (format "_{%s}" contents) - (format "_%s" contents))) + (format "^{%s}" contents) + (format "^%s" contents))) ;;;; Strike-through @@ -1659,20 +1665,25 @@ are ignored." (or (gethash key cache) (puthash key - (or (and (not org-ascii-table-widen-columns) - (org-export-table-cell-width table-cell info)) - (let* ((max-width 0)) - (org-element-map table 'table-row - (lambda (row) - (setq max-width - (max (string-width - (org-export-data - (org-element-contents - (elt (org-element-contents row) col)) - info)) - max-width))) - info) - max-width)) + (let ((cookie-width (org-export-table-cell-width table-cell info))) + (or (and (not org-ascii-table-widen-columns) cookie-width) + (let ((contents-width + (let ((max-width 0)) + (org-element-map table 'table-row + (lambda (row) + (setq max-width + (max (string-width + (org-export-data + (org-element-contents + (elt (org-element-contents row) col)) + info)) + max-width))) + info) + max-width))) + (cond ((not cookie-width) contents-width) + (org-ascii-table-widen-columns + (max cookie-width contents-width)) + (t cookie-width))))) cache)))) (defun org-ascii-table-cell (table-cell contents info) diff --git a/lisp/org/ox-beamer.el b/lisp/org/ox-beamer.el index f3a79d7c860..5ab805db271 100644 --- a/lisp/org/ox-beamer.el +++ b/lisp/org/ox-beamer.el @@ -687,7 +687,7 @@ used as a communication channel." (cond ((equal type "radio") (let ((destination (org-export-resolve-radio-link link info))) - (when destination + (if (not destination) contents (format "\\hyperlink%s{%s}{%s}" (or (org-beamer--element-has-overlay-p link) "") (org-export-solidify-link-text @@ -1092,6 +1092,7 @@ aid, but the tag does not have any semantic meaning." envs) '((:endgroup)) '(("BMCOL" . ?|)))) + (org-tag-persistent-alist nil) (org-use-fast-tag-selection t) (org-fast-tag-selection-single-key t)) (org-set-tags) diff --git a/lisp/org/ox-html.el b/lisp/org/ox-html.el index 88e572084c8..23498b26924 100644 --- a/lisp/org/ox-html.el +++ b/lisp/org/ox-html.el @@ -2275,83 +2275,70 @@ holding contextual information." "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
%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 extra-ids full-text level1) + ;; When there is no section, pretend there is an + ;; empty one to get the correct
(incf link-count) 1) - (not (org-html-inline-image-p obj info)))) - (otherwise t))) - info 'first-match 'link)))))) + (catch 'exit + (let ((link-count 0)) + (org-element-map (org-element-contents paragraph) + (cons 'plain-text org-element-all-objects) + #'(lambda (obj) + (when (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)) + (throw 'exit nil))) + info nil 'link) + (= link-count 1)))))) (defun org-html-link (link desc info) "Transcode a LINK object from Org to HTML. @@ -2719,7 +2707,7 @@ INFO is a plist holding contextual information. See ;; link's description. ((string= type "radio") (let ((destination (org-export-resolve-radio-link link info))) - (when destination + (if (not destination) desc (format "%s" (org-export-solidify-link-text (org-element-property :value destination)) diff --git a/lisp/org/ox-icalendar.el b/lisp/org/ox-icalendar.el index a60c2f92f39..cd48bbf9aef 100644 --- a/lisp/org/ox-icalendar.el +++ b/lisp/org/ox-icalendar.el @@ -174,8 +174,7 @@ The anniversaries are defined in the BBDB database." (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." +These are entries like in the diary, but directly in an Org file." :group 'org-export-icalendar :type 'boolean) @@ -302,14 +301,14 @@ which will be updated." INFO is a plist used as a communication channel. -a headline is blocked when either: +A headline is blocked when either - - It has children which are not all in a completed state. + - 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. + - 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 + - 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. @@ -478,10 +477,10 @@ or subject for the event." ;;; Filters (defun org-icalendar-clear-blank-lines (headline back-end info) - "Remove trailing blank lines in HEADLINE export. + "Remove 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)) + (replace-regexp-in-string "^\\(?:[ \t]*\n\\)+" "" headline)) @@ -570,13 +569,19 @@ inlinetask within the section." ;; happen once ENTRY is one of them. (let ((counter 0)) (mapconcat - 'identity + #'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))) + (when (let ((type (org-element-property :type ts))) + (case (plist-get info :with-timestamps) + (active (memq type '(active active-range))) + (inactive (memq type '(inactive inactive-range))) + ((t) t))) + (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. @@ -589,7 +594,7 @@ inlinetask within the section." (and (eq type 'headline) (not (org-icalendar-blocked-headline-p entry info)))) - ('t (eq todo-type 'todo)))) + ((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 @@ -597,7 +602,7 @@ inlinetask within the section." ;; separately. (when org-icalendar-include-sexps (let ((counter 0)) - (mapconcat 'identity + (mapconcat #'identity (org-element-map (cons (org-element-property :title entry) (org-element-contents inside)) @@ -613,7 +618,7 @@ inlinetask within the section." ;; inlinetask within it. In agenda export, this is independent ;; from the mark (or lack thereof) on the entry. (when (eq type 'headline) - (mapconcat 'identity + (mapconcat #'identity (org-element-map inside 'inlinetask (lambda (task) (org-icalendar-entry task nil info)) info) "")) diff --git a/lisp/org/ox-latex.el b/lisp/org/ox-latex.el index 53cc54f00f7..2c71f7d785a 100644 --- a/lisp/org/ox-latex.el +++ b/lisp/org/ox-latex.el @@ -524,7 +524,7 @@ When nil, no transformation is made." :package-version '(Org . "8.0") :type '(choice (string :tag "Format string") - (const :tag "No formatting"))) + (const :tag "No formatting" nil))) ;;;; Text markup @@ -689,9 +689,9 @@ These options are supplied as a comma-separated list to the a list containing two strings: the name of the option, and the value. For example, - (setq org-latex-listings-options + \(setq org-latex-listings-options '((\"basicstyle\" \"\\\\small\") - (\"keywordstyle\" \"\\\\color{black}\\\\bfseries\\\\underbar\"))) + \(\"keywordstyle\" \"\\\\color{black}\\\\bfseries\\\\underbar\"))) will typeset the code in a small size font with underlined, bold black keywords. @@ -1526,17 +1526,16 @@ holding contextual information." (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)))))) + (mapconcat #'identity tags ":")))))) + (concat "\\begin{center}\n" + "\\fbox{\n" + "\\begin{minipage}[c]{.6\\textwidth}\n" + full-title "\n\n" + (and (org-string-nw-p contents) + (concat "\\rule[.8em]{\\textwidth}{2pt}\n\n" contents)) + "\\end{minipage}\n" + "}\n" + "\\end{center}")))))) ;;;; Italic @@ -1810,7 +1809,7 @@ INFO is a plist holding contextual information. See ;; description. ((string= type "radio") (let ((destination (org-export-resolve-radio-link link info))) - (when destination + (if (not destination) desc (format "\\hyperref[%s]{%s}" (org-export-solidify-link-text (org-element-property :value destination)) @@ -1843,7 +1842,8 @@ INFO is a plist holding contextual information. See 'number-to-string (org-export-get-headline-number destination info) "-")))) - (if (and (plist-get info :section-numbers) (not desc)) + (if (and (not desc) + (org-export-numbered-headline-p destination info)) (format "\\ref{%s}" label) (format "\\hyperref[%s]{%s}" label (or desc diff --git a/lisp/org/ox-md.el b/lisp/org/ox-md.el index 1f841c865fa..99a4ae01786 100644 --- a/lisp/org/ox-md.el +++ b/lisp/org/ox-md.el @@ -102,21 +102,28 @@ This variable can be set to either `atx' or `setext'." TREE is the parse tree being exported. BACKEND is the export back-end used. INFO is a plist used as a communication channel. -Make sure there's no blank line before a plain list, unless it is -located right after a paragraph. Otherwise, add a blank line -between elements. Blank lines between items are preserved. +Enforce a blank line between elements. There are three +exceptions to this rule: + + 1. Preserve blank lines between sibling items in a plain list, + + 2. Outside of plain lists, preserve blank lines between + a paragraph and a plain list, + + 3. In an item, remove any blank line before the very first + paragraph and the next sub-list. Assume BACKEND is `md'." (org-element-map tree (remq 'item org-element-all-elements) - (lambda (elem) - (org-element-put-property - elem :post-blank - (if (and (eq (org-element-type (org-export-get-next-element elem info)) - 'plain-list) - (not (and (eq (org-element-type elem) 'paragraph) - (org-export-get-previous-element elem info)))) - 0 - 1)))) + (lambda (e) + (cond + ((not (and (eq (org-element-type e) 'paragraph) + (eq (org-element-type (org-export-get-next-element e info)) + 'plain-list))) + (org-element-put-property e :post-blank 1)) + ((not (eq (org-element-type (org-element-property :parent e)) 'item))) + (t (org-element-put-property + e :post-blank (if (org-export-get-previous-element e info) 1 0)))))) ;; Return updated tree. tree) @@ -182,6 +189,14 @@ a communication channel." (and (plist-get info :with-priority) (let ((char (org-element-property :priority headline))) (and char (format "[#%c] " char))))) + (anchor + (when (plist-get info :with-toc) + (org-html--anchor + (or (org-element-property :CUSTOM_ID headline) + (concat "sec-" + (mapconcat 'number-to-string + (org-export-get-headline-number + headline info) "-")))))) ;; Headline text without tags. (heading (concat todo priority title))) (cond @@ -202,12 +217,12 @@ a communication channel." (replace-regexp-in-string "^" " " contents))))) ;; Use "Setext" style. ((eq org-md-headline-style 'setext) - (concat heading tags "\n" + (concat heading tags anchor "\n" (make-string (length heading) (if (= level 1) ?= ?-)) "\n\n" contents)) ;; Use "atx" style. - (t (concat (make-string level ?#) " " heading tags "\n\n" contents)))))) + (t (concat (make-string level ?#) " " heading tags anchor "\n\n" contents)))))) ;;;; Horizontal Rule @@ -279,57 +294,65 @@ a communication channel." (concat (file-name-sans-extension raw-path) ".md") 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-md destination))) - (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)))) - (caption (org-export-data - (org-export-get-caption - (org-export-get-parent-element link)) info))) - (format "![img](%s)" - (if (not (org-string-nw-p caption)) path - (format "%s \"%s\"" path caption))))) - ((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") contents) - ((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)) - ((string= type "file") - (let ((path (funcall link-org-files-as-md raw-path))) - (if (not (file-name-absolute-p path)) path - ;; If file path is absolute, prepend it - ;; with "file:" component. - (concat "file:" path)))) - (t raw-path)))) - (if (not contents) (format "<%s>" path) - (format "[%s](%s)" contents path))))))) + (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-md destination))) + (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)))) + (caption (org-export-data + (org-export-get-caption + (org-export-get-parent-element link)) info))) + (format "![img](%s)" + (if (not (org-string-nw-p caption)) path + (format "%s \"%s\"" path caption))))) + ((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") contents) + ((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 ".")))))))) + ;; Link type is handled by a special function. + ((let ((protocol (nth 2 (assoc type org-link-protocols)))) + (and (functionp protocol) + (funcall protocol + (org-link-unescape (org-element-property :path link)) + contents + 'md)))) + (t (let* ((raw-path (org-element-property :path link)) + (path + (cond + ((member type '("http" "https" "ftp")) + (concat type ":" raw-path)) + ((string= type "file") + (let ((path (funcall link-org-files-as-md raw-path))) + (if (not (file-name-absolute-p path)) path + ;; If file path is absolute, prepend it + ;; with "file:" component. + (concat "file:" path)))) + (t raw-path)))) + (if (not contents) (format "<%s>" path) + (format "[%s](%s)" contents path))))))) ;;;; Paragraph diff --git a/lisp/org/ox-odt.el b/lisp/org/ox-odt.el index 772017cdd0c..03b3214a469 100644 --- a/lisp/org/ox-odt.el +++ b/lisp/org/ox-odt.el @@ -1741,7 +1741,8 @@ CONTENTS is nil. INFO is a plist holding contextual information." :transcoders '((paragraph . (lambda (p c i) (org-odt--format-paragraph - p c "Footnote" + p c i + "Footnote" "OrgFootnoteCenter" "OrgFootnoteQuotations"))))) info)))) @@ -2732,7 +2733,7 @@ INFO is a plist holding contextual information. See ;; link's description. ((string= type "radio") (let ((destination (org-export-resolve-radio-link link info))) - (when destination + (if (not destination) desc (format "%s" (org-export-solidify-link-text @@ -2832,33 +2833,44 @@ INFO is a plist holding contextual information. See ;;;; Paragraph -(defun org-odt--format-paragraph (paragraph contents default center quote) +(defun org-odt--paragraph-style (paragraph) + "Return style of PARAGRAPH. +Style is a symbol among `quoted', `centered' and nil." + (let ((up paragraph)) + (while (and (setq up (org-element-property :parent up)) + (not (memq (org-element-type up) + '(center-block quote-block section))))) + (case (org-element-type up) + (center-block 'centered) + (quote-block 'quoted)))) + +(defun org-odt--format-paragraph (paragraph contents info 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))) +transcoded contents of that paragraph, as a string. INFO is +a plist used as a communication channel. DEFAULT, CENTER and +QUOTE are, respectively, style to use when paragraph belongs to +no special environment, a center block, or a quote block." + (format "\n%s" + (case (org-odt--paragraph-style paragraph) + (quoted quote) + (centered center) + (otherwise default)) + ;; If PARAGRAPH is a leading paragraph in an item that has + ;; a checkbox, splice checkbox and paragraph contents + ;; together. + (concat (let ((parent (org-element-property :parent paragraph))) + (and (eq (org-element-type parent) 'item) + (not (org-export-get-previous-element paragraph info)) + (org-odt--checkbox parent))) + 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 + paragraph contents info (or (org-element-property :style paragraph) "Text_20_body") "OrgCenter" "Quotations")) diff --git a/lisp/org/ox-org.el b/lisp/org/ox-org.el index 3b2e55e2d45..195b9d76587 100644 --- a/lisp/org/ox-org.el +++ b/lisp/org/ox-org.el @@ -65,7 +65,7 @@ setting of `org-html-htmlize-output-type' is 'css." (entity . org-org-identity) (example-block . org-org-identity) (fixed-width . org-org-identity) - (footnote-definition . org-org-identity) + (footnote-definition . ignore) (footnote-reference . org-org-identity) (headline . org-org-headline) (horizontal-rule . org-org-identity) @@ -87,7 +87,7 @@ setting of `org-html-htmlize-output-type' is 'css." (quote-block . org-org-identity) (quote-section . org-org-identity) (radio-target . org-org-identity) - (section . org-org-identity) + (section . org-org-section) (special-block . org-org-identity) (src-block . org-org-identity) (statistics-cookie . org-org-identity) @@ -122,15 +122,16 @@ CONTENTS is its contents, as a string or nil. INFO is ignored." (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)) + (unless (org-element-property :footnote-section-p headline) + (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. @@ -144,6 +145,33 @@ keywords targeted at other export back-ends." org-element-block-name-alist)) (org-element-keyword-interpreter keyword nil))) +(defun org-org-section (section contents info) + "Transcode SECTION element back into Org syntax. +CONTENTS is the contents of the section. INFO is a plist used as +a communication channel." + (concat + (org-element-normalize-string contents) + ;; Insert footnote definitions appearing for the first time in this + ;; section. Indeed, some of them may not be available to narrowing + ;; so we make sure all of them are included in the result. + (let ((footnotes-alist + (org-element-map section 'footnote-reference + (lambda (fn) + (and (eq (org-element-property :type fn) 'standard) + (org-export-footnote-first-reference-p fn info) + (cons (org-element-property :label fn) + (org-export-get-footnote-definition fn info)))) + info))) + (and footnotes-alist + (concat "\n" + (mapconcat + (lambda (d) + (org-element-normalize-string + (concat (format "[%s] "(car d)) + (org-export-data (cdr d) info)))) + footnotes-alist "\n")))) + (make-string (or (org-element-property :post-blank section) 0) ?\n))) + ;;;###autoload (defun org-org-export-as-org (&optional async subtreep visible-only ext-plist) "Export current buffer to an Org buffer. diff --git a/lisp/org/ox-publish.el b/lisp/org/ox-publish.el index b38fca97059..1dc790daf37 100644 --- a/lisp/org/ox-publish.el +++ b/lisp/org/ox-publish.el @@ -805,9 +805,14 @@ Default for SITEMAP-FILENAME is 'sitemap.org'." (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))) + (let ((property + (plist-get + ;; protect local variables in open buffers + (if visiting + (org-export-with-buffer-copy (org-export-get-environment)) + (org-export-get-environment)) + :title))) (if property (org-no-properties (org-element-interpret-data property)) (file-name-nondirectory (file-name-sans-extension file)))))) @@ -822,12 +827,14 @@ 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)) + (let* ((org-inhibit-startup t) + (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)) + (if visiting + (org-export-with-buffer-copy (org-export-get-environment)) + (org-export-get-environment))) :date))) (unless visiting (kill-buffer file-buf)) ;; DATE is either a timestamp object or a secondary string. If it diff --git a/lisp/org/ox-texinfo.el b/lisp/org/ox-texinfo.el index a961d7acdbc..37841d776f4 100644 --- a/lisp/org/ox-texinfo.el +++ b/lisp/org/ox-texinfo.el @@ -21,38 +21,7 @@ ;;; 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")) -;; +;; See Org manual for details. ;;; Code: @@ -70,8 +39,8 @@ (center-block . org-texinfo-center-block) (clock . org-texinfo-clock) (code . org-texinfo-code) - (comment . org-texinfo-comment) - (comment-block . org-texinfo-comment-block) + (comment . (lambda (&rest args) "")) + (comment-block . (lambda (&rest args) "")) (drawer . org-texinfo-drawer) (dynamic-block . org-texinfo-dynamic-block) (entity . org-texinfo-entity) @@ -114,13 +83,14 @@ :export-block "TEXINFO" :filters-alist '((:filter-headline . org-texinfo-filter-section-blank-lines) + (:filter-parse-tree . org-texinfo--normalize-headlines) (: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-filename "TEXINFO_FILENAME" nil nil 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) @@ -128,7 +98,8 @@ (: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))) + (:texinfo-dirdesc "TEXINFO_DIR_DESC" nil nil t) + (:texinfo-printed-title "TEXINFO_PRINTED_TITLE" nil nil t))) @@ -141,12 +112,7 @@ :package-version '(Org . "8.0") :group 'org-export) -;;; Preamble - -(defcustom org-texinfo-filename "" - "Default filename for Texinfo output." - :group 'org-export-texinfo - :type '(string :tag "Export Filename")) +;;;; Preamble (defcustom org-texinfo-coding-system nil "Default document encoding for Texinfo output. @@ -162,19 +128,42 @@ If `nil' it will default to `buffer-file-coding-system'." (defcustom org-texinfo-classes '(("info" - "\\input texinfo @c -*- texinfo -*-" + "@documentencoding AUTO\n@documentlanguage AUTO" ("@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 +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\) - ...\) + \(numbered-section . unnumbered-section) + ...) + + +The header string +----------------- + +The header string is inserted in the header of the generated +document, right after \"@setfilename\" and \"@settitle\" +commands. + +If it contains the special string + + \"@documentencoding AUTO\" + +\"AUTO\" will be replaced with an appropriate coding system. See +`org-texinfo-coding-system' for more information. Likewise, if +the string contains the special string + + \"@documentlanguage AUTO\" + +\"AUTO\" will be replaced with the language defined in the +buffer, through #+LANGUAGE keyword, or globally, with +`org-export-default-language', which see. + The sectioning structure ------------------------ @@ -186,10 +175,12 @@ 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 +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 + :version "24.4" + :package-version '(Org . "8.2") :type '(repeat (list (string :tag "Texinfo class") (string :tag "Texinfo header") @@ -200,7 +191,7 @@ a format string in which the section title will be added." (string :tag "unnumbered")) (function :tag "Hook computing sectioning")))))) -;;; Headline +;;;; Headline (defcustom org-texinfo-format-headline-function 'ignore "Function to format headline text. @@ -230,22 +221,16 @@ order to reproduce the default set-up: :group 'org-export-texinfo :type 'function) -;;; Node listing (menu) +;;;; Node listing (menu) (defcustom org-texinfo-node-description-column 32 - "Column at which to start the description in the node - listings. - + "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 +;;;; Timestamps (defcustom org-texinfo-active-timestamp-format "@emph{%s}" "A printf format string to be applied to active timestamps." @@ -262,14 +247,14 @@ be placed after the end of the title." :group 'org-export-texinfo :type 'string) -;;; Links +;;;; 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 +;;;; Tables (defcustom org-texinfo-tables-verbatim nil "When non-nil, tables are exported verbatim." @@ -285,14 +270,14 @@ When nil, no transformation is made." :group 'org-export-texinfo :type '(choice (string :tag "Format string") - (const :tag "No formatting"))) + (const :tag "No formatting" nil))) (defcustom org-texinfo-def-table-markup "@samp" "Default setting for @table environments." :group 'org-export-texinfo :type 'string) -;;; Text markup +;;;; Text markup (defcustom org-texinfo-text-markup-alist '((bold . "@strong{%s}") (code . code) @@ -316,7 +301,7 @@ returned as-is." :type 'alist :options '(bold code italic verbatim comment)) -;;; Drawers +;;;; Drawers (defcustom org-texinfo-format-drawer-function (lambda (name contents) contents) @@ -331,10 +316,10 @@ The function should return the string to be exported. The default function simply returns the value of CONTENTS." :group 'org-export-texinfo :version "24.4" - :package-version '(Org . "8.3") + :package-version '(Org . "8.2") :type 'function) -;;; Inlinetasks +;;;; Inlinetasks (defcustom org-texinfo-format-inlinetask-function 'ignore "Function called to format an inlinetask in Texinfo code. @@ -370,18 +355,13 @@ in order to mimic default behavior: :group 'org-export-texinfo :type 'function) -;;; Src blocks -;; -;; Src Blocks are example blocks, except for LISP - -;;; Compilation +;;;; Compilation -(defcustom org-texinfo-info-process - '("makeinfo %f") +(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 +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" @@ -403,12 +383,13 @@ 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.") + "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") @@ -425,6 +406,31 @@ If two strings share the same prefix (e.g. \"ISO-8859-1\" and (let ((blanks (make-string 2 ?\n))) (replace-regexp-in-string "\n\\(?:\n[ \t]*\\)*\\'" blanks headline))) +(defun org-texinfo--normalize-headlines (tree back-end info) + "Normalize headlines in TREE. + +BACK-END is the symbol specifying back-end used for export. INFO +is a plist used as a communication channel. + +Make sure every headline in TREE contains a section, since those +are required to install a menu. Also put exactly one blank line +at the end of each section. + +Return new tree." + (org-element-map tree 'headline + (lambda (hl) + (org-element-put-property hl :post-blank 1) + (let ((contents (org-element-contents hl))) + (when contents + (let ((first (org-element-map contents '(headline section) + #'identity info t))) + (unless (eq (org-element-type first) 'section) + (apply #'org-element-set-contents + hl + (cons `(section (:parent ,hl)) contents))))))) + info) + tree) + (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." @@ -433,18 +439,6 @@ This is used to choose a separator for constructs like \\verb." 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." @@ -472,207 +466,44 @@ See `org-texinfo-text-markup-alist' for details." ;; 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--get-node (blob info) + "Return node or anchor associated to BLOB. +BLOB is an element or object. INFO is a plist used as +a communication channel. The function guarantees the node or +anchor name is unique." + (let ((cache (plist-get info :texinfo-node-cache))) + (or (cdr (assq blob cache)) + (let ((name + (org-texinfo--sanitize-node + (case (org-element-type blob) + (headline + (org-export-data (org-export-get-alt-title blob info) info)) + ((radio-target target) (org-element-property :value blob)) + (otherwise (or (org-element-property :name blob) "")))))) + ;; Ensure NAME is unique. + (while (rassoc name cache) (setq name (concat name "x"))) + (plist-put info :texinfo-node-cache (cons (cons blob name) cache)) + name)))) + +;;;; Menu sanitizing + +(defun org-texinfo--sanitize-node (title) + "Bend string TITLE to node line requirements. +Trim string and collapse multiple whitespace characters as they +are not significant. Also remove the following characters: @ +{ } ( ) : . ," + (replace-regexp-in-string + "[:,.]" "" + (replace-regexp-in-string + "\\`(\\(.*)\\)" "[\\1" + (org-trim (replace-regexp-in-string "[ \t]\\{2,\\}" " " 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)) + "Escape special characters in string TEXT. +Special characters are: @ { }" + (replace-regexp-in-string "[@{}]" "@\\&" text)) ;;; Template @@ -680,145 +511,127 @@ of the longest menu entry." "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))) + (let ((title (org-export-data (plist-get info :title) info)) + ;; Copying data is the contents of the first headline in + ;; parse tree with a non-nil copying property. + (copying (org-element-map (plist-get info :parse-tree) 'headline + (lambda (hl) + (and (org-not-nil (org-element-property :COPYING hl)) + (org-element-contents hl))) + info t))) (concat - ;; Header - header "\n" + "\\input texinfo @c -*- texinfo -*-\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) + (let ((file (or (plist-get info :texinfo-filename) + (let ((f (plist-get info :output-file))) + (and f (concat (file-name-sans-extension f) ".info")))))) + (and file (format "@setfilename %s\n" file))) + (format "@settitle %s\n" title) + ;; Insert class-defined header. + (org-element-normalize-string + (let ((header (nth 1 (assoc (plist-get info :texinfo-class) + org-texinfo-classes))) + (coding + (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)))))) + (language (plist-get info :language)) + (case-fold-search nil)) + ;; Auto coding system. + (replace-regexp-in-string + "^@documentencoding \\(AUTO\\)$" + coding + (replace-regexp-in-string + "^@documentlanguage \\(AUTO\\)$" language header t nil 1) t nil 1))) + ;; Additional header options set by #+TEXINFO_HEADER. + (let ((texinfo-header (plist-get info :texinfo-header))) + (and texinfo-header (org-element-normalize-string texinfo-header))) + "@c %**end of header\n\n" + ;; Additional options set by #+TEXINFO_POST_HEADER. + (let ((texinfo-post-header (plist-get info :texinfo-post-header))) + (and texinfo-post-header + (org-element-normalize-string texinfo-post-header))) + ;; Copying. + (and copying + (format "@copying\n%s@end copying\n\n" + (org-element-normalize-string + (org-export-data copying info)))) + ;; Info directory information. Only supply if both title and + ;; category are provided. + (let ((dircat (plist-get info :texinfo-dircat)) + (dirtitle + (let ((title (plist-get info :texinfo-dirtitle))) + (and title + (string-match "^\\(?:\\* \\)?\\(.*?\\)\\(\\.\\)?$" title) + (format "* %s." (match-string 1 title)))))) + (when (and dircat dirtitle) (concat "@dircategory " dircat "\n" "@direntry\n" - "* " dirtitle "." - (make-string dirspacing ?\s) - dirdesc "\n" - "@end direntry\n")) - "\n\n" - + (let ((dirdesc + (let ((desc (plist-get info :texinfo-dirdesc))) + (cond ((not desc) nil) + ((org-string-match-p "\\.$" desc) desc) + (t (concat desc ".")))))) + (if dirdesc (format "%-23s %s" dirtitle dirdesc) dirtitle)) + "\n" + "@end direntry\n\n"))) ;; Title + "@finalout\n" "@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" + (format "@title %s\n" (or (plist-get info :texinfo-printed-title) title)) + (let ((subtitle (plist-get info :subtitle))) + (and subtitle + (org-element-normalize-string + (replace-regexp-in-string "^" "@subtitle " subtitle)))) + (when (plist-get info :with-author) + (concat + ;; Primary author. + (let ((author (org-string-nw-p + (org-export-data (plist-get info :author) info))) + (email (and (plist-get info :with-email) + (org-string-nw-p + (org-export-data (plist-get info :email) info))))) + (cond ((and author email) + (format "@author %s (@email{%s})\n" author email)) + (author (format "@author %s\n" author)) + (email (format "@author @email{%s}\n" email)))) + ;; Other authors. + (let ((subauthor (plist-get info :subauthor))) + (and subauthor + (org-element-normalize-string + (replace-regexp-in-string "^" "@author " subauthor)))))) + (and copying "@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" - + ;; Table of contents. + (and (plist-get info :with-toc) "@contents\n\n") ;; Configure Top Node when not for Tex "@ifnottex\n" "@node Top\n" - "@top " title " Manual\n" - "@insertcopying\n" + (format "@top %s\n" title) + (and copying "@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 + ;; Menu. + (org-texinfo-make-menu (plist-get info :parse-tree) info 'master) "\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")))) + (case (plist-get info :with-creator) + ((nil) nil) + (comment (format "@c %s\n" (plist-get info :creator))) + (otherwise (concat (plist-get info :creator) "\n"))) ;; Document end. - "\n@bye"))) + "@bye"))) ;;; Transcode Functions -;;; Bold +;;;; Bold (defun org-texinfo-bold (bold contents info) "Transcode BOLD from Org to Texinfo. @@ -826,7 +639,7 @@ CONTENTS is the text with bold markup. INFO is a plist holding contextual information." (org-texinfo--text-markup contents 'bold)) -;;; Center Block +;;;; Center Block (defun org-texinfo-center-block (center-block contents info) "Transcode a CENTER-BLOCK element from Org to Texinfo. @@ -834,7 +647,7 @@ CONTENTS holds the contents of the block. INFO is a plist used as a communication channel." contents) -;;; Clock +;;;; Clock (defun org-texinfo-clock (clock contents info) "Transcode a CLOCK element from Org to Texinfo. @@ -851,7 +664,7 @@ information." (and time (format " (%s)" time))))) "@*")) -;;; Code +;;;; Code (defun org-texinfo-code (code contents info) "Transcode a CODE object from Org to Texinfo. @@ -859,23 +672,7 @@ 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 +;;;; Drawer (defun org-texinfo-drawer (drawer contents info) "Transcode a DRAWER element from Org to Texinfo. @@ -886,15 +683,15 @@ holding contextual information." name contents))) output)) -;;; Dynamic Block +;;;; 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'." +holding contextual information." contents) -;;; Entity +;;;; Entity (defun org-texinfo-entity (entity contents info) "Transcode an ENTITY object from Org to Texinfo. @@ -903,7 +700,7 @@ contextual information." (let ((ent (org-element-property :latex entity))) (if (org-element-property :latex-math-p entity) (format "@math{%s}" ent) ent))) -;;; Example Block +;;;; Example Block (defun org-texinfo-example-block (example-block contents info) "Transcode an EXAMPLE-BLOCK element from Org to Texinfo. @@ -912,7 +709,7 @@ information." (format "@verbatim\n%s@end verbatim" (org-export-format-code-default example-block info))) -;;; Export Block +;;;; Export Block (defun org-texinfo-export-block (export-block contents info) "Transcode a EXPORT-BLOCK element from Org to Texinfo. @@ -920,7 +717,7 @@ 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 +;;;; Export Snippet (defun org-texinfo-export-snippet (export-snippet contents info) "Transcode a EXPORT-SNIPPET object from Org to Texinfo. @@ -928,7 +725,7 @@ 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 +;;;; Fixed Width (defun org-texinfo-fixed-width (fixed-width contents info) "Transcode a FIXED-WIDTH element from Org to Texinfo. @@ -938,8 +735,7 @@ CONTENTS is nil. INFO is a plist holding contextual information." (org-texinfo--sanitize-content (org-element-property :value fixed-width))))) -;;; Footnote Reference -;; +;;;; Footnote Reference (defun org-texinfo-footnote-reference (footnote contents info) "Create a footnote reference for FOOTNOTE. @@ -950,7 +746,7 @@ plist holding contextual information." (format "@footnote{%s}" (org-trim (org-export-data def info))))) -;;; Headline +;;;; Headline (defun org-texinfo-headline (headline contents info) "Transcode a HEADLINE element from Org to Texinfo. @@ -960,66 +756,29 @@ holding contextual information." (level (org-export-get-relative-level headline info)) (numberedp (org-export-numbered-headline-p headline info)) (class-sectioning (assoc class org-texinfo-classes)) - ;; Find the index type, if any + ;; 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 + ;; 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-sectioning)) - (fboundp (nth 2 class-sectioning))) - (funcall (nth 2 class-sectioning) level numberedp) - (nth (1+ level) class-sectioning)))) - (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))) + (if (org-not-nil (org-element-property :APPENDIX headline)) + "@appendix %s\n%s" + (let ((sec (if (and (symbolp (nth 2 class-sectioning)) + (fboundp (nth 2 class-sectioning))) + (funcall (nth 2 class-sectioning) level numberedp) + (nth (1+ level) class-sectioning)))) (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"))))))) + ;; 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))) + (concat (if (or index (not numberedp)) (cdr sec) (car sec)) + "\n%s")))))) (todo (and (plist-get info :with-todo-keywords) (let ((todo (org-element-property :todo-keyword headline))) @@ -1029,100 +788,54 @@ holding contextual information." (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 (not (eq org-texinfo-format-headline-function 'ignore)) - ;; 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 (not (eq org-texinfo-format-headline-function 'ignore)) - ;; 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))) + (text (org-export-data (org-element-property :title headline) info)) + (full-text (if (not (eq org-texinfo-format-headline-function 'ignore)) + ;; 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 ":")))))) + (contents (if (org-string-nw-p contents) (concat "\n" contents) ""))) (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) + ((org-not-nil (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))))) + (concat node + (format + section-fmt + full-text + (concat contents + (and (member index '("cp" "fn" "ky" "pg" "tp" "vr")) + (concat "\n@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)))) + (concat (and (org-export-first-sibling-p headline info) + (format "@%s\n" (if numberedp 'enumerate 'itemize))) + "@item\n" full-text "\n" + contents + (if (org-export-last-sibling-p headline info) + (format "@end %s" (if numberedp 'enumerate 'itemize)) + "\n"))) ;; 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 + (t (concat node (format section-fmt full-text 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. @@ -1132,7 +845,7 @@ contextual information." (separator (org-texinfo--find-verb-separator code))) (concat "@verb{" separator code separator "}"))) -;;; Inlinetask +;;;; Inlinetask (defun org-texinfo-inlinetask (inlinetask contents info) "Transcode an INLINETASK element from Org to Texinfo. @@ -1165,7 +878,7 @@ holding contextual information." "\n") full-title contents))))) -;;; Italic +;;;; Italic (defun org-texinfo-italic (italic contents info) "Transcode ITALIC from Org to Texinfo. @@ -1173,18 +886,18 @@ CONTENTS is the text with italic markup. INFO is a plist holding contextual information." (org-texinfo--text-markup contents 'italic)) -;;; Item +;;;; 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"))) + (format "@item%s\n%s" + (let ((tag (org-element-property :tag item))) + (if tag (concat " " (org-export-data tag info)) "")) + (or contents ""))) -;;; Keyword +;;;; Keyword (defun org-texinfo-keyword (keyword contents info) "Transcode a KEYWORD element from Org to Texinfo. @@ -1200,14 +913,14 @@ CONTENTS is nil. INFO is a plist holding contextual information." ((string= key "TINDEX") (format "@tindex %s" value)) ((string= key "VINDEX") (format "@vindex %s" value))))) -;;; Line Break +;;;; 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 +;;;; Link (defun org-texinfo-link (link desc info) "Transcode a LINK object from Org to Texinfo. @@ -1225,55 +938,69 @@ INFO is a plist holding contextual information. See ((and (string= type "file") (file-name-absolute-p 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))) + ((equal type "radio") + (let ((destination (org-export-resolve-radio-link link info))) + (if (not destination) desc + (format "@ref{%s,,%s}" + (org-texinfo--get-node destination info) + desc)))) + ((member type '("custom-id" "id" "fuzzy")) + (let ((destination + (if (equal type "fuzzy") + (org-export-resolve-fuzzy-link link info) + (org-export-resolve-id-link link info)))) (case (org-element-type destination) + ((nil) + (format org-texinfo-link-with-unknown-path-format + (org-texinfo--sanitize-content path))) ;; 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 ""))) + (cond + (desc) + ((org-export-numbered-headline-p destination info) + (org-export-data + (org-element-property :title destination) info)) + (t + (mapconcat + #'number-to-string + (org-export-get-headline-number destination info) "."))))) (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 ((topic + (or desc + (if (and (eq (org-element-type destination) 'headline) + (not (org-export-numbered-headline-p + destination info))) + (org-export-data + (org-element-property :title destination) info)) + (let ((n (org-export-get-ordinal destination info))) + (cond + ((not n) nil) + ((integerp n) n) + (t (mapconcat #'number-to-string n "."))))))) + (when topic + (format "@ref{%s,,%s}" + (org-texinfo--get-node destination info) + topic))))))) + ((equal 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)) + ((string= type "mailto") + (format "@email{%s}" + (concat (org-texinfo--sanitize-content path) + (and desc (concat "," desc))))) + ((let ((protocol (nth 2 (assoc type org-link-protocols)))) + (and (functionp protocol) + (funcall protocol (org-link-unescape path) desc 'texinfo)))) ;; External link with a description part. ((and path desc) (format "@uref{%s,%s}" path desc)) ;; External link without a description part. @@ -1282,27 +1009,97 @@ INFO is a plist holding contextual information. See (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 +;;;; Menu + +(defun org-texinfo-make-menu (scope info &optional master) + "Create the menu for inclusion in the Texinfo document. + +SCOPE is a headline or a full parse tree. INFO is the +communication channel, as a plist. + +When optional argument MASTER is non-nil, generate a master menu, +including detailed node listing." + (let ((menu (org-texinfo--build-menu scope info))) + (when (org-string-nw-p menu) + (org-element-normalize-string + (format + "@menu\n%s@end menu" + (concat menu + (when master + (let ((detailmenu + (org-texinfo--build-menu + scope info + (let ((toc-depth (plist-get info :with-toc))) + (if (wholenump toc-depth) toc-depth + org-texinfo-max-toc-depth))))) + (when (org-string-nw-p detailmenu) + (concat "\n@detailmenu\n" + "--- The Detailed Node Listing ---\n\n" + detailmenu + "@end detailmenu\n")))))))))) + +(defun org-texinfo--build-menu (scope info &optional level) + "Build menu for entries within SCOPE. +SCOPE is a headline or a full parse tree. INFO is a plist +containing contextual information. When optional argument LEVEL +is an integer, build the menu recursively, down to this depth." + (cond + ((not level) + (org-texinfo--format-entries (org-texinfo--menu-entries scope info) info)) + ((zerop level) nil) + (t + (org-element-normalize-string + (mapconcat + (lambda (h) + (let ((entries (org-texinfo--menu-entries h info))) + (when entries + (concat + (format "%s\n\n%s\n" + (org-export-data (org-export-get-alt-title h info) info) + (org-texinfo--format-entries entries info)) + (org-texinfo--build-menu h info (1- level)))))) + (org-texinfo--menu-entries scope info) ""))))) + +(defun org-texinfo--format-entries (entries info) + "Format all direct menu entries in SCOPE, as a string. +SCOPE is either a headline or a full Org document. INFO is +a plist containing contextual information." + (org-element-normalize-string + (mapconcat + (lambda (h) + (let* ((title (org-export-data + (org-export-get-alt-title h info) info)) + (node (org-texinfo--get-node h info)) + (entry (concat "* " title ":" + (if (string= title node) ":" + (concat " " node ". ")))) + (desc (org-element-property :DESCRIPTION h))) + (if (not desc) entry + (format (format "%%-%ds %%s" org-texinfo-node-description-column) + entry desc)))) + entries "\n"))) + +(defun org-texinfo--menu-entries (scope info) + "List direct children in SCOPE needing a menu entry. +SCOPE is a headline or a full parse tree. INFO is a plist +holding contextual information." + (let* ((cache (or (plist-get info :texinfo-entries-cache) + (plist-get (plist-put info :texinfo-entries-cache + (make-hash-table :test #'eq)) + :texinfo-entries-cache))) + (cached-entries (gethash scope cache 'no-cache))) + (if (not (eq cached-entries 'no-cache)) cached-entries + (puthash scope + (org-element-map (org-element-contents scope) 'headline + (lambda (h) + (and (not (org-not-nil (org-element-property :COPYING h))) + (not (org-element-property :footnote-section-p h)) + (not (org-export-low-level-p h info)) + h)) + info nil 'headline) + cache)))) + +;;;; Paragraph (defun org-texinfo-paragraph (paragraph contents info) "Transcode a PARAGRAPH element from Org to Texinfo. @@ -1310,32 +1107,27 @@ CONTENTS is the contents of the paragraph, as a string. INFO is the plist used as a communication channel." contents) -;;; Plain List +;;;; 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)) + (indic (or (plist-get attr :indic) org-texinfo-def-table-markup)) (table-type (plist-get attr :table-type)) - ;; Ensure valid texinfo table type. - (table-type (if (member table-type '("ftable" "vtable")) table-type - "table")) + (type (org-element-property :type plain-list)) (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) + ((member table-type '("ftable" "vtable")) table-type) + (t "table")))) + (format "@%s\n%s@end %s" + (if (eq type 'descriptive) (concat list-type " " indic) list-type) contents list-type))) -;;; Plain Text +;;;; Plain Text (defun org-texinfo-plain-text (text info) "Transcode a TEXT string from Org to Texinfo. @@ -1366,7 +1158,7 @@ contextual information." ;; Return value. output)) -;;; Planning +;;;; Planning (defun org-texinfo-planning (planning contents info) "Transcode a PLANNING element from Org to Texinfo. @@ -1402,7 +1194,7 @@ information." " ") "@*")) -;;; Property Drawer +;;;; Property Drawer (defun org-texinfo-property-drawer (property-drawer contents info) "Transcode a PROPERTY-DRAWER element from Org to Texinfo. @@ -1412,7 +1204,7 @@ information." ;; lines nonetheless. "") -;;; Quote Block +;;;; Quote Block (defun org-texinfo-quote-block (quote-block contents info) "Transcode a QUOTE-BLOCK element from Org to Texinfo. @@ -1424,7 +1216,7 @@ holding contextual information." (format " %s" title))))) (format "%s\n%s@end quotation" start-quote contents))) -;;; Quote Section +;;;; Quote Section (defun org-texinfo-quote-section (quote-section contents info) "Transcode a QUOTE-SECTION element from Org to Texinfo. @@ -1433,7 +1225,7 @@ CONTENTS is nil. INFO is a plist holding contextual information." (org-element-property :value quote-section)))) (when value (format "@verbatim\n%s@end verbatim" value)))) -;;; Radio Target +;;;; Radio Target (defun org-texinfo-radio-target (radio-target text info) "Transcode a RADIO-TARGET object from Org to Texinfo. @@ -1444,15 +1236,17 @@ contextual information." (org-element-property :value radio-target)) text)) -;;; Section +;;;; 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) + (concat contents + (let ((parent (org-export-get-parent-headline section))) + (and parent (org-texinfo-make-menu parent info))))) -;;; Special Block +;;;; Special Block (defun org-texinfo-special-block (special-block contents info) "Transcode a SPECIAL-BLOCK element from Org to Texinfo. @@ -1460,34 +1254,26 @@ CONTENTS holds the contents of the block. INFO is a plist used as a communication channel." contents) -;;; Src Block +;;;; 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))))) + (let ((lispp (org-string-match-p "lisp" + (org-element-property :language src-block))) + (code (org-texinfo--sanitize-content + (org-export-format-code-default src-block info)))) + (format (if lispp "@lisp\n%s@end lisp" "@example\n%s@end example") code))) -;;; Statistics Cookie +;;;; 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 +;;;; Subscript (defun org-texinfo-subscript (subscript contents info) "Transcode a SUBSCRIPT object from Org to Texinfo. @@ -1495,7 +1281,7 @@ CONTENTS is the contents of the object. INFO is a plist holding contextual information." (format "@math{_%s}" contents)) -;;; Superscript +;;;; Superscript (defun org-texinfo-superscript (superscript contents info) "Transcode a SUPERSCRIPT object from Org to Texinfo. @@ -1503,96 +1289,47 @@ 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. +;;;; Table (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)))) + (if (eq (org-element-property :type table) 'table.el) + (format "@verbatim\n%s@end verbatim" + (org-element-normalize-string + (org-element-property :value table))) + (let* ((col-width (org-export-read-attribute :attr_texinfo table :columns)) + (columns + (if col-width (format "@columnfractions %s" col-width) + (org-texinfo-table-column-widths table info)))) + (format "@multitable %s\n%s@end multitable" + columns + contents)))) (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 + (let ((widths (make-vector (cdr (org-export-table-dimensions table info)) 0))) + (org-element-map table 'table-row + (lambda (row) + (let ((idx 0)) + (org-element-map row 'table-cell + (lambda (cell) + ;; Length of the cell in the original buffer is only an + ;; approximation of the length of the cell in the + ;; output. It can sometimes fail (e.g. it considers + ;; "/a/" being larger than "ab"). + (let ((w (- (org-element-property :contents-end cell) + (org-element-property :contents-begin cell)))) + (aset widths idx (max w (aref widths idx)))) + (incf idx)) + info))) + info) + (format "{%s}" (mapconcat (lambda (w) (make-string w ?a)) widths "} {")))) + +;;;; Table Cell (defun org-texinfo-table-cell (table-cell contents info) "Transcode a TABLE-CELL element from Org to Texinfo. @@ -1609,7 +1346,7 @@ a communication channel." contents) (when (org-export-get-next-element table-cell info) "\n@tab "))) -;;; Table Row +;;;; Table Row (defun org-texinfo-table-row (table-row contents info) "Transcode a TABLE-ROW element from Org to Texinfo. @@ -1618,21 +1355,15 @@ 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 + (let ((rowgroup-tag + (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)) + "@headitem " + "@item "))) + (concat rowgroup-tag contents "\n")))) + +;;;; Target (defun org-texinfo-target (target contents info) "Transcode a TARGET object from Org to Texinfo. @@ -1641,7 +1372,7 @@ information." (format "@anchor{%s}" (org-export-solidify-link-text (org-element-property :value target)))) -;;; Timestamp +;;;; Timestamp (defun org-texinfo-timestamp (timestamp contents info) "Transcode a TIMESTAMP object from Org to Texinfo. @@ -1656,7 +1387,7 @@ information." (format org-texinfo-inactive-timestamp-format value)) (t (format org-texinfo-diary-timestamp-format value))))) -;;; Verbatim +;;;; Verbatim (defun org-texinfo-verbatim (verbatim contents info) "Transcode a VERBATIM object from Org to Texinfo. @@ -1664,26 +1395,13 @@ CONTENTS is nil. INFO is a plist used as a communication channel." (org-texinfo--text-markup (org-element-property :value verbatim) 'verbatim)) -;;; Verse Block +;;;; 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))) + (format "@display\n%s@end display" contents)) ;;; Interactive functions @@ -1797,29 +1515,21 @@ Return INFO file name or an error if it couldn't be produced." 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"))) + ;; Replace %b, %f and %o with appropriate values in each command + ;; before applying it. Output is redirected to "*Org INFO + ;; Texinfo Output*" buffer. + (let ((outbuf (get-buffer-create "*Org INFO Texinfo Output*"))) + (dolist (command org-texinfo-info-process) + (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)) + ;; Collect standard errors from output buffer. + (setq errors (org-texinfo-collect-errors outbuf))) (let ((infofile (concat out-dir base-name ".info"))) ;; Check for process failure. Provide collected errors if ;; possible. diff --git a/lisp/org/ox.el b/lisp/org/ox.el index faa2e0541b4..dd81ad13d1d 100644 --- a/lisp/org/ox.el +++ b/lisp/org/ox.el @@ -814,7 +814,7 @@ This variable can be either set to `buffer' or `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 +When Org exports to a file, the buffer visiting that file is never 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 @@ -1317,6 +1317,10 @@ The back-end could then be called with, for example: ;; - category :: tree ;; - type :: list of elements and objects ;; +;; + `:input-buffer' :: Name of input buffer. +;; - category :: option +;; - type :: string +;; ;; + `:input-file' :: Full path to input file, if any. ;; - category :: option ;; - type :: string or nil @@ -1329,6 +1333,10 @@ The back-end could then be called with, for example: ;; - category :: option ;; - type :: string ;; +;; + `:output-file' :: Full path to output file, if any. +;; - category :: option +;; - type :: string or nil +;; ;; + `:parse-tree' :: Whole parse tree, available at any time during ;; transcoding. ;; - category :: option @@ -1765,17 +1773,19 @@ Assume buffer is in Org mode. Narrowing, if any, is ignored." (when (stringp value) (setq plist (plist-put plist property - (org-element-parse-secondary-string - value (org-element-restriction 'keyword)))))))))) + (or (org-element-parse-secondary-string + value (org-element-restriction 'keyword)) + ;; When TITLE keyword sets an empty + ;; string, make sure it doesn't + ;; appear as nil in the plist. + (and (eq property :title) "")))))))))) (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)))))) + :input-buffer (buffer-name (buffer-base-buffer))))) (defun org-export--get-global-options (&optional backend) "Return global export options as a plist. @@ -1788,23 +1798,22 @@ process." (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)) + (let ((prop (car cell))) + (unless (plist-member plist prop) (setq plist (plist-put plist prop - ;; Eval default value provided. If keyword is + ;; Evaluate 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))))))))))) + (if (and (stringp value) + (member (nth 1 cell) + 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. @@ -1843,6 +1852,13 @@ an alist where associations are (VARIABLE-NAME VALUE)." ;; Return value in appropriate order of appearance. (nreverse (funcall collect-bind nil nil))))) +;; defsubst org-export-get-parent must be defined before first use, +;; was originally defined in the topology section + +(defsubst org-export-get-parent (blob) + "Return BLOB parent or nil. +BLOB is the element or object considered." + (org-element-property :parent blob)) ;;;; Tree Properties ;; @@ -2146,9 +2162,8 @@ INFO is a plist containing export directives." 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 +Return a string." + (or (gethash data (plist-get info :exported-data)) (let* ((type (org-element-type data)) (results (cond @@ -2174,9 +2189,9 @@ Return transcoded string." ;; 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. + ;; 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) @@ -2201,16 +2216,16 @@ Return transcoded string." (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. + ;; 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 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 @@ -2227,10 +2242,10 @@ Return transcoded string." (puthash data (cond - ((not results) nil) + ((not results) "") ((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. + ;; 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 @@ -2240,10 +2255,10 @@ Return transcoded string." (if (memq type org-element-all-elements) (concat (org-element-normalize-string results) (make-string post-blank ?\n)) - (concat results (make-string post-blank ? )))) + (concat results (make-string post-blank ?\s)))) info))) results))) - (plist-get info :exported-data)))))) + (plist-get info :exported-data))))) (defun org-export-data-with-backend (data backend info) "Convert DATA into BACKEND format. @@ -3011,6 +3026,14 @@ Return code as a string." (org-export-install-filters (org-combine-plists info (org-export-get-environment backend subtreep ext-plist)))) + ;; Special case: provide original file name or buffer name as + ;; default value for :title property. + (unless (plist-get info :title) + (plist-put + info :title + (let ((file (plist-get info :input-file))) + (if file (file-name-sans-extension (file-name-nondirectory file)) + (plist-get info :input-buffer))))) ;; Expand export-specific set of macros: {{{author}}}, ;; {{{date}}}, {{{email}}} and {{{title}}}. It must be done ;; once regular macros have been expanded, since document @@ -5106,11 +5129,7 @@ Return the new string." ;; `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)) - +;; defsubst org-export-get-parent must be defined before first use (defun org-export-get-genealogy (blob) "Return full genealogy relative to a given element or object. @@ -5638,7 +5657,8 @@ 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))) + (let ((ext-plist (org-combine-plists `(:output-file ,file) ext-plist)) + (encoding (or org-export-coding-system buffer-file-coding-system))) (if async (org-export-async-start `(lambda (file) -- 2.39.2