Chapter toc 만들기에 대하여

2015.10.15 15:02

yihoze 조회 수:1067

http://www.ktug.org/xe/index.php?document_srl=213871&mid=KTUG_open_board


chaptertoc.PNG


이 글에서 소개한 방법을 성공하기까지 겪은 것들을 이야기해 보겠다. 장 차례(장 제목 아래에 그 장의 목차가 오는)를 만들려면 minitoc 패키지를 사용한다.


\usepackage{minitoc}

\begin{document}

\dominitoc

\chapter{...}

\minitoc


minitoc가 나무랄 데 없지만, \chapter 뒤에 매번 \minitoc를 써 주는 게 좀 못마땅하다. (못마땅할 것도 없다. 서문이나 부록을 고려하면 저 방법이 합리적이다.) 명령 하나로 모든 장에서 차례가 생성되게 할 수 없을까? 


실은, 북마크와 하이퍼링크가 보편화된 요즘에 minitoc는 더 이상 유용하지 않다고 생각하고 있었기 때문에 이 문제에 관심을 둘 이유가 없었다. 그런데 Gromob 교수님과 Ischo 교수님이 장 차례가 유용하다고 주장하셨다. 


"학생이든 선생이든 두꺼운 책을 갖고 다니는 것이 불편하여 장 단위로 복사하여 읽는 것을 선호한다. 그런데 그 경우에 차례가 없으니 다소 불편하다. 그리고 같은 이유로 면주에 장 제목뿐만 아니라 책 제목이 있는 것이 좋겠다."


2013년 가을이었다. 연장자를 공경하는 마음에 메므와가 제공하는 \newlistof 명령이 이를 쉽게 구현해 주리라는 지나친 믿음이 더해져서 "minitoc 없이 창 차례 만들기"를 시작하였다.  minitoc 패키지에 하자가 없는데 왜 이를 대체하려 했을까? 돌이켜 보면 어리석은 결정이었다.


이 얘기를 계속하기에 앞서 \newlistof 명령이 무엇을 하는지 살펴보겠다. 메므와 클래스는 \tableofcontents를 이렇게 만든다.


\newlistof{tableofcontents}{toc}{\contentsname}


이로부터 많은 것들이 정의되는데, 주목해야 할 것은 두 가지이다.
1) \tableofcontents 명령 (위 선언에서 첫 인자에 백슬래시가 포함되어 있지 않음을 유념해야 한다.)
2) toc 파일


장 차례를 구상하는 아이디어는 간단하다.

1) tabloeofcontents 대신 \chapteri, \chapterii, ... \chapterx를 만든다. 즉 로마 숫자를 이용한다. chapter 카운터를 로마 숫자로 바꾸어 붙이면 그만이다.

2) 마찬가지로 toc 대신 toci, tocii, ... tocx를 만든다. 

3) 한 번의 선언으로 모든 챕터에 적용되게 하기 위해 (\minitoc 같은 것을 되풀이되지 않기 위해) hook를 사용한다. 메므와는 많은 후크를 제공하므로 chapter에도 분명 어떤 후크가 있을 것이다. 찾아보니 \memendofchapterhook가 있다. 이것은 비어 있고 여기에 뭔가 집어넣으면 \chapter 명령이 그것을 맨 마지막에 처리한다.

4) toci 등등의 파일에 내용이 들어가도록 \addtocontents를 재정의한다. 본래 기능을 유지하면서 (toc 파일에 내용을 넣으면서) 현재의 챕터에 해당하는 tocX 파일에 내용을 넣는다. hyperref 패키지가 이 명령을 재정의하는데, hyperref 패키지를 대부분 사용하므로 그것을 따라 재정의한다.


\newlistof에 넣을 인자들부터 정의한다.


1) \def\chapcontents{Contents\roman{chapter}}

\def\ChapterContents{\csname Contents\roman{chapter}\endcsname} 

2) \def\chaptoc{toc\roman{chapter}}

3) \def\ContentsName{In This Chapter}


\newlistof{\chapcontents}{\chaptoc}{\ContentsName}


이것을 \memendofchapterhook에 넣는다.


\renewcommand\memendofchapterhook{

\newlistof{\chapcontents}{\chaptoc}{\ContentsName}

\ChpaterContents

}


뒤에서 설명할 터인데, 이것이 기대한 대로 작동하지 않는다.

그리고 \patchcommand를 이용하여 \addtocontents에 \addtocontents를 덧붙인다.


