0
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

参照をいい感じにしつつTeXファイル分割

Last updated at Posted at 2021-02-12

##背景

  • TeXファイルが長くなったので節ごとに分割したい(します)。
  • 節ごとのTeXファイルはそれぞれごとにコンパイルできてほしい。
  • \autorefとかもいい感じに振る舞ってほしい。

上二つを実現する方法としてはsubfilesを使う方法がありますが、リンク先の記事でも言及されている通り、あまり3つ目の欲望が満たせそうにないので、今回は「仕掛け」を用いる方法を使います。
この記事は、上記の欲望が達成されたような気がする、という報告です。
GitHubへ

##フォルダ構成
フォルダ構成は以下の通りとします:

フォルダ構造
Main
├── MainFile.tex
├── MainFile.aux など
├── Style
│   └── Test.sty
└── Sub
    ├── SubFile.tex
    └── SubFile.aux など

SubFile.tex は例えば「Section 5に対応するファイル」のような感じで、
MainFile.tex はなんか全部inputされてる感じのやつを想定してます。

###中身
中身は以下の通りであるとします (「仕掛け」の記事で紹介されている「仕掛け」が施してあります)。

MainFile.tex
\newcommand{\MainFile}{MainFile}
\documentclass[uplatex,dvipdfmx]{jsarticle}
\input{Style/Test.sty}
\begin{document}
\section{親ファイル}\label{section: Main section}\begin{thm}\label{thm: main theorem}
  え?
\end{thm}
\begin{lem}\label{lem: main lemma}
  え?
\end{lem}

\input{Sub/SubFile.tex}

\autoref{section: Main section},\autoref{section: sub section},
\autoref{thm: main theorem},\autoref{thm: sub theorem},
\autoref{lem: main lemma},\autoref{lem: sub lemma},
\ref{section: Main section},\ref{section: sub section},
\ref{thm: main theorem},\ref{thm: sub theorem},
\ref{lem: main lemma},\ref{lem: sub lemma},

\end{document}
Sub/SubFile.tex
\ifcsname MainFile\endcsname\else
\documentclass[uplatex,dvipdfmx]{jsarticle}
\input{../Style/Test.sty}
\begin{document}
\fi

\SetTrueSecNumber{section: sub section}
\section{子ファイル}\label{section: sub section}\begin{thm}\label{thm: sub theorem}
  え?
\end{thm}
\begin{lem}\label{lem: sub lemma}
  え?
\end{lem}

\autoref{section: Main section},\autoref{section: sub section},
\autoref{thm: main theorem},\autoref{thm: sub theorem},
\autoref{lem: main lemma},\autoref{lem: sub lemma},
\ref{section: Main section},\ref{section: sub section},
\ref{thm: main theorem},\ref{thm: sub theorem},
\ref{lem: main lemma},\ref{lem: sub lemma},

\ifcsname MainFile\endcsname\else
\end{document}
\fi

「仕掛け」の意味は当該記事を参照してください。
この仕掛けによって、MainFile.tex と SubFile.tex はそれぞれごとにコンパイルすることができます (もちろん、Test.sty にめちゃくちゃなことが書いてあったらエラー吐きますが)。
Style ファイルには以下の (上のファイルたちをまともに出力させるための) 事柄が既に書かれているとします (これらの意味については説明しません。ハイパーリンク系は青色にしてます)。

Style/Test.sty
\usepackage{xcolor}
\usepackage{graphicx}
\usepackage[setpagesize=false]{hyperref}
\usepackage{aliascnt}
\hypersetup{colorlinks=true,citecolor=blue,linkcolor=blue,urlcolor=blue,}

\usepackage{amsthm}
\theoremstyle{definition}
\newtheorem{thm}{定理}[section]
\newaliascnt{lem}{thm}
\newtheorem{lem}[lem]{補題}
\aliascntresetthe{lem}
\renewcommand{\sectionautorefname}{}
\newcommand{\thmautorefname}{定理}
\newcommand{\lemautorefname}{補題}

Subfilesの記事の最後の方にも書いてある通りですが、このままだと参照とかはあんまりいい感じじゃないです。なので、この.styにいろいろ追記して参照とかをいい感じにしていきます。

##やったこと

  • 参照 (\autorefとか\refとか) もいい感じにした。

###「いい感じに」の定義

  • MainFile.tex では通常通りに出力してほしい。
  • MainFile.tex のラベルであって SubFile.tex 内のラベルにないものを SubFile.tex で参照した場合は、MainFile.tex 内での正しいナンバリングが (ハイパーリンクなしで) 印字されてほしい。

これらを実現するために、\label\ref\autorefを再定義します。

##再定義
.sty ファイルに (\usepackage{hyperref}よりも後に) 以下を書き込みます(コメントは直前に行った作業の説明です):

Style/Test.sty

