
Я готовлю некоторые материалы курса (PDF) для руководства, которое включает в себя командную строку Unix. Поскольку я стремлюсь к автоматизации (некоторые называют это ленью), я написал небольшой пакет, который позволяет мне, используя \write18
(with --shell-escape
) и verbatim
пакет,
- запускать команды (например
ls
, ) по командев течениекомпиляция моего.tex
документа и набор их в моем документе, - перенаправить полученные
stdout
иstderr
во внешние файлы, - введите эти внешние файлы для набора текста
stdout
иstderr
в моем.tex
документе.
Однако, насколько я понимаю, каждый вызов \write18
открывает и закрывает собственную сессию оболочки. Это досадно, так как требует некоторых ухищрений и дублирования кода. В частности,
- все переменные оболочки, определенные в одном сеансе, недоступны в следующем;
- Мне приходится
cd
переходить в тот же каталог в начале каждого файла,\write18
чтобы вернуться в тот же каталог, в котором я находился в конце предыдущего\write18
.
Посмотрите пример моей игрушки ниже.
Есть ли способ взаимодействовать с оболочкой во время pdflatex
выполнения, но каким-то образом сохранять сессию оболочки открытой от одного \write18
вызова до другого? Или есть лучший подход, который бы соответствовал моим потребностям?
\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}
решение1
\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}
а) настроить «сервер» для приема команд, я просто использую именованный канал:
$ cd /tmp
$ mkfifo zzpipe
$ while true ; do eval `cat /tmp/zzpipe` >/tmp/result.txt ; done
затем запустите указанный выше tex-файл ( /tmp
или организуйте result.txt
запись в другом месте), вывод должен быть таким, как показано.
Это в Windows с Cygwin Bash, другие командные строки будут похожи, но могут потребовать других соглашений о кавычках. И, как вы можете видеть, cd
и настройка FOO
сохраняется от одной записи до другой.
решение2
Я добавил базовую поддержку bash в pythontex
...в итоге заняло менее 20 строк кода. Чтобы использовать это, вам понадобится последняя версия отGitHub. Вам нужно будет использовать стандартную pythontex
3-шаговую компиляцию всякий раз, когда у вас есть новый код bash, который нужно выполнить (запустить LaTeX, запустить скрипт PythonTeX, запустить LateX). Когда у вас нет нового кода, который нужно выполнить, вы можете просто запустить LaTeX сам по себе. Поскольку он не использует \write18
, вам не нужен shell-escape (выполнение кода обрабатывается скриптом PythonTeX).
Кажется, все работает, но если вы найдете какие-либо ошибки, вам придется сообщить мне. Номера строк с ошибками должны быть правильно синхронизированы с номерами исполняемого кода.
Ниже приведен пример документа, вывод которого показан ниже. \stdoutpythontex
по умолчанию является дословным, поэтому формат указывать не нужно, как это делается с \printpythontex
(или эквивалентом \stdoutpythontex
).
\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}