根据目录树动态创建文档章节

根据目录树动态创建文档章节

为了创建文档结构,我通常使用如下方法:

\section{1}
  Text for chapter 1

\section{2}
  Text for chapter 2

  \subsection{2.1}
  Text for chapter 2.1

    \subsubsection{2.1.1}
      Text for chapter 2.1.1

      \paragraph{2.1.1.1}\mbox{}\\
      Text for chapter 2.1.1.1

是否可以\section \subsection \subsubsection\paragraph ...根据目录结构自动处理?我的想法是拥有树状目录结构,作为文档创建的模板。在此示例中,所需文本"Text for chapter ..."位于chapter.tex文件内:

./1/chapter.tex
./2/chapter.tex
./2/2.1/chapter.tex
./2/2.1/2.1.1/chapter.tex
./2/2.1/2.1.1/2.1.1.1/chapter.tex

以下示例与上一个示例相同,只是所需文本包含在具有不同名称的文件中(每个目录一个文件)。这样更好,因为在编辑器中,您可以看到章节的正确名称,而不是chapter.txt每个文档部分的名称:

./1/1.tex
./2/2.tex
./2/2.1/2_1.tex
./2/2.1/2.1.1/2_1_1.tex
./2/2.1/2.1.1/2.1.1.1/2_1_1_1.tex

作为奖励,我还希望自动标记每个章节\section \subsection \subsubsection\paragraph ...,例如等等\label{2.1.1}

我猜我需要某种预处理器,它首先按字母顺序或数字下划线对目录进行排序,然后编写最终文档。我不确定这个 LaTeX 是否可以做到,或者是否需要一些外部工具。多平台解决方案很好,但我的主要操作系统是 Linux。谢谢。

答案1

这是一个解决方案

笔记

  1. 解决方案使用(la)TeX循环。
  2. 文件名更改为 1_1_1 -->1+1+1 (这样更简单)

\documentclass{article}
\usepackage{lipsum}

\setcounter{secnumdepth}{4}

\newif\ifmoreinput
\newcounter{sec}
\newcounter{ssec}[sec]
\newcounter{sssec}[ssec]
\newcounter{parg}[sssec]
\begin{document}
\loop
\stepcounter{section}%
\stepcounter{sec}%
\edef\mtpath{\thesection}%
\edef\mtfile{\thesec}%
\IfFileExists{\mtpath/\mtfile.tex}{%
\moreinputtrue%
\addtocounter{section}{-1}%
\let\SomeMagicCommandThatHoldsChapterNameGoesHere\section
\input{\mtpath/\mtfile.tex}%
{\loop
\stepcounter{subsection}%
\stepcounter{ssec}%
\edef\mtpath{\thesection/\thesubsection}%
\edef\mtfile{\thesec+\thessec}%
\IfFileExists{\mtpath/\mtfile.tex}{%
\moreinputtrue%
\addtocounter{subsection}{-1}%
\let\SomeMagicCommandThatHoldsChapterNameGoesHere\subsection
\input{\mtpath/\mtfile.tex}%
{\loop
\stepcounter{subsubsection}%
\stepcounter{sssec}%
\edef\mtpath{\thesection/\thesubsection/\thesubsubsection}%
\edef\mtfile{\thesec+\thessec+\thesssec}%
\IfFileExists{\mtpath/\mtfile.tex}{%
\moreinputtrue%
\addtocounter{subsubsection}{-1}%
\let\SomeMagicCommandThatHoldsChapterNameGoesHere\subsubsection
\input{\mtpath/\mtfile.tex}%
{\loop
\stepcounter{paragraph}%
\stepcounter{parg}%
\edef\mtpath{\thesection/\thesubsection/\thesubsubsection/\theparagraph}%
\edef\mtfile{\thesec+\thessec+\thesssec+\theparg}%
\IfFileExists{\mtpath/\mtfile.tex}{%
\moreinputtrue%
\addtocounter{paragraph}{-1}%
\let\SomeMagicCommandThatHoldsChapterNameGoesHere\paragraph
\input{\mtpath/\mtfile.tex}}{\moreinputfalse}%
\ifmoreinput\repeat}}{\moreinputfalse}%
\ifmoreinput\repeat}}{\moreinputfalse}%
\ifmoreinput\repeat}}{\moreinputfalse}%
\ifmoreinput\repeat

\end{document}

