Problem With \newcommand in latexpdf

350 views
Skip to first unread message

bradley...@gmail.com

unread,
Aug 12, 2020, 8:19:54 AM8/12/20
to sphinx-users
The index.rst file below demonstrates that \newcommand does not work with latexpdf.

------------ Below is my conf.py file ------------------------
# For conf.py documentation see
# http://www.sphinx-doc.org/en/master/config
#
project   = 'newcommand'
extensions = [
    'sphinx.ext.mathjax',
]
------------- Below is my index.rst file -------------------------
Problem With \newcommand in latexpdf
####################################
This file builds just file,
and displays as intended, with ``make html``,
but with ``make latexpdf`` it generates and
``Undefined control sequence.`` error for the
macro ``\B``.

Define Latex Macro
******************
``:math: \newcommand{\B}[1]{{\bf #1}}``
:math:`\newcommand{\B}[1]{{\bf #1}}`

Use Latex Macro \B
******************
``:math: f : \B{R} \rightarrow \B{R}``
:math:`f : \B{R} \rightarrow \B{R}`

This File
*********
.. literalinclude:: index.rst

jfbu

unread,
Aug 13, 2020, 3:16:22 AM8/13/20
to sphinx...@googlegroups.com
Hi,
the LaTeX has scope limiting constructs such as "environments"
but also equations, inclusive of inline mathematics

(delimited in the file in LaTeX mark-up produced by make latex by \( ... \) delimiters)

you must locate the \newcommand outside of such scope delimited location

either via

.. raw:: latex

\newcommand{\B}[1]{{\bf #1}}

before it is used (and only once)

or in conf.py

latex_elements = {
'preamble': r"\newcommand{\B}[1]{{\bf #1}}",
}

which is a priori better location, recommended for that usage.


Once this is done do not put any other \newcommand{\B} as this will generate an error.

Notice that \bf mark-up has been deprecated by LaTeX developers
and perhaps {\mathbf{#1}} is more legit

latex_elements = {
'preamble': r"\newcommand{\B}[1]{\mathbf{#1}}",
}


or, if you use xelatex with unicode-math, perhaps \symbf


Besides LaTeX normative gurus will try to discourage you to define a one-letter
command such as \B. (the rationale being that depending on language perhaps
the one-letter command has a meaning already ; anyway if it does the \newcommand
will then raise an error so you will know).


Jean-François


bradley...@gmail.com

unread,
Aug 13, 2020, 10:14:25 AM8/13/20
to sphinx-users
I am trying to get the same source code to produce both the html pages and a pdf document. I think this is one of the advantages of sphinx ? I was not expecting the scope of commands to be different for the two cases, html and pdf.

I am using a file called preamble.rst to get my definitions for the entire document inside each html page (this includes other commands besides latex command). If I use the latex_elements as suggested above, I have to include the definitions in preamble.rst to build html files and remove them to build latexpdf files. While this doable, it would seem there should be a simpler way.

Perhaps I should ask this with another conservation ?
I have noticed something strange in the latexpdf output (now that I can get it) . The table of contents in the pdf file only seems to include the toctree command in the index.rst file, and not the toctree commands in other files that get included. I am using the Read The Docs theme and the htm_theme_options has 'titles_only' is set to True.

Matthias Geier

unread,
Aug 13, 2020, 10:54:19 AM8/13/20
to sphinx...@googlegroups.com
On Thu, Aug 13, 2020 at 4:14 PM bradley...@gmail.com wrote:
>
> I am trying to get the same source code to produce both the html pages and a pdf document. I think this is one of the advantages of sphinx ?

Yes it is! But sometimes there are a few unexpected hurdles one has to
overcome ...

> I was not expecting the scope of commands to be different for the two cases, html and pdf.

I hope I can shed a bit of light on this:

As Jean-François said before, if you use \newcommand inside math mode,
the definitions are only visible in the current "scope", in this case
the current math block.

That's just how LaTeX works.

The actual bug is that MathJax doesn't behave like LaTeX in this case.

But there is a way to work around this: The low-level TeX counterpart
to \newcommand is \def, which has the same "scoping rules" as
described above. But there is another command called \gdef, which
defines things that are globally visible.

This is great for your use case, but there is a different problem,
because MathJax doesn't support \gdef by default. But there is a
plugin/extension which can be used, see below.

> I am using a file called preamble.rst to get my definitions for the entire document inside each html page (this includes other commands besides latex command). If I use the latex_elements as suggested above, I have to include the definitions in preamble.rst to build html files and remove them to build latexpdf files. While this doable, it would seem there should be a simpler way.

Some of my colleagues and I came up with a somewhat fiddly solution:

We created an RST file that we can include whenever we need math
definitions (I guess similar to your preamble.rst):

https://github.com/sfstoolbox/sfs-python/blob/master/doc/math-definitions.rst

... which looks something like this:

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

.. raw:: latex

\marginpar{% Avoid creating empty vertical space for the math definitions

.. rst-class:: hidden
.. math::

\gdef\dirac#1{\mathop{{}\delta}\left(#1\right)}
\gdef\e#1{\operatorname{e}^{#1}}

% ... more \gdef stuff...

.. raw:: latex

}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

On each page where we need it, we do this:

.. include:: math-definitions.rst

In order to activate the MathJax plugin mentioned above, we add this
to our conf.py:

mathjax_config = {
'TeX': {
'extensions': ['newcommand.js', 'begingroup.js'], # Support for \gdef
},
}

See https://github.com/sfstoolbox/sfs-python/blob/4d55ff05a1d77438ae914ab3b7b5370bfa9dda98/doc/conf.py#L96-L100

There might be a different way to load those plugins (suggested in
https://github.com/jupyterlab/jupyterlab/pull/5997#issuecomment-475289432),
but I have not yet tested this:

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

.. raw:: latex

\newcommand{\require}[1]{}

.. math::

\require{begingroup}\require{newcommand}
\gdef\vec#1{\boldsymbol{#1}}
% ...

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

If you try this, please let me know whether it works or not!

> Perhaps I should ask this with another conservation ?
> I have noticed something strange in the latexpdf output (now that I can get it) . The table of contents in the pdf file only seems to include the toctree command in the index.rst file, and not the toctree commands in other files that get included.

For LaTeX output, all toctree commands are collected to create one big
table of contents at the beginning.

There are no local sub-TOCs like in HTML.

That's yet another difference between HTML and LaTeX output ...

To reduce the differences (if you want that), you can use the :hidden:
option which hides the local TOCs also in HTML output. Depending on
the HTML theme (and its settings, something with "includehidden"),
those hidden entries might be visible in the sidebar or not.

> I am using the Read The Docs theme and the htm_theme_options has 'titles_only' is set to True.

The HTML theme shouldn't affect the LaTeX output (but it might
sneakily run some extension code ... so you never know).

cheers,
Matthias
> --
> You received this message because you are subscribed to the Google Groups "sphinx-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sphinx-users...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/sphinx-users/5ae0887c-7d93-4fa1-bdb7-63c0b8efd5dcn%40googlegroups.com.

Daniel Scott

unread,
Nov 25, 2020, 10:34:57 PM11/25/20
to sphinx...@googlegroups.com
--
You received this message because you are subscribed to the Google Groups "sphinx-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sphinx-users...@googlegroups.com.

bradley...@gmail.com

unread,
Nov 30, 2020, 8:45:05 AM11/30/20
to sphinx-users

I came up with what seemed to me to be a simpler solution. I put the macros in my preamble.rst between two comment lines that I could recognize and remove easily using sed. I then used a wrapper script to build the pdf that fist removed the macors in preamble.rst, then build the pdf, and then replaced the original preamble.rst. Here is my preamble.rst:

    .. |space| unicode:: 0xA0
    .. |tab| replace:: |space| |space| |space| |space|
     
    .. comment BEGIN_LATEX_MACROS
        These latex macros must also be defined in latex_elements in conf.py
     
    .. rst-class:: hidden
     
        :math:`\newcommand{\B}[1]{ {\bf #1} }`
        :math:`\newcommand{\R}[1]{ {\rm #1} }`
     
    .. comment END_LATEX_MACROS

My problem is that I would like to use ReadtheDocs to display my documentation, but I do no know how to get it to run a script between building the html and build the pdf ?

Perhaps there is a way in preamble.rst to conditionaly include the macros depending on if latex or html conversion is being done ?
Reply all
Reply to author
Forward
0 new messages