\patchcommand{\addcontentsline}{}{

\ifthenelse{\equal{#1}{toc}\and\not\equal{#2}{chapter}}

{\addtocontents{\chaptoc}{\protect\contentsline{#2}{#3}{\thepage}{\@currentHref}}}

{}}


\addcontentsline이 toc에 내용을 넣을 때, 그것이 chapter가 아니면 tocX에도 넣으라는 것이다.


앞으로 되돌아가서 \newlistof{\chapcontents}{\chaptoc}{\ContentsName}를 보자. 이것은 기대와 달리 맨 마지막 챕터의 파일, 5 장까지 있다면, toci ... tociv를 만들지 않고 tocv만 만들었다. 애당초 필요해서 시작한 일이 아니었기 때문에 여기에서 포기했다. 그리고 어제 (또 다시 불필요하게) expl3이 도와주리라는 믿음을 갖고 재도전했다. 과잉 믿음이다. expl3가 이것의 결정적인 해법에서 아무런 기여도 하지 않는다.


\newlistof가 이런저런 명령과 편의를 만들어주지만, toc 같은 파일을 만드는 것은 \@starttoc이다. 즉 \newlistof를 사용하지 않아도 된다. 내가 만약 book 클래스로 처음에 시도했다면 실패하지 않았을 것이다. tocX 파일들이 생성되지 않은 까닭은 메므와가 재정의한 \@starttoc가 \AtEndDocument를 사용하기 때문이다. \@starttoc를 latex.ltx의 정의로 되돌리면 이 문제가 해결된다. 하지만 그것은 다른 차례 파일들에 영향을 줄지도 모르므로 피하는 것이 좋겠다. 필요한 것만 가져다 쓰기로 했다.


\renewcommand\memendofchapterhook{

    \@input{\jobname.\chaptoc}

    \if@filesw

          \expandafter\newwrite\csname tf@\chaptoc\endcsname

          \immediate\openout \csname tf@\chaptoc\endcsname \jobname.\chaptoc\relax

\fi}


tocX 파일들이 생성된다. 그런데 tocvi까지만, 여섯 개만 만들어진다. 이 때에 만나는 에러 메시지가 "No room for new write"이다. 뭔 소린가? 다시 삽질의 시간을 갖는다. 그러다가 동시에 열 수 있는 부속 파일의 수가 제한되어 있지 않은지 의심하였다. 구글 선생에게 물어 보니 그렇다고 한다. 해법은 morewirtes 패키지이다. 그 패키지의 저자인 Bruno Le Floch에게 감사 드린다.


실용적인 수준에서 사용하려면 손질이 좀 더 필요하다. \frontmatter 따위를 검사해서 달리 작동하게 한다든가, 필요에 따라 \minitoc 같은 선별적으로 사용할 수 있는 명령을 제공하는 것이 필요할 것이다. 그런 것은 어렵지 않으니 필요할 때 고치거나 만들어 쓰면 된다. 그러나 원점으로 돌아가서, minitoc가 필요한 사람들이 정말 있을까?


아무튼 이상의 것들은 (쓸 일 없지만 버리기도 아까워서) hzguide 클래스에 포함되어 있다. KTUG 마당의 것과는 코드가 약간 다르다.


\DeclareExpandableDocumentCommand \chaptoc {}

toc \int_to_roman:n {\c@chapter}

}


\NewDocumentCommand \EnableChapterContents {}

{

\usepackage{morewrites}


\RenewDocumentCommand \memendofchapterhook {}

{

    \@input{\jobname.\chaptoc}%

    \if@filesw

          \expandafter\newwrite\csname tf@\chaptoc\endcsname

          \immediate\openout \csname tf@\chaptoc\endcsname \jobname.\chaptoc\relax

\fi  

}

\RenewDocumentCommand \addcontentsline {mmm}

{

\addtocontents{##1}{\protect\contentsline{##2}{##3}{\thepage}{\@currentHref}}

\str_if_eq:nnT {##1}{toc}

{

\str_if_eq:nnF {##2}{chapter}

{

\addtocontents{\chaptoc}{\protect\contentsline{##2}{##3}{\thepage}{\@currentHref}}

}

}

}

}


전문에서 \EnableChapterContents를 선언하면 모든 장에 차례가 생긴다. minitoc보다 눈곱만큼 좋다고 할 수 있으려나?




XE Login