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 tables
@cindex list of listings @cindex list of listings
@cindex #+TOC
@vindex org-export-with-toc @vindex org-export-with-toc
Org normally inserts the table of contents directly before the first headline The table of contents includes all @emph{numbered} headlines in the document.
of the file. Org sets the TOC depth the same as the headline levels in the Its depth is therefore the same as the headline levels in the file. If you
file. Use a lower number for lower TOC depth. To turn off TOC entirely, use need to use a different depth, or turn it off entirely, set the
@code{nil}. This is configured in the @code{org-export-with-toc} variable or @code{org-export-with-toc} variable accordingly. You can achieve the same on
as keywords in an Org file as: a per file basis, using the following @samp{toc} item in @samp{#+OPTIONS}
keyword:
@example @example
#+OPTIONS: toc:2 @r{only include two levels in TOC} #+OPTIONS: toc:2 @r{only include two levels in TOC}
#+OPTIONS: toc:nil @r{no default TOC at all} #+OPTIONS: toc:nil @r{no default TOC at all}
@end example @end example
To move the table of contents to a different location, first turn off the @cindex #+TOC
default with @code{org-export-with-toc} variable or with @code{#+OPTIONS: Org normally inserts the table of contents directly before the first headline
toc:nil}. Then insert @code{#+TOC: headlines N} at the desired location(s). 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 @example
#+OPTIONS: toc:nil @r{no default TOC} #+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 * Version 9.2
** Incompatible changes ** 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 *** =align= STARTUP value no longer narrow table columns
Columns narrowing (or shrinking) is now dynamic. See [[*Dynamically 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 (defcustom org-texinfo-classes
'(("info" '(("info"
"@documentencoding AUTO\n@documentlanguage AUTO" "@documentencoding AUTO\n@documentlanguage AUTO"
("@chapter %s" "@unnumbered %s" "@appendix %s") ("@chapter %s" "@chapheading %s" "@appendix %s")
("@section %s" "@unnumberedsec %s" "@appendixsec %s") ("@section %s" "@heading %s" "@appendixsec %s")
("@subsection %s" "@unnumberedsubsec %s" "@appendixsubsec %s") ("@subsection %s" "@subheading %s" "@appendixsubsec %s")
("@subsubsection %s" "@unnumberedsubsubsec %s" "@appendixsubsubsec %s"))) ("@subsubsection %s" "@subsubheading %s" "@appendixsubsubsec %s")))
"Alist of Texinfo classes and associated header and structure. "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 a class 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." section string and will be replaced by the title of the section."
:group 'org-export-texinfo :group 'org-export-texinfo
:version "26.1" :version "26.1"
:package-version '(Org . "9.1") :package-version '(Org . "9.2")
:type '(repeat :type '(repeat
(list (string :tag "Texinfo class") (list (string :tag "Texinfo class")
(string :tag "Texinfo header") (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. argument N becomes relative to the level of that headline.
Return a list of all exportable headlines as parsed elements. 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)) (let* ((scope (cond ((not scope) (plist-get info :parse-tree))
((eq (org-element-type scope) 'headline) scope) ((eq (org-element-type scope) 'headline) scope)
((org-export-get-parent-headline scope)) ((org-export-get-parent-headline scope))
@ -5226,7 +5226,8 @@ Footnote sections are ignored."
limit)))) limit))))
(org-element-map (org-element-contents scope) 'headline (org-element-map (org-element-contents scope) 'headline
(lambda (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))) (let ((level (org-export-get-relative-level headline info)))
(and (<= level n) headline)))) (and (<= level n) headline))))
info))) info)))

View File

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