Jason-S-Ross / ox-context

An Org Mode export backend for ConTeXt
13 stars 4 forks source link

Please provide a book alike preset or a switch to start sectioning at chapter level #27

Open juh2 opened 2 years ago

juh2 commented 2 years ago

While the default settings are quite flexible I have difficulties when I want to produce a book.

Jason-S-Ross commented 2 years ago

The problem is more challenging than it first appears. Here's some notes on the subject if I pick this up later or if someone wants to submit a PR.

Challenges

Types of sections

There are actually 4 separate types of sections produced by the exporter:

The first two are built-in; the last two are defined on demand.

Tables of Contents

Org allows specifying the depth of the table of contents by number, e.g. toc:5. ConTeXt wants an explicit list of section names to include in the TOC. This mismatch discussed in this thread. Hans says that the latest ConTeXt has an option for specifying the depth numerically, but I haven't tried it out yet and I don't want to use a brand new version of ConTeXt as a dependency.

Requirements

An ideal solution will do the following

Incomplete Solutions

Custom Headline List

Just allow the user to specify the headlines they want in a document with a list? For instance

  (setq org-context-headline-list
      '(("MySection" "MySubject" "MySectionNoToc" "MySubjectNoToc")
        ("MySubSection" "MySubSubject" "MySubSectionNoToc" "MySubSubjectNoToc")))

This could be implemented by modifying org-context--get-headline-command to something like

