Есть ли способ взаимодействовать с оболочкой, оставляя открытым тот же сеанс?

Есть ли способ взаимодействовать с оболочкой, оставляя открытым тот же сеанс?

Я готовлю некоторые материалы курса (PDF) для руководства, которое включает в себя командную строку Unix. Поскольку я стремлюсь к автоматизации (некоторые называют это ленью), я написал небольшой пакет, который позволяет мне, используя \write18(with --shell-escape) и verbatimпакет,

  1. запускать команды (например ls, ) по командев течениекомпиляция моего .texдокумента и набор их в моем документе,
  2. перенаправить полученные stdoutи stderrво внешние файлы,
  3. введите эти внешние файлы для набора текста 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. Вам нужно будет использовать стандартную pythontex3-шаговую компиляцию всякий раз, когда у вас есть новый код 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}

введите описание изображения здесь

Связанный контент