TeX Live에 들어 있는 명령의 대부분은 문서를 조판하지 않습니다. 문서를 읽습니다. 어떤 명령이 실제로 어떻게 정의되어 있는지 보여 주는 texdef, 원고의 버릇을 짚어 주는 chktex와 lacheck, 천 줄짜리 로그를 몇 줄로 줄이는 texfot, 낱말 수를 세는 texcount, .log에서 필요한 줄만 캐내는 texloganalyser. LaTeX 작업에서 정말로 시간을 잡아먹는 것은 조판 자체가 아니라 왜 안 되었는지를 찾는 시간이므로, 이 언저리를 한 번 익혀 두면 크게 도움이 됩니다. 패키지 설명서를 여는 texdoc은 다른 페이지의 몫이니 여기서는 그 밖의 것을 다루고, 마지막에 완성된 PDF에 손을 대는 Ghostscript를 놓아 둡니다.
texdef — 이 명령은 결국 어떻게 정의되어 있는가
재정의가 부딪쳤을 때 지금 유효한 정의가 무엇인지 아는 가장 빠른 길은 엔진에 직접 묻는 것입니다. latexdef \section이라고 치면 \long macro:->\@startsection {section}{1}{\z@ }{-3.5ex \@plus -1ex \@minus -.2ex}{2.3ex \@plus .2ex}{\normalfont \Large \bfseries }가 돌아옵니다. 값 그 자체이고, 게다가 지금 이 환경의 값입니다. 패키지를 얹은 상태로 보고 싶으면 -p를 더합니다. latexdef -p amsmath \tfrac은 \genfrac {}{}{}1을 돌려주어, \tfrac이 \genfrac의 얇은 껍데기일 뿐임을 그 자리에서 보여 줍니다. 존재하지 않는 이름을 건네면 답은 무뚝뚝하게 undefined입니다. 작성자는 Martin Scharrer이고, TeX Live 2024에 든 것은 version 1.9(2020/09/27)입니다.
여기서 dvipdfmx와 같은 장치가 다시 나옵니다. latexdef는 texdef를 가리키는 심볼릭 링크이고, 프로그램은 자신이 어떤 이름으로 불렸는지를 보고 포맷을 정합니다. texdef라면 plain TeX, latexdef라면 LaTeX입니다. 그래서 맨 texdef \LaTeX은 undefined를 돌려주며, 이는 버그가 아닙니다. 같은 것을 -t latex이나 -t lualatex으로 명시할 수도 있습니다. 더 쓸모 있는 것은 위치를 찾는 옵션들입니다. -F는 정의된 자리를 알려 줍니다. latexdef -p booktabs -F \toprule은 \toprule first defined in "/usr/local/texlive/2024/texmf-dist/tex/latex/booktabs/booktabs.sty".라고 답합니다. 그리고 -l은 그 패키지가 제공하는 이용자용 명령의 목록을 냅니다. 설명서를 펼치기 전에 무엇이 있는지 먼저 보고 싶을 때 좋습니다.
latexdef \section # the definition in force right now
latexdef -p amsmath \tfrac # with a package loaded
latexdef -p booktabs -F \toprule # which file defined it
latexdef -p geometry -l # the user-level commands a package adds
latexdef -c beamer \frametitle # inside a different document classchktex와 lacheck — 두 린터가 보는 것은 서로 다르다
둘 다 “컴파일은 되는데 지면이 이상한” 부류의 문제를 잡아 주지만, 잘하는 분야가 다릅니다. chktex는 조판의 작법을 봅니다. 같은 원고를 통과시키면 Warning 26 in lint.tex line 4: You ought to remove spaces in front of punctuation.이나 Warning 44 in lint.tex line 5: User Regex: 1:Capitalize before references. 같은 번호 붙은 지적이 늘어서고, 문제가 된 칸을 ^로 짚어 줍니다. 번호가 붙어 있다는 것은 잠재울 수 있다는 뜻이니, 곧은 큰따옴표를 TeX의 인용부호로 바꾸라는 18번이 거슬리면 chktex -n18입니다. lacheck는 구조의 대응을 봅니다. 환경이나 중괄호, 수식의 시작과 끝이 어긋나면 양쪽 끝을 행 번호와 함께 <-와 -> 짝으로 보여 줍니다. 일부러 망가뜨린 원고로 시험하니 "broken.tex", line 5: <- unmatched "\end{enumerate}"가 나오고 바로 이어 "broken.tex", line 3: -> unmatched "\begin{itemize}"가 나왔습니다. 엔진보다 먼저, 그것도 훨씬 읽기 좋은 형태로 알려 줍니다.
CI에 넣을 생각이라면 결정적인 차이 하나를 알아 두십시오. lacheck는 무엇을 찾아내든 종료 코드 0을 돌려줍니다. 위의 망가진 원고 — 환경 대응이 두 겹으로 어긋나고 수식이 닫히지 않은 — 에서도 0이었습니다. 즉 빌드의 성패로는 쓸 수 없고, 표준 출력을 붙잡아 스스로 판정해야 합니다. 반면 chktex -q는 경고를 인쇄한 실행마다 2를, 깨끗한 파일에는 0을 돌려주었습니다. 관문으로 쓸 수 있는 쪽은 이것입니다. 한 가지 더, 이 TeX Live 2024의 macOS 빌드에 든 chktex는 POSIX 확장 정규 표현식으로 컴파일되어 있고 기본 규칙 하나가 Perl 계열 선행 탐색을 쓰기 때문에, 실행할 때마다 chktex: WARNING -- Compilation of regular expression으로 시작하는 줄이 먼저 나옵니다. 실질적인 해는 없지만 CI 로그에서 무시하도록 적어 두면 조용해집니다.
chktex -q paper.tex # exit 2 when it prints warnings, 0 when clean
chktex -q -n18 -n26 paper.tex # mute the quotation-mark and punctuation rules
lacheck paper.tex # unmatched groups, shown as a <- and -> pair
lacheck paper.tex | tee lacheck.out # its exit code is always 0, so read this이 도구들의 성격을 이해하려면 lacheck man 페이지의 BUGS 절을 한 번 읽어 볼 만합니다. 고급 매크로에는 혼란스러워하고 단순한 매크로에는 속으며, TeX 자체를 좋아하지 않고, 경고를 개별로 끌 방법도 없다고 스스로 인정합니다. 그리고 자신을 “at best a crude approximation”이라고 적어 둡니다. 어쩌면 그 정직함이야말로, 1990년대 초 Kresten Krab Thorup이 쓰고 Per Abrahamsen이 손본 이 작은 도구가 지금도 TeX Live에 실려 있는 이유일지 모릅니다. chktex 쪽도 시작 배너에 Copyright 1995-96 Jens T. Berger Thielemann.을 그대로 걸어 두고 있습니다. 서른 해 가까이 된 도구가 오늘 쓴 원고에 여전히 쓸모 있는 지적을 한다는 것 — 그것 또한 LaTeX 세계의 속도입니다.
texfot — 24줄짜리 로그를 4줄로
TeX의 출력을 아무도 읽지 않는 이유는 단순합니다. 양이 너무 많기 때문입니다. texfot은 엔진을 대신 실행하고, 그 출력에서 주목할 만한 줄만 통과시킵니다. 이 기기에서 lipsum을 쓴 한 쪽짜리 문서를 맨 pdflatex으로 조판하니 터미널에 24줄이 흘렀지만, 같은 것을 texfot pdflatex으로 돌리니 4줄이 되었습니다. 남은 것은 엔진의 버전 줄, Overfull \hbox (122.18651pt too wide) detected at line 4, 그리고 Output written on over.pdf (1 page, 19010 bytes).입니다. 버려진 것도 아닙니다. 필터 전의 전체 출력은 임시 파일로 tee 되므로 필요하면 나중에 읽을 수 있습니다(저장 위치를 바꾸려면 --tee=, 필요 없으면 --tee=/dev/null). 종료 코드는 엔진의 것을 그대로 돌려주므로 latexmk나 CI에 끼워도 판정이 망가지지 않습니다. 오류가 있는 문서로 시험하니 맨 pdflatex과 똑같이 1이 돌아왔습니다. 작성자는 Karl Berry입니다.
texfot pdflatex paper.tex
# texfot: invoking: pdflatex paper.tex
# This is pdfTeX, Version 3.141592653-2.6-1.40.26 (TeX Live 2024)
# Overfull \hbox (122.18651pt too wide) detected at line 4
# Output written on paper.pdf (1 page, 19010 bytes).
texfot --tee=/dev/null lualatex paper.tex # do not keep the full copy
# .latexmkrc: wrap the engine
$pdflatex = 'texfot pdflatex %O %S';texcount와 texloganalyser — 낱말을 세고, 로그를 캔다
투고 규정에 “본문 8,000 낱말 이내”라고 적혀 있을 때 wc -w는 쓸 수 없습니다. \usepackage도 매크로 이름도 세어 버리기 때문입니다. texcount(TeXcount 3.1.1, 2018년 10월)는 LaTeX 구문을 이해하고 세며, 본문·제목·캡션을 따로, 나아가 수식의 개수까지 나누어 보고합니다. -brief를 붙이면 2+0+0 (0/0/0/0) File: over.tex처럼 한 줄로 정리됩니다. 다른 하나인 texloganalyser(Thomas van Oudenhove, version 0.11, BSD 라이선스)는 이미 쓰인 .log를 나중에 캐내는 도구입니다. -o는 오버풀 박스만, -r는 상호 참조 경고만, -i는 읽어 들인 이미지, -s는 사용된 .sty와 .cls를 꺼냅니다. texfot이 “돌리면서 걸러 낸다”면 이쪽은 “끝난 로그에서 캐낸다”입니다. 용도가 겹치지 않으니 둘 다 갖춰 두어 손해 볼 것이 없습니다.
texcount -brief paper.tex # words in text + headers + captions
texcount -inc -sum paper.tex # follow \input and \include, one total
texloganalyser -o paper.log # only the overfull boxes
texloganalyser -r paper.log # only the reference warnings
texloganalyser -s paper.log # which .sty and .cls were actually loadedGhostscript — PDF 합치기, 그리고 “압축”이 듣지 않을 때
gs는 PostScript와 PDF의 인터프리터이며, ps2pdf가 안에서 돌리는 것이기도 합니다. -sDEVICE=pdfwrite를 주면 PDF를 써 내므로 PostScript에서의 변환, 여러 PDF의 병합, 페이지 추출이 각각 한 줄로 끝납니다. 병합이 가장 단순해서 입력을 차례로 늘어놓기만 하면 됩니다. 이 기기에서 7,940바이트짜리와 6,865바이트짜리 PDF를 늘어놓으니 12,543바이트짜리 한 권이 되었습니다. 참고로 gs는 TeX Live에 포함되어 있지 않습니다. MacTeX 같은 설치 프로그램이 따로 넣는 Ghostscript이고, 이 환경의 버전은 10.03.0입니다.
gs -q -sDEVICE=pdfwrite -dNOPAUSE -dBATCH \
-sOutputFile=merged.pdf front.pdf body.pdf
gs -q -sDEVICE=pdfwrite -dNOPAUSE -dBATCH \
-dFirstPage=3 -dLastPage=8 -sOutputFile=extract.pdf paper.pdf
gs -q -sDEVICE=pdfwrite -dPDFSETTINGS=/ebook -dNOPAUSE -dBATCH \
-sOutputFile=small.pdf big.pdf여기서 널리 믿어지는 이야기 하나를 바로잡아 둡니다. -dPDFSETTINGS는 “PDF를 압축하는 스위치”가 아닙니다. 이 프리셋들이 주로 정하는 것은 이미지 재표본화 방침이며, 해상도 하한이 /screen(화면용)에서 /ebook, /printer, /prepress로 갈수록 높아집니다. 따라서 비트맵 이미지가 없는 문서는 줄어들 여지가 없습니다. 이 기기에서 시험하니 글자뿐인 6,865바이트 PDF가 /screen에서 7,310, /ebook에서 7,309, /prepress에서 7,302, /printer에서는 9,869바이트로 넷 다 원본보다 커졌습니다. 파일을 다시 만드는 비용만 남기 때문입니다. 이 옵션이 값을 하는 자리는 사진과 스캔 이미지가 잔뜩 든 문서입니다. 그리고 어느 경우든 통과 전후로 글꼴 임베딩·링크·책갈피·페이지 크기를 눈으로 확인하십시오. pdfwrite는 PDF를 다시 구성하므로 눈에 보이지 않는 정보가 빠질 수 있습니다.
의문에서 명령 찾기
| 명령 | 답해 주는 물음 |
|---|---|
latexdef NAME | 이 명령은 지금 어떻게 정의되어 있는가. -F를 더하면 어느 파일이 정의했는가 |
chktex -q | 원고에 조판상의 버릇은 없는가. CI 관문에 쓸 수 있는 종료 코드를 돌려줍니다 |
lacheck | 환경과 괄호의 대응이 무너지지 않았는가. 다만 종료 코드는 늘 0입니다 |
texfot ENGINE FILE | 이번 실행의 로그 가운데 정말로 봐야 할 몇 줄은 무엇인가 |
texcount -brief | 본문의 낱말 수는 몇인가. 매크로나 \usepackage를 세지 않고 |
texloganalyser -o | 이미 쓰인 .log에서 오버풀 박스나 참조 경고만 캐냅니다 |
gs -sDEVICE=pdfwrite | PDF를 합치거나, 쪽을 뽑아내거나, 이미지가 많은 PDF를 가볍게 하고 싶을 때 |