5

I'm trying to define a command which creates a part/chapter/section/subsection/... depending on the last defined part/chapter/section/subsection/...

It should look like this pseudo code:

global string currentSection;

function level(arg, sectioningArgs ...) { 
  switch(arg) {
    case '+' {
      switch(currentSection) {
        case 'none' {
          \part(sectioningArgs)
        }
        case 'part' {
          \chapter(sectioningArgs)
        }
        case 'chapter' {
          \section(sectioningArgs)
        }
        ...
      }
    }
    case '-' {
      ...
    }      
    case '0' {
      ...
    }
  }
}

(just imagine a 'break' after each case ...)

The usage should be like follows:

\documentclass[a4paper,12pt,oneside]{book}

\newcommand{\level}[<?>]{<?>}

\begin{document}
  \level{+}{A part}
  \level{+}{A chapter}
  \level{+}{A section}
  \level{0}{Another section}
  \level{-}{A chapter}
  \level{-}{A part}
\end{document}

Rationale: I often find myself changing subsections to sections and so on in subfiles I include in my main document --- this should automate the process.

Any help is greatly appreciated, thank you in advance.

Werner
  • 603,163
MCH
  • 165
  • 4

2 Answers2

5

The keys +, - and 0 are not sufficient, because typically you need to jump up levels when a chapter finishes.

The \level macro has a mandatory argument; it can be +, -, = or an integer (between –1 and 5, extremes included).

I find using +, - or = error prone, unless your editor allows you to fold at \level. However, it's easy to use the absolute level.

\documentclass{book}

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\level}{m}
 {
  \mch_level:n { #1 }
 }

\int_new:N \g_mch_level_int

\cs_new_protected:Nn \mch_level:n
 {
  \str_case:nnF { #1 }
   {
    {+}{ \int_gincr:N \g_mch_level_int }
    {-}{ \int_gdecr:N \g_mch_level_int }
    {=}{ }
   }
   { \int_gset:Nn \g_mch_level_int { #1 } }
  \int_case:nnF { \g_mch_level_int }
   {
    {-1}{\part}
     {0}{\chapter}
     {1}{\section}
     {2}{\subsection}
     {3}{\subsubsection}
     {4}{\paragraph}
     {5}{\subparagraph}
   }
   {Beyond limit!}
 }
\ExplSyntaxOff

\begin{document}

\mainmatter

\level{0}{Introduction}

Text

\level{-}{First part}

\level{+}{First chapter}

\level{+}{First section}

\level{+}{First subsection}

\level{=}{Second subsection}

\level{-}{Second section}

\level{+}{First subsection}

\level{=}{Second subsection}

\level{0}[Second chapter]{Second chapter with a very very very long title}

\end{document}

enter image description here

egreg
  • 1,121,712
4

Here is a very elementary implementation that doesn't include error checking (but can be added) and a slight interface change - an optional argument rather than a mandatory one for switching the relative level of the sectional unit.

enter image description here

\documentclass{book}

\newcounter{cursecdepth}
\setcounter{cursecdepth}{-1}
\makeatletter
\@namedef{seclevel@0}{\part}
\@namedef{seclevel@1}{\chapter}
\@namedef{seclevel@2}{\section}
\@namedef{seclevel@3}{\subsection}
\@namedef{seclevel@4}{\subsubsection}
\@namedef{seclevel@5}{\paragraph}
\@namedef{seclevel@6}{\subparagraph}

\newcommand{\level}[1][=]{%
  \ifnum\pdfstrcmp{#1}{+}=0
    \stepcounter{cursecdepth}% Jump down a level
  \else\ifnum\pdfstrcmp{#1}{-}=0
    \addtocounter{cursecdepth}{-1}% Jump up a level
  \else\ifnum\pdfstrcmp{#1}{=}=0
    % Stay at this level
  \else
    \setcounter{cursecdepth}{#1}% Set the current level
  \fi\fi\fi
  \csname seclevel@\arabic{cursecdepth}\endcsname
}
\makeatother
\newcommand{\uplevel}{\addtocounter{cursecdepth}{-1}}
\newcommand{\downlevel}{\stepcounter{cursecdepth}}

\begin{document}

\tableofcontents

\level[+]{A part}
\level[+]{A chapter}
\level[+]{A section}
\level[2]{Another section}
\level[=]{Yet another section}
\level   {Another, final section}
\level[+]{A subsection}
\level[1]{A chapter}
\level[-]{A part}

\end{document}

I've set the counter cursecdepth to -1 at the start, which requires you to use \level[+] to start with a \part. However, it would be more intuitive to start with \level (or \level[0]) as a \part.

Fixed-depth jumping is achieved by setting the optional parameter to a number, where the number indicates the level of the sectional unit:

  0. Part
  1. Chapter
  2. Section
  3. Subsection
  4. Subsubsection
  5. Paragraph
  6. Subparagraph

One can use \uplevel or \downlevel to step the current level as needed.

Werner
  • 603,163
  • What if a chapter end with a subsubsection? – egreg Sep 08 '15 at 16:51
  • I decided to accept egreg's answer, because it deals with the issue of `jumping up'. But it was really my fault --- I didn't think of this beforehand and didn't include it in the question. Therefore Werner's answer is correct as well. It's a shame that it's impossible to accept multiple answers. – MCH Sep 08 '15 at 17:38
  • @MCH: You can still vote on the answers; that's different from accepting. I'll update my answer to accommodate for such jumping. – Werner Sep 08 '15 at 17:39