
Estou preparando algum material de curso (PDF) para um tutorial que envolve a linha de comando do Unix. Como eu busco a automação (alguns chamam isso de preguiça), escrevi um pequeno pacote que me permite, usando \write18
(with --shell-escape
) e o verbatim
pacote,
- execute comandos (por exemplo
ls
) no comandodurantecompilação do meu.tex
documento e digitá-los no meu documento, - redirecionar o resultante
stdout
estderr
para arquivos externos, - insira esses arquivos externos para composição tipográfica
stdout
estderr
em meu.tex
documento.
No entanto, meu entendimento é que cada invocação \write18
abre e fecha sua própria sessão de shell. Isto é lamentável, pois requer algumas contorções e duplicação de código. Em particular,
- todas as variáveis de shell definidas durante uma sessão ficam indisponíveis na próxima;
- Eu tenho que
cd
ir para o mesmo diretório no início de cada um\write18
para voltar ao mesmo diretório em que estava no final do anterior\write18
.
Veja meu exemplo de brinquedo abaixo.
Existe alguma maneira de interagir com o shell durante uma pdflatex
execução, mas de alguma forma manter uma sessão do shell aberta de uma \write18
chamada para outra? Ou existe uma abordagem melhor que atenda às minhas necessidades?
\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}
Responder1
\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) configurar um "servidor" para aceitar os comandos, apenas uso um pipe nomeado:
$ cd /tmp
$ mkfifo zzpipe
$ while true ; do eval `cat /tmp/zzpipe` >/tmp/result.txt ; done
em seguida, execute o arquivo tex acima ( /tmp
ou o arranjo result.txt
é escrito em outro lugar). A saída deve ser conforme mostrado.
Isso ocorre no Windows com cygwin bash, outras linhas de comando serão semelhantes, mas podem precisar de convenções de cotação diferentes. e como você pode ver, cd
a configuração de FOO
sobrevive de uma gravação para a outra.
Responder2
Eu adicionei suporte básico ao bash para pythontex
... acabei ocupando menos de 20 linhas de código. Para usar isso, você precisará da versão mais recente doGitHub. Você precisará usar a pythontex
compilação padrão de 3 etapas sempre que tiver um novo código bash que precisa ser executado (execute o LaTeX, execute o script PythonTeX, execute o LateX). Quando você não tem um novo código que precisa ser executado, você pode simplesmente executar o LaTeX sozinho. Como isso não usa \write18
, você não precisa de shell-escape (a execução do código é controlada pelo script PythonTeX).
Tudo parece estar funcionando, mas você deverá me avisar se encontrar algum bug. Os números das linhas de erro devem ser sincronizados corretamente com os do código executado.
Aqui está um documento de amostra, com a saída mostrada abaixo. \stdoutpythontex
é literalmente por padrão, portanto, o formato não precisa ser especificado como acontece com \printpythontex
(ou equivalente \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}