5

Note: The ideas in this question and accepted answer have been composed into a CTAN package called "modular".


Consider the following subimportlevel macro:

packages.tex

\usepackage{import}
\usepackage{coseoul}

\newcommand{\subimportlevel}[3]{
\setcounter{currentlevel}{#3}
\subimport*{#1}{#2}
\setcounter{currentlevel}{#3}
}

The purpose of the macro is to import a modular piece of a document while getting the section/subsection levels right, regardless of what imported the sub-document. The problem with this macro is that the subimported file can change currentlevel so that the final \setcounter{currentlevel}{#3} doesn't do the right thing (it's supposed to reset currentlevel to whatever it was before the \subimport.

Here's an example usage illustrating the problem:

main.tex

\documentclass{article}
\input{packages.tex}

\author{Daniel Sank}
\title{Example}

\begin{document}
\maketitle
\subimportlevel{./}{content}{5}
\end{document}

content.tex

\subimportlevel{./}{section1}{\value{currentlevel}}  % <-- can change currentlevel inside section1.tex
\subimportlevel{./}{section2}{\value{currentlevel}}

section1.tex

\levelstay{Section 1}
This is the first section

\leveldown{A subsection}
This is a subsection

\levelstay{Another subsection}
This is another subsection of the first section.

section2.tex

\levelstay{Section 2}
This is the second section

\leveldown{Subsection}
This should be a subsection of the second section.

\levelstay{Another subsection}
This is supposed to be another subsection of the second section.

Building main.tex results in the following output

enter image description here

Note that the second section is numbered as a subsection. How can I fix this? Is there a way to expand the \value{currentlevel} before the importing happens?

  • \levelstay and \leveldown? Where are those macros defined? –  May 17 '15 at 04:44
  • @ChristianHupfer They're from coseoul. I'd be happy to achieve this without coseoul though. – DanielSank May 17 '15 at 06:38
  • Am probably completely misunderstanding what you are trying to achieve but you can use things like \let\subparagraph\paragraph \let\paragraph\subsubsection \let\subsubsection\subsection \let\subsection\section \let\section\chapter – Aubrey Blumsohn May 17 '15 at 08:56
  • Do you have cross references within or between your sub-documents? – Aubrey Blumsohn May 17 '15 at 09:07
  • @AubreyBlumsohn Yes. In fact I have several question on this site about that. I intend to post my own answers to them once I figure out this present issue. – DanielSank May 17 '15 at 16:10
  • My inclination would be to avoid this approach altogether and use sed to pre-process the files you are importing. – Aubrey Blumsohn May 17 '15 at 18:23
  • @AubreyBlumsohn: That's too bad. This whole thing has made me understand that TeX is not well suited to actually programming anything. Global variables and fixed depth section markers like \section preclude rational programming. – DanielSank May 17 '15 at 18:41
  • Don't think that - but if you want to go this route (and I think it is interesting) I think you need to make this a whole lot simpler so that it can be debugged. You have nested subimportlevels for a start so my head is spinning. Does a simple \setcounter{currentlevel}{5} do as expected? Without looking at the packages involved I don't know whether the current level is actually even set before it is used in a header. – Aubrey Blumsohn May 18 '15 at 09:10

1 Answers1

3

Edit

My first definition of \subimportlevel (see below) imports subfiles in a group to protect \mycurrentlevel. In this new solution, I use multiple macros (\@currrentlevel0, \@currentlevel1, ...) so no group is required.

\makeatletter
\newcounter{currentimportdepth}
\setcounter{currentimportdepth}{0}
\newcommand{\subimportlevel}[2]{
  \expandafter\edef\csname @currentlevel\thecurrentimportdepth\endcsname{\thecurrentlevel}
  \addtocounter{currentimportdepth}{1}
  \addtocounter{curentlevel}{-1}
  \subimport*{#1}{#2}
  \addtocounter{currentimportdepth}{-1}
  \setcounter{currentlevel}{\csname  @currentlevel\thecurrentimportdepth\endcsname}
}
\makeatother

First solution

I'm not sure I understand the question. The following solution could meet your need ...

\documentclass{article}

\usepackage{import}
\usepackage{coseoul}

\newcommand{\subimportlevel}[2]{
  \edef\mycurrentlevel{\thecurrentlevel}
  \bgroup
  \subimport*{#1}{#2}
  \egroup
  \setcounter{currentlevel}{\mycurrentlevel}
}

\begin{document}
\levelstay{A}
\subimportlevel{./}{content}
\levelstay{B}
\end{document}

section1.tex

\levelstay{Section 1}
This is the first section

\leveldown{A subsection}
This is a subsection

\levelstay{Another subsection}
This is another subsection of the first section.

section2.tex

\levelstay{Section 2}
This is the second section

\leveldown{Subsection}
This should be a subsection of the second section.

\levelstay{Another subsection}
This is supposed to be another subsection of the second section.

content.tex

\subimportlevel{./}{section1}
\levelstay{Test}
\subimportlevel{./}{section2}
\leveldown{Test}
\subimportlevel{./}{section2}
Stefan Pinnow
  • 29,535
Paul Gaborit
  • 70,770
  • 10
  • 176
  • 283
  • This looks like what I've been trying to do. Would you mind annotating the solutions a bit? For example, in the first solution, what is the purpose of the \bgroup and \egroup? Is that protecting mycurrentlevel from mutation inside nested invocations of subimportlevel? – DanielSank May 21 '15 at 03:58
  • @DanielSank Exactly: a group (between \bgroup and \egroup, or between \begingroup and \endgroup, or between { and }) confines most changes. It works in this particular MWE... But, I think that it is a bad general solution. – Paul Gaborit May 21 '15 at 05:47
  • Very curious as to why you say this is a bad solution. It seems like you've just taught me how to get TeX to use rational scoping rules! This makes so many things easier. – DanielSank May 21 '15 at 06:03
  • @DanielSank LaTeX sectioning commands (or \input, or \import) are not environments (or groups). It is a design choice. Here, by introducing a group, we change this choice just to protect \mycurrentlevel... – Paul Gaborit May 21 '15 at 06:27
  • I think I understand. Normally we would have to \subimportlevel all of the files in content.tex within a single macro in order to get proper control over currentlevel. Using the group makes it a little easier. – DanielSank May 21 '15 at 07:13
  • This doesn't actually do what we want. Section "A" and "Section 1" are at the same level, whereas we want Section 1 to be a level below A. Just using \leveldown{Section 1} wouldn't count because the whole point is to have section1.tex stand on its own, i.e. be able to use it as it's own complete document. I think this might be fixable with just some adjustments to the imports. Working on it. – DanielSank Sep 07 '16 at 06:21
  • Is there a way to (optionally) make \thecurrentlevel increment +1 within the stuff imported by \subimportlevel? – DanielSank Sep 07 '16 at 06:41
  • In other words, I think we need a \subimportleveldown. – DanielSank Sep 07 '16 at 06:52
  • @DanielSank With coseoul package, you can't down the current level without insert a title. So, your new \subimportleveldown macro should insert a new title before import a file. – Paul Gaborit Sep 10 '16 at 06:24
  • Actually, I figured out exactly how to do what I want. We just need an \addtocounter{currentlevel}{-1} right before the \subimport. I've edited your answer to indicate this. – DanielSank Sep 10 '16 at 08:27