更新这里有一个更好的方法:我们用它makemymain.tex来生成mymain.tex 这个新文件,它将结构良好,并且更有助于使用乳胶编辑器(我会尽可能解释)

制作我的主程序

\documentclass{article}
\usepackage{lipsum}
\setcounter{secnumdepth}{4}
\newcommand{\SomeMagicCommandThatHoldsChapterNameGoesHere}[1]{{#1}}

\newread\mtread
\newwrite\mtwrite
\immediate\openout\mtwrite=mymain.tex

\newcommand{\mtadd}[1]{\immediate\write\mtwrite{\string#1}}
\newcommand{\mtinput}[1]{%
\moreinputtrue%
\openin\mtread=\mtpath/\mtfile.tex
\read\mtread to \myread
\closein\mtread
\immediate\write\mtwrite{\string#1\myread}
\immediate\write\mtwrite{\string\input {\mtpath/\mtfile.tex}}}

% creating preamble of mymain.tex
\mtadd{\documentclass{article}}
\mtadd{\usepackage{lipsum}}
\mtadd{\setcounter{secnumdepth}{4}}
\mtadd{\newcommand{\string\SomeMagicCommandThatHoldsChapterNameGoesHere}[1]{}}
\mtadd{\begin{document}}

\AtEndDocument{\mtadd{\end{document}}}

\newif\ifmoreinput
\newcounter{sec}
\newcounter{ssec}[sec]
\newcounter{sssec}[ssec]
\newcounter{parg}[sssec]
\begin{document}
\tableofcontents
\loop
\stepcounter{section}%
\stepcounter{sec}%
\edef\mtpath{\thesection}%
\edef\mtfile{\thesec}%
\IfFileExists{\mtpath/\mtfile.tex}{%
\mtinput{\section}%
{\loop
\stepcounter{subsection}%
\stepcounter{ssec}%
\edef\mtpath{\thesection/\thesubsection}%
\edef\mtfile{\thesec+\thessec}%
\IfFileExists{\mtpath/\mtfile.tex}{%
\mtinput{\subsection}%
{\loop
\stepcounter{subsubsection}%
\stepcounter{sssec}%
\edef\mtpath{\thesection/\thesubsection/\thesubsubsection}%
\edef\mtfile{\thesec+\thessec+\thesssec}%
\IfFileExists{\mtpath/\mtfile.tex}{%
\mtinput{\subsubsection}%
{\loop
\stepcounter{paragraph}%
\stepcounter{parg}%
\edef\mtpath{\thesection/\thesubsection/\thesubsubsection/\theparagraph}%
\edef\mtfile{\thesec+\thessec+\thesssec+\theparg}%
\IfFileExists{\mtpath/\mtfile.tex}{%
\mtinput{\paragraph}}{\moreinputfalse}%
\ifmoreinput\repeat}}{\moreinputfalse}%
\ifmoreinput\repeat}}{\moreinputfalse}%
\ifmoreinput\repeat}}{\moreinputfalse}%
\ifmoreinput\repeat

\end{document}

更新 2 避免扩展问题(读写)

\newcommand{\SomeMagicCommandThatHoldsChapterNameGoesHere}[1]{{#1}} 

替换为

\newcommand{\SomeMagicCommandThatHoldsChapterNameGoesHere}[1]{{\unexpanded{#1}}}

回到文件命名的原始约定2_1_1.tex

\catcode`\_12\relax 

在第一个循环之前添加

制作我的主程序

\documentclass{article}
\usepackage{lipsum}
\newcommand{\SomeMagicCommandThatHoldsChapterNameGoesHere}[1]{{\unexpanded{#1}}}

\newread\mtread
\newwrite\mtwrite
\immediate\openout\mtwrite=mymain.tex

\newcommand{\mtadd}[1]{\immediate\write\mtwrite{\string#1}}
\newcommand{\mtinput}[1]{%
\moreinputtrue%
\openin\mtread=\mtpath/\mtfile.tex
\read\mtread to \myread
\closein\mtread
\immediate\write\mtwrite{\string#1\myread}
\immediate\write\mtwrite{\string\input {\mtpath/\mtfile.tex}^^J}}

% creating preamble of mymain.tex
\mtadd{\documentclass{article}}
\mtadd{\usepackage{lipsum}}
\mtadd{\setcounter{secnumdepth}{4}}
\mtadd{\newcommand{\string\SomeMagicCommandThatHoldsChapterNameGoesHere}[1]{}}
\mtadd{\begin{document}}

\AtEndDocument{\mtadd{\end{document}}}

\newif\ifmoreinput
\newcounter{sec}
\newcounter{ssec}[sec]
\newcounter{sssec}[ssec]
\newcounter{parg}[sssec]
\begin{document}
\tableofcontents
\catcode`\_12\relax
\loop
\stepcounter{section}%
\stepcounter{sec}%
\def\mtpath{\thesection}%
\def\mtfile{\thesec}%
\IfFileExists{\mtpath/\mtfile.tex}{%
\mtinput{\section}%
{\loop
\stepcounter{subsection}%
\stepcounter{ssec}%
\def\mtpath{\thesection/\thesubsection}%
\def\mtfile{\thesec_\thessec}%
\IfFileExists{\mtpath/\mtfile.tex}{%
\mtinput{\subsection}%
{\loop
\stepcounter{subsubsection}%
\stepcounter{sssec}%
\def\mtpath{\thesection/\thesubsection/\thesubsubsection}%
\def\mtfile{\thesec_\thessec_\thesssec}%
\IfFileExists{\mtpath/\mtfile.tex}{%
\mtinput{\subsubsection}%
{\loop
\stepcounter{paragraph}%
\stepcounter{parg}%
\def\mtpath{\thesection/\thesubsection/\thesubsubsection/\theparagraph}%
\def\mtfile{\thesec_\thessec_\thesssec_\theparg}%
\IfFileExists{\mtpath/\mtfile.tex}{%
\mtinput{\paragraph}}{\moreinputfalse}%
\ifmoreinput\repeat}}{\moreinputfalse}%
\ifmoreinput\repeat}}{\moreinputfalse}%
\ifmoreinput\repeat}}{\moreinputfalse}%
\ifmoreinput\repeat

\end{document}

主文件

\documentclass{article}
\usepackage{lipsum}
\setcounter{secnumdepth}{4}
\newcommand{\SomeMagicCommandThatHoldsChapterNameGoesHere}[1]{}
\begin{document}
\section{chapter 1} 
\input{1/1.tex}

\section{chapter 2} 
\input{2/2.tex}

\subsection{chapter 2.1} 
\input{2/2.1/2_1.tex}

\subsubsection{chapter 2.1.1} 
\input{2/2.1/2.1.1/2_1_1.tex}

\paragraph{chapter 2.1.1.1} 
\input{2/2.1/2.1.1/2.1.1.1/2_1_1_1.tex}

\subsection{chapter 2.2} 
\input{2/2.2/2_2.tex}

\subsubsection{chapter 2.2.1} 
\input{2/2.2/2.2.1/2_2_1.tex}

\end{document}

在此处输入图片描述

答案2

这种方法可能不是一个好主意,LaTeX 旨在为您处理编号(例如,当您稍后决定在 1 和 2 之间添加一个部分时)。

如果你无论如何都想这么做,那么脚本语言可能是最简单的方法。Perl 中的示例:

use File::Find;
use Cwd;
# get working directory for script
$cwd1 = getcwd();

# find all tex files recursively, store the path relative to cwd1
find(sub{ push(@allfiles,substr(getcwd(),length($cwd1))."/".$_) if $_=~/tex$/; },'.');

# sort the file list to get the right order
# note: tex files are called 0chapter.tex for sorting purposes
foreach $file(sort @allfiles){
    # count the number of underscores minus 2 (/1/0chapter.tex is level 0)
    $strlevel = "sub" x (($file =~ tr#/#/#)-2);
    # read the file
    open(IN,"<$cwd1$file");
    chomp(@contents = <IN>);
    close(IN);
    # print the first line of the file as (subsubsub)section title and the rest as contents
    print "\\$strlevel"."section\{$contents[0]\}\n".join("\n",@contents[1..$#contents])."\n";
    close(IN);
}

添加某个\newcommand{\subsubsubsection}[1]{\paragraph{#1}\mbox{}\\}地方,您就设置好了。此脚本的示例输出,使用您的目录结构:

\section{Title of foo}
contents of foo
\section{Title of bar}
contents of bar
\subsection{Title of foobar}
contents of foobar
\subsubsection{Title of foobarbaz}
contents of foobarbaz
\subsubsubsection{Title of foobarbazqux}
contents of foobarbazqux

相关内容