(defun org-context--get-headline-command (headline info)
  "Create a headline name with the correct depth.
HEADLINE is the headline object. INFO is a plist containing
contextual information."
  (let* ((level (org-export-get-relative-level headline info))
         (numberedp (org-export-numbered-headline-p headline info))
         (notoc (org-export-excluded-from-toc-p headline info)))
    (cond ((listp org-context-headline-list)
           (let ((typeindex
                  (cond
                   ((and numberedp (not notoc)) 0)
                   ((and (not numberedp) (not notoc)) 1)
                   ((and numberedp notoc) 2)
                   ((and (not numberedp) notoc) 3))))
             (nth typeindex (nth level org-context-headline-list))))
          ((functionp org-context-headline-list)
           (funcall org-context-headline-list level numberedp notoc))
          (t
           (let* ((suffix (if numberedp "section" "subject"))
                  (prefix (apply 'concat (make-list (+ level (- 1)) "sub")))
                  (hname (concat prefix suffix)))
             (if notoc
                 (format "%sNoToc" hname)
               hname))))))

It requires more elisp written by the user, but it's pretty simple and easy to explain what the data structures involved are.

startsectionelevel commands

Replace all section commands with start/stopsectionlevel in the export. This is appealing for a few reasons:

How does it compare to the requirements?

I think this solution has the most potential, but I haven't had time to look into what it takes to handle the tables of contents. If it can be done with pure ConTeXt with a reasonably old version, then I think this is the way to go.

Jason-S-Ross commented 2 years ago

Hans wrote an implementation for levels=n in this commit

juh2 commented 2 years ago

Thank you very much!

This looks very promising. While I can't comment on most of your thoughts due to my lack of org-mode knowledge, I have one remark.

I use ConTeXt for a couple of years now and I never found it useful to not use the latest ConTeXt version. ConTeXt was actively developed in all that time and all versions in distributions of all kinds were so old that I never used them. For anyone who wants to start using ConTeXt today I would recommend install the latest version as described here: https://wiki.contextgarden.net/Installation

You may ask more experienced users if that is really consensus or just my habit. But I would encourage you to skip your fourth requirement.

Jason-S-Ross commented 2 years ago

If you have time to try out #29 I would appreciate any feedback. I am optimistic about this implementation.

Couple of things to note:

  1. ALL special sectioning commands are included in the document preamble in a new snippet headlines-default. If you want special headlines, you can just define a different snippet. You will have to define as many headline levels as you will use.
  2. There is no mechanism to only define the NoToc headlines that are actually used anymore. I don't think that's a big loss to anyone. It just wastes a bit of space in the file.
  3. We don't use startsection/startsubsection etc. anymore. We only use startsectionlevel and ConTeXt takes care of the sectioning automatically. This makes it harder to tell what level of sectioning you're looking at in the mkiv file, but the pdf should look the same.
  4. Emacs does not know what the names of sections are anymore

This also includes unnumbered sections in the TOC unless they are :UNNUMBERED: notoc, which is the behavior seen in other backends (except LaTeX).

To make use of this with e.g. chapter-first sectioning, use the following snippet:

\definehead
  [titleNoToc]
  [title]
\definehead
  [chapterNoToc]
  [chapter]
\setuphead[title][incrementnumber=list]
\definesectionlevels
  [default]
  [{chapter, title},
   {section, subject},
   {subsection, subsubject},
   {subsubsection, subsubsubject},
   {subsubsubsection, subsubsubsubject},
   {subsubsubsubsection, subsubsubsubsubject},
   {subsubsubsubsubsection, subsubsubsubsubsubject},
   {subsubsubsubsubsubsection, subsubsubsubsubsubsubject},
   {subsubsubsubsubsubsubsection, subsubsubsubsubsubsubsubject},
   {subsubsubsubsubsubsubsubsection, subsubsubsubsubsubsubsubsubject},
   {subsubsubsubsubsubsubsubsubsection, subsubsubsubsubsubsubsubsubsubject}]
\definesectionlevels
  [NoToc]
  [{chapterNoToc, titleNoToc},
   {sectionNoToc, subjectNoToc},
   {subsectionNoToc, subsubjectNoToc},
   {subsubsectionNoToc, subsubsubjectNoToc},
   {subsubsubsectionNoToc, subsubsubsubjectNoToc},
   {subsubsubsubsectionNoToc, subsubsubsubsubjectNoToc},
   {subsubsubsubsubsectionNoToc, subsubsubsubsubsubjectNoToc},
   {subsubsubsubsubsubsectionNoToc, subsubsubsubsubsubsubjectNoToc},
   {subsubsubsubsubsubsubsectionNoToc, subsubsubsubsubsubsubsubjectNoToc},
   {subsubsubsubsubsubsubsubsectionNoToc, subsubsubsubsubsubsubsubsubjectNoToc},
   {subsubsubsubsubsubsubsubsubsectionNoToc, subsubsubsubsubsubsubsubsubsubjectNoToc}]
juh2 commented 2 years ago

How can I try it out? I am using straight. I don't see the branch:

$ git branch -a
    * main
      remotes/origin/HEAD -> origin/main
      remotes/origin/develop
      remotes/origin/feat-readme
      remotes/origin/feat-table-cust
      remotes/origin/fix-enum-spacing
      remotes/origin/fix-footnote
      remotes/origin/fix-table-split
      remotes/origin/fix-toc-t
      remotes/origin/homework
      remotes/origin/main
      remotes/origin/ox-context
      remotes/origin/quickfix
      remotes/origin/test
      remotes/origin/wip-toc
Jason-S-Ross commented 2 years ago

I think you need to git fetch. I don't use straight, I use doom, but my config looks like

(package! ox-context
  :recipe (:host github :repo "Jason-S-Ross/ox-context" )
  :pin "24264bc4ce1cf8ddc75cee3ce000b7c181eced0b" )

because it works better in doom to pin a commit than pin a branch.

juh2 commented 2 years ago

I tried it out. I can make a document and played around with

#+options: toc:2
#+context_header_extra: \environment org

org.tex is the snippet you cited above.

I could insert a part headline level in org.tex and it works.

I can change the toc depth.

I can use :UNNUMBERED: toc/notoc and get headlines unnumbered with toc or without toc.

Please ask more experienced org-mode users as I don't have a real world example in org-mode. See 3. above.

I run into some minor issues that might be unrelated to ox-context.

  1. With the two lines cited above the #+title is included in the toc as first entry. This goes away if I also use several of my environments. Don't know why.
  2. There is no pagebreak between title and toc. I am not sure how to customize this.
  3. My books have these pages:
    • title page
    • titleback with imprint
    • dedication page
    • epigraph page
    • table of contents
    • mainmatter block
    • backmatter stuff like bibliography I have no idea how to achieve this in org-mode.
Jason-S-Ross commented 2 years ago

I run into some minor issues that might be unrelated to ox-context.

  1. With the two lines cited above the #+title is included in the toc as first entry. This goes away if I also use several of my environments. Don't know why.

The title-article and title-report commands both use \title to place a title. If your sectioning structure includes title and use one of these snippets, you can override the OrgMakeTitle command with e.g.

#+CONTEXT_HEADER_EXTRA: \define\OrgMakeTitle{\tfa \documentvariable{metadata:title}%
#+CONTEXT_HEADER_EXTRA:   \doifnot{\documentvariable{metadata:subtitle}}{}{%
#+CONTEXT_HEADER_EXTRA:   \blank[force,1*big] \tfa \documentvariable{metadata:subtitle}}}

to avoid this problem.

  1. There is no pagebreak between title and toc. I am not sure how to customize this.

This can be fixed by adding a \pagebreak to the definition of OrgMakeTitle shown above

  1. My books have these pages:
  • title page

Modify the OrgMakeTitle command to your liking.

  • titleback with imprint

Depending on your requirements, you could either roll this into the definition of OrgMakeTitle or just wrap the content in #+CONTEXT: your command here keywords that specify the setup/teardown for the titleback and imprint. Org doesn't have document semantics for this so you have to roll your own.

  • dedication page

  • epigraph page

See above.

  • table of contents

You can place the table of contents anywhere in the document using #+TOC: headlines. By default, the table of contents will be placed after the title, but if you want it somewhere else, you can set #+OPTIONS: toc:nil and use the #+TOC keyword. The wiki describes how to set up the table of contents.

  • mainmatter block

  • backmatter stuff like bibliography I have no idea how to achieve this in org-mode.

ConTeXt supports document part commands like startfrontmatter, startbodymatter, startappendices, and startbackmatter. In ox-context, you can select that headlines be placed in specific sections by adding FRONTMATTER, BACKMATTER, or APPENDIX to the headline property drawer. Headlines with those properties are placed within the corresponding document parts. Note that these semantics are not part of Org mode, they are unique to ox-context.