emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Rasmus <rasmus@gmx.us>
To: emacs-orgmode@gnu.org
Cc: alantyree@gmail.com, tsd@tsdye.com
Subject: [patch, ox] Unnumbered headlines
Date: Fri, 08 Aug 2014 15:39:15 +0200	[thread overview]
Message-ID: <87lhqzyubg.fsf@gmx.us> (raw)

[-- Attachment #1: Type: text/plain, Size: 1991 bytes --]


In a recent thread¹ Tom and Alan mention that authors sometimes need
unnumbered headlines, e.g. for prefaces.  This patch (tries to) add
this feature via the tag :nonumber: (customizable via Custom or

I make two assumptions.  First, the tag is recursive, so if the parent
is not numbered the child is not numbered.  Secondly, I depart from
the LaTeX tradition of ignoring unnumbered headlines in the TOC
(except in the case of ox-latex.el where it depends on
org-latex-classes).  (See example below).

Needless to say such a feature needs to be discussed and I not sure
whether the greater Org community finds it useful or needless clutter.

In my opinion a :nonumber: tag is a natural continuation of :export:
and :noexport: and unlike :ignoreheading: the implementation is fairly
clean (or maybe I'm cheating myself here).  A reason for why to
include it is that it seems relatively easy to do *during* export, but
it's hard to consistently get it right on in both headlines and the
TOC via filters.

The patch is messing with ox.el, and thus I would appreciate a review
and potentially testing, in the case that it is agreed that such a
feature would be OK to add to ox.

It seems to work well with ox-latex.el, ox-ascii.el and ox-html.el.
It doesn't play well with ox-odt.el (headlines are still numbered).  I
will fix this as well as adding documentation if a consensus of the
worthwhileness of the patch can be reached.

Finally, here's an example output using ox-ascii

#+begin_src org
    * a (not numbered)	              :nonum:
    ** aa (not numbert)
    * b (1)
    ** ba (not numbered)	      :nonum:
    *** baa (not numbered)
    ** bb (1.1)


#+RESULTS: (TOC only, but the rest is as expected)
    a (not numbered)
    .. aa (not numbert)
    1 b (1)
    .. ba (not numbered)
    ..... baa (not numbered)
    .. 1.1 bb (1.1)


¹   http://permalink.gmane.org/gmane.emacs.orgmode/89515

Vote for proprietary math!

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-ox.el-Support-unnumbered-headlines-via-tag.patch --]
[-- Type: text/x-diff, Size: 5626 bytes --]

From d38a728fef66af9df2a0b87e2126533961d87ecf Mon Sep 17 00:00:00 2001
From: Rasmus <rasmus@gmx.us>
Date: Fri, 8 Aug 2014 14:53:01 +0200
Subject: [PATCH] ox.el: Support unnumbered headlines via tag.

* ox.el (org-export-options-alist): NO_NUMBER_TAGS new keyword.
(org-export-not-numbered-tags): New defcustom.
(org-export--collect-headline-numbering): Considers whether
headline is numbered.
(org-export-numbered-headline-p): Tests if headline is
to be numbered.
(org-export--recursive-tags): New function based.  Previouesly
part of `orge-export-get-tags'.
(org-export-get-tags): Ignoes NO_NUMBER_TAGS.
 lisp/ox.el | 60 +++++++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 43 insertions(+), 17 deletions(-)

diff --git a/lisp/ox.el b/lisp/ox.el
index d47c2e6..2fff14f 100644
--- a/lisp/ox.el
+++ b/lisp/ox.el
@@ -109,6 +109,7 @@
     (:language "LANGUAGE" nil org-export-default-language t)
     (:select-tags "SELECT_TAGS" nil org-export-select-tags split)
     (:exclude-tags "EXCLUDE_TAGS" nil org-export-exclude-tags split)
+    (:no-number-tags "NO_NUMBER_TAGS" nil org-export-not-numbered-tags split)
     (:creator "CREATOR" nil org-export-creator-string)
     (:headline-levels nil "H" org-export-headline-levels)
     (:preserve-breaks nil "\\n" org-export-preserve-breaks)
@@ -448,6 +449,18 @@ e.g. \"*:nil\"."
   :group 'org-export-general
   :type 'boolean)
+(defcustom org-export-not-numbered-tags '("nonumber")
+  "Tags that exclude trees from obtaining numbers.
+All trees carrying any of these tags will be excluded from
+receiving a number.  This includes subtress.
+This option can also be set in files with the NO_NUMBER_TAGS
+  :group 'org-export-general
+  :type '(repeat (string :tag "Tag")))
 (defcustom org-export-exclude-tags '("noexport")
   "Tags that exclude a tree from export.
@@ -1993,7 +2006,8 @@ for a footnotes section."
   (let ((numbering (make-vector org-export-max-depth 0)))
     (org-element-map data 'headline
       (lambda (headline)
-	(unless (org-element-property :footnote-section-p headline)
+	(unless (or (org-element-property :footnote-section-p headline)
+		    (not (org-export-numbered-headline-p headline info)))
 	  (let ((relative-level
 		 (1- (org-export-get-relative-level headline options))))
@@ -3785,9 +3799,12 @@ INFO is a plist holding contextual information."
 (defun org-export-numbered-headline-p (headline info)
   "Return a non-nil value if HEADLINE element should be numbered.
 INFO is a plist used as a communication channel."
-  (let ((sec-num (plist-get info :section-numbers))
+  (let ((tags (org-export--recursive-tags headline info))
+	(sec-num (plist-get info :section-numbers))
 	(level (org-export-get-relative-level headline info)))
-    (if (wholenump sec-num) (<= level sec-num) sec-num)))
+    (unless (loop for k in (plist-get info :no-number-tags)
+		  thereis (member k tags))
+      (if (wholenump sec-num) (<= level sec-num) sec-num))))
 (defun org-export-number-to-roman (n)
   "Convert integer N into a roman numeral."
@@ -3805,14 +3822,33 @@ INFO is a plist used as a communication channel."
 	  (pop roman)))
+(defun org-export--recursive-tags (element info)
+  "Return the full list of recursive tags associated with ELEMENT.
+ELEMENT has either an `headline' or an `inlinetask' type.  INFO
+is a plist used as a communication channel."
+  (let ((current-tag-list (org-element-property :tags element)))
+       (mapc
+	(lambda (parent)
+	  (mapc
+	   (lambda (tag)
+	     (when (and (memq (org-element-type parent) '(headline inlinetask))
+			(not (member tag current-tag-list)))
+	       (push tag current-tag-list)))
+	   (org-element-property :tags parent)))
+	(org-export-get-genealogy element))
+       ;; Add FILETAGS keywords and return results.
+       (org-uniquify (append (plist-get info :filetags) current-tag-list))))
 (defun org-export-get-tags (element info &optional tags inherited)
   "Return list of tags associated to ELEMENT.
 ELEMENT has either an `headline' or an `inlinetask' type.  INFO
 is a plist used as a communication channel.
-Select tags (see `org-export-select-tags') and exclude tags (see
-`org-export-exclude-tags') are removed from the list.
+Select tags (see `org-export-select-tags'), exclude tags (see
+`org-export-exclude-tags') and no-number tags (see
+`org-export-no-number-tags') are removed from the list.
 When non-nil, optional argument TAGS should be a list of strings.
 Any tag belonging to this list will also be removed.
@@ -3822,21 +3858,11 @@ inherited from parent headlines and FILETAGS keywords."
    (lambda (tag) (or (member tag (plist-get info :select-tags))
 		(member tag (plist-get info :exclude-tags))
+		(member tag (plist-get info :no-number-tags))
 		(member tag tags)))
    (if (not inherited) (org-element-property :tags element)
      ;; Build complete list of inherited tags.
-     (let ((current-tag-list (org-element-property :tags element)))
-       (mapc
-	(lambda (parent)
-	  (mapc
-	   (lambda (tag)
-	     (when (and (memq (org-element-type parent) '(headline inlinetask))
-			(not (member tag current-tag-list)))
-	       (push tag current-tag-list)))
-	   (org-element-property :tags parent)))
-	(org-export-get-genealogy element))
-       ;; Add FILETAGS keywords and return results.
-       (org-uniquify (append (plist-get info :filetags) current-tag-list))))))
+     (org-export--recursive-tags (element info)))))
 (defun org-export-get-node-property (property blob &optional inherited)
   "Return node PROPERTY value for BLOB.

             reply	other threads:[~2014-08-08 13:39 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-08-08 13:39 Rasmus [this message]
2014-08-08 22:35 ` [patch, ox] Unnumbered headlines Alan L Tyree
2014-08-09  1:04 ` [patch, ox] Unnumbered headlines - early test Alan L Tyree
2014-08-09  7:47 ` [patch, ox] Unnumbered headlines Detlef Steuer
2014-08-11 14:18 ` Nicolas Goaziou
2014-08-11 15:37   ` Rasmus
2014-08-12  8:58     ` Nicolas Goaziou
2014-09-20 16:02       ` Rasmus
2014-09-20 20:34         ` Alan L Tyree
2014-09-21 13:12         ` Nicolas Goaziou
2014-09-21 14:37           ` Rasmus
2014-09-21 19:40             ` Nicolas Goaziou
2014-09-21 20:13               ` Rasmus
2014-09-22 15:53                 ` Nicolas Goaziou
2014-09-23  0:35                   ` Rasmus
2014-09-23  1:10                     ` Thomas S. Dye
2014-09-26  7:51                     ` Nicolas Goaziou
2014-09-26 13:48                       ` Rasmus
2014-09-27  8:19                         ` Nicolas Goaziou
2014-09-30 22:54                       ` Rasmus
2014-10-02  0:35                         ` Rasmus
2014-10-03  7:56                         ` Nicolas Goaziou
2014-10-03  8:49                           ` Sebastien Vauban
2014-10-03 10:26                           ` Rasmus
2014-10-03 20:14                             ` Nicolas Goaziou
2014-10-03 20:31                               ` Rasmus
2014-10-05  8:06                                 ` Nicolas Goaziou

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87lhqzyubg.fsf@gmx.us \
    --to=rasmus@gmx.us \
    --cc=alantyree@gmail.com \
    --cc=emacs-orgmode@gnu.org \
    --cc=tsd@tsdye.com \


* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).