texの分割ファイルについて
texには、ファイルを分割して作業効率が上がるpackageがあります。\input
や\include
はファイルを分割することが可能ですが、分割したファイル単体でコンパイルするとエラーを吐かれます。そこで、分割されたファイルでもコンパイルエラーを吐かないsubfilesを用いたファイル分割を個人的に使ってます。
subfilesの書き方などについてはこちらの記事を御覧ください。
分割した LaTeX ファイルを subfiles を使ってコンパイルする
ただこの記事でも書かれていますが、子ファイルで\ref
や\cite
を用いると,?? や [?] のように出力されてしまう現象が起きます。
\documentclass[uplatex]{jsreport}
\usepackage{subfiles}
\begin{document}
% chapter1
\subfile{./sub1.tex}
% chapter2
\subfile{./sub2.tex}
\end{document}
\documentclass[master.tex]{subfiles}
\begin{document}
\chapter{sub1ファイルだよ\label{chap:sub1}}
hello sub1.
\end{document}
\documentclass[master.tex]{subfiles}
\begin{document}
\chapter{sub2ファイルだよ\label{chap:sub2}}
hello sub2.
% 本当はここでsub1の章を参照してほしいけどsubfilesだとそれができずに??になっちゃう
第\ref{chap:sub1}章の後にくる章だよ
\end{document}
個人的にもこの問題に悩んでいて、参照している部分はすべて同じファイル内に無理やり記述してました。見返すと超汚いファイル分割になっていて、なんとかならないもんかといろいろ考えました。
そこで
そこで、**「じゃあ自分で好きなようにファイルを分割した上でwebpackみたいに一つのファイルにまとめてくれれば、まとまったファイル上ではこの問題解決するんじゃね」**って思ったわけです。
具体的にはこんな感じ
\documentclass[uplatex]{jsreport}
\usepackage{subfiles}
\begin{document}
% chapter1
\subfile{./sub1.tex}
% chapter2
\subfile{./sub2.tex}
\end{document}
\documentclass[master.tex]{subfiles}
\begin{document}
\chapter{sub1ファイルだよ\label{chap:sub1}}
hello sub1.
\end{document}
\documentclass[master.tex]{subfiles}
\begin{document}
\chapter{sub2ファイルだよ\label{chap:sub2}}
hello sub2.
第\ref{chap:sub1}章の後にくる章だよ
\end{document}
この3つのファイルから
\documentclass[uplatex]{jsreport}
\usepackage{subfiles}
\begin{document}
% chapter1
\chapter{sub1ファイルだよ\label{chap:sub1}}
hello sub1.
% chapter2
\chapter{sub2ファイルだよ\label{chap:sub2}}
hello sub2.
% これなら\ref{chap:sub1}をちゃんと参照してくれる
第\ref{chap:sub1}章の後にくる章だよ
\end{document}
こんなtexファイルを自動生成してくれたら\ref
も\cite
もoutput.tex
上で正しく参照してくれそうです。
ということで作りました
Goの勉強をしたかったので、試しにGo言語で書いてみました。なんかもっと良い書き方あったらコメントで教えてください。今までjsで脳死動的型付けしてた身としては、コーディングでやたらコンパイルエラー出まくっていろいろストレス溜まったけれど、Goは書き方がみんな一緒になるっている理由が何となくわかった気がしました。あとテンプレートリテラル使いたい人生だった。
やってることはたいしたことないです。subfiles自体、\subfile{}
でファイルのパスを指定しているのでそのファイルオープンして中身を全部output.tex
に流し込んでるだけ。メソッドわけはめんどいんでしてませんがあしからず。
package main
import(
"fmt"
"os"
"bufio"
"strings"
"flag"
)
func main(){
// masterファイルとoutputファイルをオープン
mainName := flag.String("m", "master.tex", "master file")
outputName := flag.String("o", "dist.tex", "output file")
flag.Parse()
file, err := os.Open(*mainName)
if err != nil {
fmt.Printf("failed to open inputfile")
}
outputFile, err := os.OpenFile(*outputName, os.O_WRONLY, 0666)
if err != nil {
fmt.Printf("failed to open outputfile")
}
scanner := bufio.NewScanner(file)
sumText := ""
// masterファイルを一行ずつ見ていく
for scanner.Scan() {
text := scanner.Text()
fileStr := "subfile{"
// 子ファイルを呼び出している行を見つけたらその子ファイルの中身をコピーしてoutputファイルに書き込み
if strings.Contains(text, fileStr) {
filePath := text[9:len(text)-1]
subfile, err := os.Open(filePath)
if err != nil {
fmt.Printf("failed to open file")
}
scanner := bufio.NewScanner(subfile)
isActive := false
// begin{document}からend{document}の間の行だけコピー
for scanner.Scan() {
subtext := scanner.Text()
if strings.Contains(subtext, "end{document}") {
isActive = false
}
if isActive {
sumText += (subtext + "\n")
}
if strings.Contains(subtext, "begin{document}") {
isActive = true
}
}
if err = scanner.Err(); err != nil {
fmt.Printf("failed to read file")
}
} else {
sumText += text
}
}
if err = scanner.Err(); err != nil {
fmt.Printf("failed to read file")
}
fmt.Fprintln(outputFile, sumText)
}
そして
go run MargeTex.go -m path/to/master.tex -o path/to/output.tex
をすればmaster.tex
含め、呼び出している子ファイルも全部まとまったoutput.tex
が生成されます。
結果
素晴らしいtexファイル分割ライフが始まりました。
副産物として、どこかにtexファイルを提出する事になったときはこの出力texファイル一つを提出すればいいだけので提出する際にも便利ですね。
githubにも載せましたので、寄った方はぜひスターつけて帰ってください(笑)。
それではみなさんも快適なtexファイル分割ライフをノシ