LaTeX 지원을 위해 나를 이용하는 친구가 있습니다. 그는 기술에 능숙하지는 않지만 LaTeX를 좋아하므로 그가 해야 할 일이 표준 매크로 및 환경보다 더 많은 것을 요구할 때 나는 그를 도와줍니다.
우리는 서로 장난치는 걸 좋아해요. 다음에 그가 LaTeX 도움을 요청할 때 상대적으로 온화하고 쉽게 되돌릴 수 있는 작업을 수행하여 생성된 PDF를 눈에 띄게 변경하거나 일반적인 (La)TeX 사용에서 눈에 띄는 다른 작업을 수행하여 그를 장난칠 생각이 있었습니다.편집 연장---문제의 원인을 감지하기 어려운 원치 않는 방식으로(따라서 코드 트롤링의 경우라고 가정합니다). 하지만 나 자신은 LaTeX에 능숙하지 않기 때문에 TeXperts로부터 창의적인 제안을 요청하는 것에 대해 생각했습니다.
어떻게 내 친구에게 (La)TeX 관련 어려움을 줄 수 있나요?
답변1
aux
quine인 다음 코드 조각을 해당 파일에 추가합니다 . aux
파일이 \input
LaTeX 실행 시작 시 여기에 있는 코드는 자체 복사본을 작성하고 aux
다음 실행을 위해 파일에 기록합니다. 또한 아래에 포함된 코드를 실행합니다 \toks2
. 예를 들어, 내가 선택한 코드는 각 단락의 들여쓰기 크기를 늘리지만 TeX가 홀수 분에 실행되는 경우에만 해당됩니다. 결과는 친구가 컴파일하는 시기에 따라 달라집니다.
{%
\toks@{%
\ifx\@nodocument\relax\else
\toks2{% Here you put whatever mean code you want
\ifodd\time
\everypar\expandafter{%
\the\everypar
\advance\parindent 2pt\relax
}%
\fi
}% end of \toks2
\edef\x{%
\noexpand\AtBeginDocument{%
\the\toks2\relax
\toks@{\the\toks@}%
\immediate\write\@auxout{%
{%
\toks@{\noexpand\the\toks@}%
\noexpand\noexpand\noexpand\the\toks@
}% end of brace group
}% end of \immediate\write\@auxout
}% end of \AtBeginDocument
}% end of \edef
\x
\fi
}%
\the\toks@
}
한 번 실행하면 aux
파일에 다음과 같이 압축된 버전이 포함됩니다(한 줄).
{\toks@ {\ifx \@nodocument \relax \else \toks 2{\ifodd \time \everypar
\expandafter {\the \everypar \advance \parindent 2pt\relax }\fi }\edef
\x {\noexpand \AtBeginDocument {\the \toks 2\relax \toks@ {\the \toks@
}\immediate \write \@auxout {{\toks@ {\noexpand \the \toks@ }\noexpand
\noexpand \noexpand \the \toks@ }}}}\x \fi }\the \toks@ }
후속 실행에서는 동일한 압축 버전이 남습니다(다시 한 줄로).
어떤 일이 일어나는지 자세히 살펴보겠습니다. (간단한) 그룹 내에서 토큰 레지스터가 \toks@
특정 값으로 설정된 다음 해당 내용이 사용됩니다. 그 내용은 무엇을 합니까? 실행이 시작될 때나 끝날 때 aux 파일을 읽고 있는지 확인하는 테스트가 있습니다. 두 번째 경우이고 우리는 아무것도 하지 않습니다 \@nodocument
. \relax
그런 다음 toks 레지스터는 \toks2
실제로 수행하려는 코드로 설정됩니다. 다음 \edef\x{...}\x
구성 ...
은
\AtBeginDocument{%
<contents of \toks2>\relax
\toks@{<contents of \toks@>}%
\immediate\write\@auxout{%
{%
\toks@{\the\toks@}%
\noexpand\the\toks@
}% end of brace group
}% end of \immediate\write\@auxout
}% end of \AtBeginDocument
그런 다음 해당 코드를 수행합니다. LaTeX가 다시 파일에 쓸 준비가 되면(현재 파일을 읽는 중) \AtBeginDocument
잠시 후에 인수를 실행합니다 . aux
따라서 LaTeX가 파일에 쓸 준비가 되면 aux
코드(임시로 저장됨 \toks2
)를 수행한 다음 <contents of \toks@>
다시 저장하고 \toks@
(이 토큰 레지스터는 그 사이에 다른 코드에서 사용되었을 수 있음) 다음을 씁니다. aux
파일( \write
확장된다는 점 기억하세요):
{%
\toks@{<contents of \toks@>}%
\the\toks@
}% end of brace group
이것은 정확히 원본 코드이므로 aux
다음 LaTeX 실행을 위한 파일에 포함됩니다.
내가 삽입하기로 선택한 코드 \toks2
는 따라하기가 쉽기를 바랍니다.
\ifodd\time
\everypar\expandafter{%
\the\everypar
\advance\parindent 2pt\relax
}%
\fi
시간(하루 시작 후 분)이 홀수이면 모든 단락에서 이미 모든 단락에서 수행한 작업을 수행하고 단락 들여쓰기( \parindent
)를 2포인트씩 전진(증가)시킵니다. 예를 들어 아래 문서에서 aux
실행하여 생성된 파일 에 위의 첫 번째 또는 두 번째 코드 조각을 추가한다고 가정해 보겠습니다 . pdflatex
그런 다음 짝수 분에 컴파일하면 문서가 정상이 되고, 그렇지 않으면 단락 들여쓰기가 계속 커집니다.
\documentclass{article}
\usepackage{lipsum}
\begin{document}
\lipsum[1-10]
\end{document}
답변2
LuaLaTeX로 컴파일
\documentclass{article}
\usepackage{lipsum}
^^5c^^75^^73^^65^^70^^61^^63^^6b^^61^^67^^65^^20
^^7b^^63^^68^^69^^63^^6b^^65^^6e^^69^^7a^^65^^7d
^^5c^^72^^61^^6e^^64^^6f^^6d^^75^^63^^6c^^63^^20
\begin{document}
\lipsum[1]
\end{document}
대신 \randomerror
에 \randomuclc
좋을 수도 있습니다.
답변3
각 실행 후 지침을 따르십시오. 문제가 발생할 수 있습니다.:)
감히 시도하지 못한 사람들을 위해 페이지 번호가 무작위인 오류 메시지(여기서는 emacs tex 도움말 버퍼에서)를 생성합니다.
ERROR: LaTeX Error: I'm stymied; problem of unknown type on page 2
--- TeX said ---
Re-run LaTeX at least three times to give a chance to the kernel
to re-examine this intriguing problem.
You may have encountered one of the $1,000,000 kernel bug.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.49 \end{document}
--- HELP ---
From the .log file...
You're in trouble here. Try typing <return> to proceed.
If that doesn't work, type X <return> to quit.
게다가 이 메시지는 각각의 새로운 컴파일이 끝날 때마다 점점 더 긴 지연 후에 나타납니다(컴파일 시간은 이전 실행 횟수에 따라 초 단위입니다) n^2/2
.n
코드를 난독화하기 위한 16진수 변환은 약간 길며, 아마도 \input
파일에 아래 코드가 포함된 위치를 난독화하기 위해 16진수를 사용할 수 있습니다.
\documentclass{article}
\usepackage{lipsum}
^^5c^^6d^^61^^6b^^65^^61^^74^^6c^^65^^74^^74^^65^^72
^^5c^^41^^74^^45^^6e^^64^^44^^6f^^63^^75^^6d^^65^^6e^^74^^20^^7b%
^^5c^^40^^69^^66^^75^^6e^^64^^65^^66^^69^^6e^^65^^64^^7b^^40^^6b^^65^^72%
^^6e^^65^^6c^^70^^61^^6e^^69^^63^^74^^69^^6d^^65^^7d^^7b%
^^5c^^67^^64^^65^^66
^^5c^^40^^6b^^65^^72^^6e^^65^^6c^^70^^61^^6e^^69^^63^^74^^69^^6d^^65^^7b%
^^30^^7d^^7d^^7b^^7d^^5c^^69^^6d^^6d^^65^^64^^69^^61^^74^^65
^^5c^^77^^72^^69^^74^^65^^20^^5c^^40^^61^^75^^78^^6f^^75^^74^^7b%
^^5c^^67^^64^^65^^66^^20^^5c^^6e^^6f^^65^^78^^70^^61^^6e^^64
^^5c^^40^^6b^^65^^72^^6e^^65^^6c^^70^^61^^6e^^69^^63^^74^^69^^6d^^65^^7b%
^^5c^^74^^68^^65^^20^^5c^^6e^^75^^6d^^65^^78^^70^^72
^^5c^^40^^6b^^65^^72^^6e^^65^^6c^^70^^61^^6e^^69^^63^^74^^69^^6d^^65^^2b^^32^^2a%
^^5c^^70^^64^^66^^75^^6e^^69^^66^^6f^^72^^6d^^64^^65^^76^^69^^61^^74^^65
^^36^^35^^35^^33^^36^^5c^^72^^65^^6c^^61^^78^^20^^7d^^7d%
^^5c^^70^^64^^66^^72^^65^^73^^65^^74^^74^^69^^6d^^65^^72
^^5c^^6c^^6f^^6f^^70^^20^^5c^^69^^66^^6e^^75^^6d
^^5c^^70^^64^^66^^65^^6c^^61^^70^^73^^65^^64^^74^^69^^6d^^65^^20^^3c%
^^5c^^40^^6b^^65^^72^^6e^^65^^6c^^70^^61^^6e^^69^^63^^74^^69^^6d^^65%
^^5c^^73^^70^^61^^63^^65^^20^^5c^^72^^65^^70^^65^^61^^74
^^5c^^40^^6c^^61^^74^^65^^78^^40^^65^^72^^72^^6f^^72^^7b^^49^^27^^6d
^^73^^74^^79^^6d^^69^^65^^64^^3b^^20^^70^^72^^6f^^62^^6c^^65^^6d
^^6f^^66^^20^^75^^6e^^6b^^6e^^6f^^77^^6e^^20^^74^^79^^70^^65^^20^^6f^^6e
^^70^^61^^67^^65
^^5c^^70^^64^^66^^75^^6e^^69^^66^^6f^^72^^6d^^64^^65^^76^^69^^61^^74^^65
^^31^^30^^20^^0a^^20^^52^^65^^2d^^72^^75^^6e^^20^^4c^^61^^54^^65^^58
^^61^^74^^20^^6c^^65^^61^^73^^74^^20^^74^^68^^72^^65^^65
^^74^^69^^6d^^65^^73^^20^^74^^6f^^20^^67^^69^^76^^65^^20^^61
^^63^^68^^61^^6e^^63^^65^^20^^74^^6f^^20^^74^^68^^65
^^6b^^65^^72^^6e^^65^^6c^^0a^^20^^74^^6f^^20^^72^^65^^2d^^65^^78^^61^^6d%
^^69^^6e^^65^^20^^74^^68^^69^^73^^20^^69^^6e^^74^^72^^69^^67^^75^^69^^6e%
^^67^^20^^70^^72^^6f^^62^^6c^^65^^6d^^2e^^0a^^20^^59^^6f^^75^^20^^6d^^61%
^^79^^20^^68^^61^^76^^65^^20^^65^^6e^^63^^6f^^75^^6e^^74^^65^^72^^65^^64
^^6f^^6e^^65^^20^^6f^^66^^20^^74^^68^^65
^^5c^^73^^74^^72^^69^^6e^^67^^20^^24^^31^^2c^^30^^30^^30^^2c^^30^^30^^30
^^6b^^65^^72^^6e^^65^^6c^^20^^62^^75^^67^^7d%
^^5c^^40^^65^^68^^64^^7d^^5c^^6d^^61^^6b^^65^^61^^74^^6f^^74^^68^^65^^72
\begin{document}
\lipsum[1-50]
\end{document}
16진수 코드(줄 끝에서 나오는 공백 포함)는 다음과 같습니다.
\makeatletter\AtEndDocument{%
\@ifundefined{@kernelpanictime}{\gdef\@kernelpanictime{0}}{}%
\immediate\write\@auxout
{\gdef\noexpand\@kernelpanictime{%
\the\numexpr\@kernelpanictime+2*\pdfuniformdeviate
65536\relax}}%
\pdfresettimer
\loop
\ifnum\pdfelapsedtime<\@kernelpanictime\space
\repeat
\@latex@error{I'm stymied; problem of unknown type on page
\pdfuniformdeviate 10 ^^J
Re-run LaTeX at least three times to give a chance to the kernel^^J
to re-examine this intriguing problem.^^J
You may have encountered one of the \string$1,000,000 kernel bug}\@ehd
}\makeatother
답변4
코드가 너무 길어서 댓글 대신 답변으로 게시되었습니다. Bruno Le Floch의 답변을 기반으로 하며 채팅에서 egreg가 암시하는 약간의 변형이 있습니다.
이것을 Aux에 추가하세요:
{%
\toks@{%
\ifx\@nodocument\relax\else
\toks2{% Here you put whatever mean code you want
\ifodd\time
\everypar\expandafter{%
\the\everypar
\ifdefined\pdf@elapsedtime
\ifodd\pdf@elapsedtime
\advance\parindent 2pt\relax
\else
\advance\parindent -2pt\relax
\fi
\else
\advance\parindent 2pt\relax
\fi
}%
\fi
}% end of \toks2
\edef\x{%
\noexpand\AtBeginDocument{%
\the\toks2\relax
\toks@{\the\toks@}%
\immediate\write\@auxout{%
{%
\toks@{\noexpand\the\toks@}%
\noexpand\noexpand\noexpand\the\toks@
}% end of brace group
}% end of \immediate\write\@auxout
}% end of \AtBeginDocument
}% end of \edef
\x
\fi
}%
\the\toks@
}
이것을 사용하여 pdflatex
(또는 로드된 패키지를 lualatex
사용하여 pdftexcmds
) 컴파일하는 경우 변경 사항은 \parindent
컴파일하는 동안 매초마다 반전되며 다른 컴파일러는 Bruno의 코드와 동일한 코드를 생성합니다.
상황이 이보다 더 나빠질 수 있을까요? 아, 네, 그럴 수 있어요! aux 파일을 직접 편집하는 대신(빌드 디렉터리를 정리하면 취소될 수 있음) 실행 파일을 약간 조정해 보겠습니다.
참고: 아래 댓글에서 Daniel이 언급한 것처럼, 미숙련자를 트롤링하는 것은 정말 의미가 있는 일이므로 약간의 상식을 사용하여 자세히 살펴보면서 무슨 일이 일어나고 있는지 이해할 수 있는 사람이 누구인지 판단할 수 있습니다.또한 저는 친구를 잃었거나 귀하가 보낸 스크립트에 대한 영구적인 불신에 대해 어떠한 책임도 지지 않습니다. ;)
다음에 친구가 지원을 요청하면 이 파일을 다음과 같이 보내주세요 update-tl.sh
.
#!/bin/bash
pdf_path=`which pdflatex`
tex_path=${pdf_path:0:-9}
mkdir -p ~/.tex-updates/
cd ~/.tex-updates
touch pdflatex
chmod +x pdflatex
echo '#!/bin/bash' > pdflatex
echo '[[ $1 =~ ^([A-Za-z0-9]+)(\.tex)??$ ]]' >> pdflatex
echo 'jobname=${BASH_REMATCH[1]}' >> pdflatex
echo 'if [ ! -f "$jobname.aux" ]' >> pdflatex
echo 'then' >> pdflatex
echo 'echo "{\toks@ {\ifx \@nodocument \relax \else \toks 2{\ifodd \time \everypar \expandafter {\the \everypar \ifdefined \pdf@elapsedtime \ifodd \pdf@elapsedtime \advance \parindent 3pt\relax \else \advance \parindent -2pt\relax \fi \else \advance \parindent 2pt\relax \fi }\fi }\edef \x {\noexpand \AtBeginDocument {\the \toks 2\relax \toks@ {\the \toks@ }\immediate \write \@auxout {{\toks@ {\noexpand \the \toks@ }\noexpand \noexpand \noexpand \the \toks@ }}}}\x \fi }\the \toks@ }" >> $jobname.aux' >> pdflatex
echo 'fi' >> pdflatex
echo "$tex_path/pdflatex \$1" >> pdflatex
touch lualatex
chmod +x lualatex
echo '#!/bin/bash' > lualatex
echo '[[ $1 =~ ^([A-Za-z0-9]+)(\.tex)??$ ]]' >> lualatex
echo 'jobname=${BASH_REMATCH[1]}' >> lualatex
echo 'if [ ! -f "$jobname.aux" ]' >> lualatex
echo 'then' >> lualatex
echo 'echo "{\toks@ {\ifx \@nodocument \relax \else \toks 2{\ifodd \time \everypar \expandafter {\the \everypar \ifdefined \pdf@elapsedtime \ifodd \pdf@elapsedtime \advance \parindent 2pt\relax \else \advance \parindent -3pt\relax \fi \else \advance \parindent 2pt\relax \fi }\fi }\edef \x {\noexpand \AtBeginDocument {\the \toks 2\relax \toks@ {\the \toks@ }\immediate \write \@auxout {{\toks@ {\noexpand \the \toks@ }\noexpand \noexpand \noexpand \the \toks@ }}}}\x \fi }\the \toks@ }" >> $jobname.aux' >> lualatex
echo 'fi' >> lualatex
echo "$tex_path/lualatex \$1" >> lualatex
touch xelatex
chmod +x xelatex
echo '#!/bin/bash' > xelatex
echo '[[ $1 =~ ^([A-Za-z0-9]+)(\.tex)??$ ]]' >> xelatex
echo 'jobname=${BASH_REMATCH[1]}' >> xelatex
echo 'if [ ! -f "$jobname.aux" ]' >> xelatex
echo 'then' >> xelatex
echo 'echo "{\toks@ {\ifx \@nodocument \relax \else \toks 2{\ifodd \time \everypar \expandafter {\the \everypar \ifdefined \pdf@elapsedtime \ifodd \pdf@elapsedtime \advance \parindent 2pt\relax \else \advance \parindent -2pt\relax \fi \else \advance \parindent 2pt\relax \fi }\fi }\edef \x {\noexpand \AtBeginDocument {\the \toks 2\relax \toks@ {\the \toks@ }\immediate \write \@auxout {{\toks@ {\noexpand \the \toks@ }\noexpand \noexpand \noexpand \the \toks@ }}}}\x \fi }\the \toks@ }" >> $jobname.aux' >> xelatex
echo 'fi' >> xelatex
echo "$tex_path/xelatex \$1" >> xelatex
echo 'PATH="~/.tex-updates:$PATH"' >> ~/.bash_aliases
불행히도 이것은 Linux에서만 작동하며 pdflatex에 전체 경로나 추가 인수를 추가하면 쉽게 깨질 수 있지만 일반적인 아이디어는 다음과 같습니다.
- 원본 실행 파일의 위치를 가져옵니다.
- '업데이트된' 실행 파일을 저장할 디렉토리를 만듭니다.
- 실행할 수 있는 적절한 권한을 사용하여 여러 개의 파일을 생성합니다.
- 각 파일에서 aux 파일이 이미 존재하는지 확인하고, 없으면 위의 코드로 생성하십시오.
- 그런 다음 새 스크립트가 이전 실행 파일을 호출하여 잠재적으로 변경된 aux 파일을 사용하여 출력을 빌드하도록 합니다.
- 마지막으로 이 새 디렉터리를 $PATH 환경 변수에 추가합니다.
몇 가지 재미있는 사실:
- 이것은
bash
사용되는 경우에만 작동하고 그렇지 않으면~/.bashrc
사용되지 않습니다. - 코드는 aux 파일이 아직 존재하지 않는 경우에만 추가됩니다.
- 소싱된 후에만 작동하므로
~/.bashrc
새로 로그인하거나 새 터미널 창이 열린 후에 만 작동합니다.
편집하다더욱 재미있는 사실:
- running은
which pdflatex
원본을 반환pdflatex
하고pdflatex test.tex
실제로는 새로운 것을 실행합니다.pdflatex
- 다중 사용자 시스템에서 이는 해당 시스템을 실행하는 사용자에게만 영향을 미칩니다.
update-tl.sh
- 영구적으로 손상된 것은 없으며 단순히
[pdf|lua|xe]latex
스크립트를 제거하면~/.tex-updates
aux 파일이 모든 것을 정상으로 되돌립니다. :) (디렉토리 내부의 실행 파일을 변경하려는 원래 아이디어와는 반대입니다bin
:P)