
Ich bereite gerade Kursmaterial (PDF) für ein Tutorial vor, das sich mit der Unix-Befehlszeile beschäftigt. Da ich nach Automatisierung strebe (manche nennen das Faulheit), habe ich ein kleines Paket geschrieben, das es mir ermöglicht, mit \write18
(with --shell-escape
) und dem verbatim
Paket
- Führen Sie Befehle aus (z. B.
ls
) auf BefehlwährendZusammenstellung meines.tex
Dokuments und deren Satz in meinem Dokument, - die resultierenden
stdout
undstderr
in externe Dateien umleiten, - Geben Sie diese externen Dateien für den Satz
stdout
undstderr
in meinem.tex
Dokument ein.
Meines Wissens nach \write18
öffnet und schließt jedoch jeder Aufruf von seine eigene Shell-Sitzung. Das ist bedauerlich, da es einige Verrenkungen und Code-Duplikationen erfordert. Insbesondere
- alle während einer Sitzung definierten Shell-Variablen sind in der nächsten nicht verfügbar;
- Ich muss
cd
am Anfang jedes einzelnen Befehls in dasselbe Verzeichnis wechseln,\write18
um wieder im selben Verzeichnis zu landen, in dem ich mich am Ende des vorhergehenden Befehls befunden habe\write18
.
Siehe mein Spielzeugbeispiel unten.
Gibt es eine Möglichkeit, während eines pdflatex
Laufs mit der Shell zu interagieren, aber trotzdem eine Shell-Sitzung von einem \write18
Aufruf zum nächsten offen zu halten? Oder gibt es einen besseren Ansatz, der meinen Anforderungen entspricht?
\documentclass{article}
\usepackage{lipsum}
\begin{document}
First, initialise the repository.
% pretend that the following is an environment that both
% - runs commands at the CL
% - typesets them in the .tex document
\immediate\write18{%
cd $HOME/Desktop;
mkdir myrepo;
cd myrepo;
git init;
}
Let's see what git has to say...
\immediate\write18{%
# I'm back in $HOME :(
# I have to cd to $HOME/Desktop/myrepo, here, but I'd like to avoid it...
cd $HOME/Desktop/myrepo;
git status
# ...
}
\end{document}
Antwort1
\documentclass{article}
\begin{document}
\immediate\write18{echo pwd > /tmp/zzpipe}
\texttt{\input{result.txt}}
\immediate\write18{echo cd > /tmp/zzpipe}
\immediate\write18{echo pwd > /tmp/zzpipe}
\texttt{\input{result.txt}}
\immediate\write18{echo 'FOO=wibble' > /tmp/zzpipe}
\immediate\write18{echo 'echo FOO is $FOO' > /tmp/zzpipe}
\texttt{\input{result.txt}}
\end{document}
a) Richten Sie einen „Server“ ein, der die Befehle entgegennimmt. Ich verwende einfach eine benannte Pipe:
$ cd /tmp
$ mkfifo zzpipe
$ while true ; do eval `cat /tmp/zzpipe` >/tmp/result.txt ; done
Führen Sie dann die obige Tex-Datei aus (in /tmp
oder Arrange result.txt
wird sie woanders geschrieben). Die Ausgabe sollte wie gezeigt aussehen.
Dies gilt für Windows mit Cygwin Bash. Andere Befehlszeilen sind ähnlich, erfordern aber möglicherweise andere Anführungszeichenkonventionen. Und wie Sie sehen, bleibt cd
die Einstellung FOO
von einem Schreibvorgang zum anderen erhalten.
Antwort2
Ich habe grundlegende Bash-Unterstützung hinzugefügt, um pythontex
... und habe dafür weniger als 20 Zeilen Code benötigt. Um dies zu verwenden, benötigen Sie die neueste Version vonGitHub. Sie müssen die standardmäßige pythontex
3-Schritt-Kompilierung verwenden, wenn Sie neuen Bash-Code haben, der ausgeführt werden muss (LaTeX ausführen, das PythonTeX-Skript ausführen, LateX ausführen). Wenn Sie keinen neuen Code haben, der ausgeführt werden muss, können Sie LaTeX einfach selbst ausführen. Da dies nicht verwendet \write18
, benötigen Sie kein Shell-Escape (die Codeausführung wird vom PythonTeX-Skript übernommen).
Alles scheint zu funktionieren, aber Sie müssen mich informieren, wenn Sie Fehler finden. Die Zeilennummern der Fehler sollten korrekt mit denen des ausgeführten Codes synchronisiert sein.
Hier ist ein Beispieldokument mit der unten gezeigten Ausgabe. \stdoutpythontex
ist standardmäßig wörtlich, das Format muss also nicht wie bei \printpythontex
(oder dem Äquivalent \stdoutpythontex
) angegeben werden.
\documentclass{article}
\usepackage[makestderr, usefamily=bash]{pythontex}
\setpythontexfv{numbers=left, firstnumber=last}
\begin{document}
A block of bash...
\begin{bashblock}
myvar="myvar's value"
echo $myvar
\end{bashblock}
...with output:
\printpythontex[verbatim]
Another block, accessing the previous variable...
\begin{bashblock}
echo "In another LaTeX environment later on..."
echo $myvar
\end{bashblock}
...with output:
\printpythontex[verbatim]
A block with an error.
\begin{bashblock}
echo "In another LaTeX environment later on..."
echo $myvar
lsERROR
\end{bashblock}
Stdout:
\printpythontex[verbatim]
Stderr:
\stderrpythontex
\end{document}