Table of contents ignore unnumbered headlines

* doc/org.texi (Table of contents): Document behavior.
* lisp/ox-texinfo.el (org-texinfo-classes): Use @heading commands and
  alike for unnumbered sections.
* lisp/ox.el (org-export-collect-headlines): Ignore unnumbered
  headlines.

* testing/lisp/test-ox.el (test-org-export/collect-headlines): Add
  test.
This commit is contained in:
Nicolas Goaziou 2017-09-10 15:53:20 +02:00
parent 7a47458b39
commit bd2378161e
5 changed files with 69 additions and 40 deletions

View File

@ -10899,22 +10899,25 @@ settings that cannot be changed using keywords.
@cindex list of tables
@cindex list of listings
@cindex #+TOC
@vindex org-export-with-toc
Org normally inserts the table of contents directly before the first headline
of the file. Org sets the TOC depth the same as the headline levels in the
file. Use a lower number for lower TOC depth. To turn off TOC entirely, use
@code{nil}. This is configured in the @code{org-export-with-toc} variable or
as keywords in an Org file as:
The table of contents includes all @emph{numbered} headlines in the document.
Its depth is therefore the same as the headline levels in the file. If you
need to use a different depth, or turn it off entirely, set the
@code{org-export-with-toc} variable accordingly. You can achieve the same on
a per file basis, using the following @samp{toc} item in @samp{#+OPTIONS}
keyword:
@example
#+OPTIONS: toc:2 @r{only include two levels in TOC}
#+OPTIONS: toc:nil @r{no default TOC at all}
@end example
To move the table of contents to a different location, first turn off the
default with @code{org-export-with-toc} variable or with @code{#+OPTIONS:
toc:nil}. Then insert @code{#+TOC: headlines N} at the desired location(s).
@cindex #+TOC
Org normally inserts the table of contents directly before the first headline
of the file. To move the table of contents to a different location, first
turn off the default with @code{org-export-with-toc} variable or with
@code{#+OPTIONS: toc:nil}. Then insert @code{#+TOC: headlines N} at the
desired location(s).
@example
#+OPTIONS: toc:nil @r{no default TOC}

View File

@ -12,6 +12,12 @@ Please send Org bug reports to mailto:emacs-orgmode@gnu.org.
* Version 9.2
** Incompatible changes
*** Table of contents ignore unnumbered headlines
This allows finer control over the table of contents itself, using,
e.g., =UNNUMBERED= property. It is also more consistent with LaTeX
export.
*** =align= STARTUP value no longer narrow table columns
Columns narrowing (or shrinking) is now dynamic. See [[*Dynamically

View File

@ -146,10 +146,10 @@ If nil it will default to `buffer-file-coding-system'."
(defcustom org-texinfo-classes
'(("info"
"@documentencoding AUTO\n@documentlanguage AUTO"
("@chapter %s" "@unnumbered %s" "@appendix %s")
("@section %s" "@unnumberedsec %s" "@appendixsec %s")
("@subsection %s" "@unnumberedsubsec %s" "@appendixsubsec %s")
("@subsubsection %s" "@unnumberedsubsubsec %s" "@appendixsubsubsec %s")))
("@chapter %s" "@chapheading %s" "@appendix %s")
("@section %s" "@heading %s" "@appendixsec %s")
("@subsection %s" "@subheading %s" "@appendixsubsec %s")
("@subsubsection %s" "@subsubheading %s" "@appendixsubsubsec %s")))
"Alist of Texinfo classes and associated header and structure.
If #+TEXINFO_CLASS is set in the buffer, use its value and the
associated information. Here is the structure of a class
@ -193,7 +193,7 @@ of strings is specified. A %s formatter is mandatory in each
section string and will be replaced by the title of the section."
:group 'org-export-texinfo
:version "26.1"
:package-version '(Org . "9.1")
:package-version '(Org . "9.2")
:type '(repeat
(list (string :tag "Texinfo class")
(string :tag "Texinfo header")

View File

@ -5214,7 +5214,7 @@ there is no such headline, collect all headlines. In any case,
argument N becomes relative to the level of that headline.
Return a list of all exportable headlines as parsed elements.
Footnote sections are ignored."
Footnote sections and unnumbered headlines are ignored."
(let* ((scope (cond ((not scope) (plist-get info :parse-tree))
((eq (org-element-type scope) 'headline) scope)
((org-export-get-parent-headline scope))
@ -5226,7 +5226,8 @@ Footnote sections are ignored."
limit))))
(org-element-map (org-element-contents scope) 'headline
(lambda (headline)
(unless (org-element-property :footnote-section-p headline)
(unless (or (org-element-property :footnote-section-p headline)
(not (org-export-numbered-headline-p headline info)))
(let ((level (org-export-get-relative-level headline info)))
(and (<= level n) headline))))
info)))

View File

@ -4286,39 +4286,58 @@ Another text. (ref:text)
"Test `org-export-collect-headlines' specifications."
;; Standard test.
(should
(= 2
(length
(org-test-with-parsed-data "* H1\n** H2"
(org-export-collect-headlines info)))))
(equal '("H1" "H2")
(org-test-with-parsed-data "* H1\n** H2"
(mapcar (lambda (h) (org-element-property :raw-value h))
(org-export-collect-headlines info)))))
;; Do not collect headlines below optional argument.
(should
(= 1
(length
(org-test-with-parsed-data "* H1\n** H2"
(org-export-collect-headlines info 1)))))
(equal '("H1")
(org-test-with-parsed-data "* H1\n** H2"
(mapcar (lambda (h) (org-element-property :raw-value h))
(org-export-collect-headlines info 1)))))
;; Never collect headlines below maximum headline level.
(should
(= 1
(length
(org-test-with-parsed-data "#+OPTIONS: H:1\n* H1\n** H2"
(org-export-collect-headlines info)))))
(equal '("H1")
(org-test-with-parsed-data "#+OPTIONS: H:1\n* H1\n** H2"
(mapcar (lambda (h) (org-element-property :raw-value h))
(org-export-collect-headlines info)))))
(should
(= 1
(length
(org-test-with-parsed-data "#+OPTIONS: H:1\n* H1\n** H2"
(org-export-collect-headlines info 2)))))
(equal '("H1")
(org-test-with-parsed-data "#+OPTIONS: H:1\n* H1\n** H2"
(mapcar (lambda (h) (org-element-property :raw-value h))
(org-export-collect-headlines info 2)))))
;; Do not collect footnote section.
(should
(equal '("H1")
(let ((org-footnote-section "Footnotes"))
(org-test-with-parsed-data "* H1\n** Footnotes"
(mapcar (lambda (h) (org-element-property :raw-value h))
(org-export-collect-headlines info))))))
;; Do not collect unnumbered headlines.
(should-not
(org-test-with-parsed-data "#+options: num:nil\n* H1\n** H2"
(org-export-collect-headlines info)))
(should
(equal '("H1")
(org-test-with-parsed-data
"* H1\n** H2\n:PROPERTIES:\n:UNNUMBERED: t\n:END:"
(mapcar (lambda (h) (org-element-property :raw-value h))
(org-export-collect-headlines info)))))
;; Collect headlines locally.
(should
(= 2
(org-test-with-parsed-data "* H1\n** H2\n** H3"
(let ((scope (org-element-map tree 'headline #'identity info t)))
(length (org-export-collect-headlines info nil scope))))))
(equal '("H2" "H3")
(org-test-with-parsed-data "* H1\n** H2\n** H3"
(let ((scope (org-element-map tree 'headline #'identity info t)))
(mapcar (lambda (h) (org-element-property :raw-value h))
(org-export-collect-headlines info nil scope))))))
;; When collecting locally, optional level is relative.
(should
(= 1
(org-test-with-parsed-data "* H1\n** H2\n*** H3"
(let ((scope (org-element-map tree 'headline #'identity info t)))
(length (org-export-collect-headlines info 1 scope)))))))
(equal '("H2")
(org-test-with-parsed-data "* H1\n** H2\n*** H3"
(let ((scope (org-element-map tree 'headline #'identity info t)))
(mapcar (lambda (h) (org-element-property :raw-value h))
(org-export-collect-headlines info 1 scope)))))))