\usepackage{letltxmacro}%monkey patch
\makeatletter
\newcommand{\Test@FirstGroup}[5]{#1}%5個のうちの1番目
\newcommand{\Test@FourthGroup}[5]{#4}%5個のうちの4番目

\newcommand{\Test@NumberingPrint}[1]{%
 \expandafter\Test@FirstGroup%
 \romannumeral-`0\csname r@MainFile: #1\endcsname%
}%%ラベルに対してそのラベルが振られているものの番号(3.5とか)を文字列として返す

\def\Test@@NamingPrint#1.{%
  \csname #1autorefname\endcsname%
}
\newcommand{\Test@NamingPrint}[1]{%
  \expandafter\Test@@NamingPrint%
  \romannumeral-`0\expandafter\Test@FourthGroup%
  \romannumeral-`0\csname r@MainFile: #1\endcsname%
}%%ラベルに対して「定理3.5」や「補題1.9」や「節6」などを文字列として返す


\AtBeginDocument{%%hyperrefよりあとから書き換えるためにAtBeginDocumentする

  \LetLtxMacro{\Test@LetLabel}{\label}%labelをコピー(letのようなもの)
  \newcommand{\Test@TrueLabel}[1]{%
    \ifcsname MainFile\endcsname%
    \Test@LetLabel{MainFile: #1}\else%
    \Test@LetLabel{SubFile: #1}\fi%
  }%コンパイル場所によってlabelの振る舞いを変える
  \renewcommand{\label}[1]{\Test@TrueLabel{#1}}%label再定義


  \LetLtxMacro{\Test@LetRef}{\ref}%refをコピー
  \newcommand{\Test@SubFile@TrueRef}[1]{%
    \ifcsname r@SubFile: #1\endcsname%
    \Test@LetRef{SubFile: #1}\else%
    \textcolor{magenta}{\Test@NumberingPrint{#1}}\fi%
  }%SubFileでのrefの振る舞い
  \newcommand{\Test@TrueRef}[1]{%
    \ifcsname MainFile\endcsname%
    \Test@LetRef{MainFile: #1}\else%
    \Test@SubFile@TrueRef{#1}\fi%
  }%コンパイル場所によってrefの振る舞いを変える
  \renewcommand{\ref}[1]{\Test@TrueRef{#1}}%ref再定義

  
  \LetLtxMacro{\Test@LetAutoref}{\autoref}%autorefをコピー
  \newcommand{\Test@SubFile@TrueAutoref}[1]{%
    \ifcsname r@SubFile: #1\endcsname%
    \Test@LetAutoref{SubFile: #1}\else%
    \textcolor{magenta}{\Test@NamingPrint{#1}}\fi%
  }%SubFileでのautorefの振る舞い
  \newcommand{\Test@TrueAutoref}[1]{%
    \ifcsname MainFile\endcsname%
    \Test@LetAutoref{MainFile: #1}\else%
    \Test@SubFile@TrueAutoref{#1}\fi%
  }%コンパイル場所によってautorefの振る舞いを変える
  \renewcommand{\autoref}[1]{\Test@TrueAutoref{#1}}%autoref再定義
}

%Sectionのラベルに対してMainFile内でのその節の番号を返す
\newcommand{\SetTrueSecNumber}[1]{%
  \expandafter\newcount\csname Count@#1\endcsname
  \csname Count@#1\endcsname=\Test@NumberingPrint{#1}
  \expandafter\advance\csname Count@#1\endcsname by -1
  \setcounter{section}{\csname Count@#1\endcsname}
}

%MainFileの.auxをinput
\ifcsname MainFile\endcsname\else%
\input{../MainFile.aux}\fi
\makeatother

コンパイルすると、
スクリーンショット 2021-02-13 2.31.05.png
このようになります。
SubFile の magenta 色の部分は MainFile のラベルであり、SubFile ではただ色がついて印字されているだけになります。
青色はちゃんとクリックすると該当箇所へと飛びます。

これで期待通りの出力が得られた!
と思ったのですが、節番号がおかしいですね。
SubFile.tex の中の\section{子ファイル}の直前の1行をコメントアウトしてから、
SubFile.tex を保存
→ MainFile.tex をコンパイル
→ コメントアウトをもとにもどして SubFile.tex をコンパイル
とします。すると
スクリーンショット 2021-02-13 2.35.47.png
となり、節番号もちゃんとします。

嬉しいです。

後日、機会 (や要望) があれば、このTest.styの中身について詳しく説明します。

##発展

  • 3層にする場合も同様です。SubFile の方で\SubFileというコマンドを定義して、適当に条件分岐を増やせば良いだけです。(cf. GitHub)。
  • enumerate に対するラベルでも同様の振る舞いをします。
  • このままだと\eqrefはうまく振る舞いません。理由ですが、amsmath が行う数式環境内でのラベルの記録は、通常のラベルづけのコマンド\labelをコピーした\ltx@labelというものが行っているからです。なので、上の\labelの再定義を用いて\renewcommand{\ltx@label}{\label}としてやる必要があります。これだけ書いていればあとはいい感じになってくれます。(cf. GitHub)。

##参考記事
効率的な LaTeX ファイル分割術
分割した LaTeX ファイルを subfiles を使ってコンパイルする

0
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?