4

I am writing a package that optionally uses the pythontex package. The pythontex package defines an environment pycode which allows you to execute Python code before \begin{document}. As far as I can see, putting the pycode environment within a macro is impossible, so I have to put it in regardless of whether the user wants to use Pythontex or not, and define or redefine it in case the user doesn't want to use it. In that case, I would have to define it in a way that ignores all the code written within the environment and that can be put into the preamble (or rather, can be executed at the loading of my package.)

MWE:

\RequirePackage{etoolbox}
\RequirePackage{xstring}
\RequirePackage{letltxmacro}

\newcommand{\@pythonbool}{false} %This tells us whether the python option is enabled or not.
\newcommand{\@pycodedefined}{false} %This tells us whether the environment pycode is defined at the loading of this style file or not.

\DeclareOption{python}{
\renewcommand{\@pythonbool}{true}
}

\ProcessOptions\relax

\expandafter\ifstrequal\expandafter{\@pythonbool}{false}{
\ifcsmacro{pycode}{
    \renewcommand{\@pycodedefined}{true}
    \LetLtxMacro{\@oldpy}{\pycode}
    \LetLtxMacro{\@oldendpy}{\endpycode}
    \renewenvironment{pycode}{}{} % If pycode is defined (because Pythontex is used), but the package should not use python, this will completely disregard anything in a pycode environment. We will correctly redefine pycode after the code to be disregarded. This is neccessary because we can't put the pycode environment inside a conditional. Arguably, we could also let the code execute, since it doesn't print anything, and so will not change the output, but this is cleaner since we avoid possible naming conflicts. I don't know if it also makes python run less often, which would be a plus too.
}{
    \newenvironment{pycode}{}{} % If pycode is undefined (because Pythontex isn't used), this prevents errors upon Latex encountering the pycode environment, which we otherwise can't, since we can't simply put the pycode environment  into a conditional.
}
}{ \RequirePackage{pythontex}
}

\begin{pycode}
some code
\end{pycode}

\expandafter\ifstrequal\expandafter{\@pycodedefined}{true}{
    \LetLtxMacro{\pycode}{\@oldpy}
    \LetLtxMacro{\endpycode}{\@oldendpy}}{}

The specific point I'm interested in is how I can stop my new definition of the environment from trying to print the code part at all.

Edit: The best way to do this seems to be a command that tells latex to ignore everything between it and its counterpart, but I wouldn't know how to define one.

3

You could define a package option called nopython and provide the following code in the preamble.

\usepackage{comment}
\DeclareOption{nopython}{\excludecomment{pycode}}

Do note the syntactic requirement, stated in the package's user guide, that

The opening and closing commands [of the environment] should appear on a line of their own. No starting spaces, nothing after it.

Applying this syntactic requirement to your document, this means that all \begin{pycode} and \end{pycode} directives must occur on lines of their own, without any starting spaces.


A full MWE, which takes into account new information that the OP uses the scrartcl document class:

\documentclass{scrartcl} 
\usepackage{pythontex} % comment this line out if **not** using PythonTeX
\makeatletter
\AtBeginDocument{\@ifpackageloaded{pythontex}{}{%
  \usepackage{comment} 
  \excludecomment{pycode}}}
\makeatother

\begin{document} 
\begin{pycode} 
Some code. 
\end{pycode} 
Some text. 
\end{document}
  • That seems like a very simple way of achieving it. Your code won't work however, since you can't use packages within DeclareOption, or so I have been told. – sgf Mar 30 '17 at 12:28
  • Also, can I later do \includecomment{pycode} so pycode works again as before? – sgf Mar 30 '17 at 12:31
  • 1
    Sweet! I know how to change your code to work, I just thought someone might try it as-is, so I thought it might be a good idea to point it out. – sgf Mar 30 '17 at 13:51
  • Actually, excludecomment doesn't seem to do the trick, it gives me "\begin{document} was ended by \end{VerbatimOut}" – sgf Mar 30 '17 at 14:25
  • Changed it to comply, but it still gives me the same error (and it works with other environments, I checked.) – sgf Mar 30 '17 at 14:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.