Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No wrapping for cpp:enumerator #7241

Closed
senyai opened this issue Mar 2, 2020 · 11 comments
Closed

No wrapping for cpp:enumerator #7241

senyai opened this issue Mar 2, 2020 · 11 comments

Comments

@senyai
Copy link

senyai commented Mar 2, 2020

Describe the bug

make latexpdf renders to:
image

To Reproduce
Render this rst:

.. cpp:enumerator:: Test::aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = 41
.. cpp:enumerator:: Test::bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb = 42
.. cpp:enumerator:: Test::cccccccccccccccccccccccccccccccccc = 43
.. cpp:enumerator:: Test::longval = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb | cccccccccccccccccccccccccccccccccc

Expected behavior
Word wrapping must occur

Additional context

@senyai
Copy link
Author

senyai commented Mar 5, 2020

I figured sphinx/texinputs/sphinx.sty has this trick:
1689:\newcommand{\pysigline}[1]{\item[{#1}]} which puts input text into \item label. I think, that this is semantically incorrect and is the root of my problem.

@jakobandersen
Copy link
Contributor

@jfbu, is there a way we can get reasonable line wrapping in this case? Except for links and formatting I would typeset the offending line as something like

Test::longval = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
\phantom{Test::longval = }bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb |
\phantom{Test::longval = }cccccccccccccccccccccccccccccccccc

(This is the alignment I referred to in #1514 (comment). How does one do the equivalent in HTML + CSS?)
To fix all these issues with line formatting we should probably come up with a set of new doc node types (if docutils doesn't already have it) that the domains can generate to indicate to the builders what the envisioned line break/indentation/wrapper should be. Each builder then implement those as sophisticated as their target allows, or default to the current formatting behaviour.

@jfbu
Copy link
Contributor

jfbu commented Mar 6, 2020

@senyai Sphinx 1.0 had \newcommand{\pysigline}[1]{\item[#1]\nopagebreak} which is not very different from current one and so the behaviour has been there forever... indeed LaTeX puts in a horizontal unbreakable box then the #1. However this is wrapped in \makelabel which the fulllineitems environment sets to \py@itemnewline. The latter macro has basically also remained unchanged much since 1.0. A conservative approach would be to consider it as the entry point to modify things here.

Using your rst source (thanks), with

latex_elements = {
    'preamble' : r"""
\makeatletter
\newdimen\spx@tempdima
\renewcommand{\py@itemnewline}[1]{%
  \kern\labelsep
  \spx@tempdima\linewidth
  \advance\spx@tempdima\labelwidth
  \makebox[\spx@tempdima][l]{\parbox{\spx@tempdima}{\raggedright#1}}%
  \kern-\labelsep
}
\makeatother
"""
}

(I took this opportunity to replace usage of LaTeX internal scratch register \@tempdima by a safer one once we start inserting like here a LaTeX macro \parbox)

I get this
Capture d’écran 2020-03-06 à 09 41 24

As you see TeX will never do any linewrap in the midst of bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb anyway.

To achieve

Capture d’écran 2020-03-06 à 09 53 58

one would require some mark-up separating the "prefix indentation" from body.

For example if the LaTeX mark-up ended using a two argument \pysigline which here would be like

\pysigline{foo = }{bar}

in place of

\pysigline{foo = bar}

then we could arrange things so that the foo = part would provide the indentation similar as in @jakobandersen \phantom idea but above I used hanging indentation rather.

But this method (of hanging indentation), with shorter strings would lead to this kind of output
Capture d’écran 2020-03-06 à 10 00 30

What is expectation ?

@jfbu
Copy link
Contributor

jfbu commented Mar 6, 2020

sorry I should have used \parbox[t] in my proposal above. Else one observes the reduced vertical space as in the images above.

@senyai
Copy link
Author

senyai commented Mar 6, 2020

I'd vote for last variant of wrapping, but really don't mind either option. And \pysigline{foo = }{bar} would make more sense than single agrument pysigline.

@jfbu
Copy link
Contributor

jfbu commented Mar 6, 2020

perhaps rather \pysigline{{foo = }{bar}} so that the people who have renewcommand'ed \pysigline as a one-argument macro will not see their hacks destroyed (as {foo = }{bar} will give same typeset result as foo = bar). If such people exist... at this stage we are back to @jakobandersen's comment

To fix all these issues with line formatting we should probably come up with a set of new doc node types (if docutils doesn't already have it) that the domains can generate to indicate to the builders what the envisioned line break/indentation/wrapper should be.

@senyai If all your use cases are with an = then I can help provide a specific hacky LaTeX \py@itemnewline which will fix your use case.

@senyai
Copy link
Author

senyai commented Mar 6, 2020

@jfbu thanks a lot for your support, the preamble you posted (+[t]) already solves my problem. I'd better wait for less hacky solution. There's \pysigstartmultiline, maybe it should be used. idk.

@jfbu
Copy link
Contributor

jfbu commented Mar 6, 2020

There's \pysigstartmultiline, maybe it should be used. idk.

This serves only to control some LaTeX paragraph parameters but the actual rendering goes via the pair \pysiglinewithargsret/\py@sigparams. The latter incorporate the \parbox[t] method already, thus \pysiglinewithargsret is able to do some multiline rendering. Which makes me realize that rather than modifying \py@itemnewline I should arguably leave it alone (it is used both for single line and multi line signatures) and modify only the \pysigline.

latex_elements = {
    'preamble' : r"""
\makeatletter
% \py@argswidth is an available length register, use it rather
% than LaTeX's internal \@tempdima as done abusively by \py@itemnewline
\renewcommand{\pysigline}[1]{%
  \setlength{\py@argswidth}{\dimexpr\labelwidth+\linewidth\relax}%
  \item[{\parbox[t]{\py@argswidth}{\raggedright#1}}]}
\makeatother
"""
}

Can you try it? It should give same output as the preamble (+[t]) originally posted.

The \pysiglinewithargsret is macro with 3 arguments and creates a multiline rendering with an indentation given by width of the first argument (and an opening parenthesis (). Thus once, the LaTeX writer has gained the suitable refinement, it is easy to imitate it for an enhanced \pysigline which will act like the above + produce some suitable indentation after first line.

@senyai
Copy link
Author

senyai commented Mar 6, 2020

Can you try it? It should give same output as the preamble (+[t]) originally posted.

Yes, it does.
/me afk for 3 days

@jfbu
Copy link
Contributor

jfbu commented Mar 14, 2021

Partially fixed at 2934aac.

Nicer typeset result should have some hanging indentation.

@senyai
Copy link
Author

senyai commented May 11, 2021

image

Thanks a lot for the fix! Version 4.0.1 has no issue for me. Closing.

@senyai senyai closed this as completed May 11, 2021
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 11, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants