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

LaTeX: optional rounded corners for framing of code-blocks #10639

Merged
merged 3 commits into from Jul 6, 2022

Conversation

jfbu
Copy link
Contributor

@jfbu jfbu commented Jul 4, 2022

Rounded corners for the framing of code-blocks, via a new configuration verbatimradius of 'sphinxsetup', which defaults
to 0pt.

If this dimension is non zero, the LaTeX package pict2e will be loaded
to construct frames with rounded corners for code-blocks. Also, the
default background color will then change from white to a light
gray. And if the LaTeX package pict2e was not found, a LaTeX warning is
issued during PDF build.

Feature or Bugfix

  • Feature

By default, nothing changes: one needs to use the verbatimradius LaTeX key inside 'sphinxsetup'. And if one sets it to a strictly postitive value, the layout in PDFs should not be modified if verbartimsep and verbatimborder stay the same.

Detail

Capture d’écran 2022-07-04 à 23 36 24

another example (the above was with default colors triggered from setting verbatimradius>0pt)

Capture d’écran 2022-07-04 à 23 54 51

This uses the pict2e which is light weight. But on Ubuntu it is part of the somewhat big texlive-pictures, which contains all of pgf+TikZ...

I also tested with a tcolorbox based implementation but there is not much interest if the box is not made much fancier. The impact on build time is very noticeable on big documents if using \tcbox in place of our custom own-defined rounded box based on the pict2e interface to the PDF operators.

Compatible with all engines as far as I know. But not tested for platex (Japanese).

@jfbu jfbu added type:enhancement enhance or introduce a new feature builder:latex labels Jul 4, 2022
@jfbu jfbu added this to the 5.1.0 milestone Jul 4, 2022
@AA-Turner
Copy link
Member

The background colour changing seems surprising due to 'just' changing the rounded corner setting -- is this part necessary?

A

@jfbu
Copy link
Contributor Author

jfbu commented Jul 4, 2022

The background colour changing seems surprising due to 'just' changing the rounded corner setting -- is this part necessary?

It is not necessary indeed. What is done is that if user decides for rounded corners the background color default will be changed from white to light gray. Why did I do that? because I copied over the default color (light gray inside, darkish gray on border) from LaTeX package tcolorbox... I have no strong opinion, I can revert it to keep default white of course.

edit: and actually that would remove some a bit messy coding for this change of default, as the option handler of LaTeX sphinx is not very sophisticated. I mean it is based on robust kvoptions and does not have all the bells and whistles of things such as pgfkeys, l3keys, etc...

@jfbu
Copy link
Contributor Author

jfbu commented Jul 5, 2022

The background colour changing seems surprising due to 'just' changing the rounded corner setting -- is this part necessary?

Thanks @AA-Turner I have now removed this colour change which was indeed not a good idea (and caused some LaTeX coding complications).

@jfbu
Copy link
Contributor Author

jfbu commented Jul 5, 2022

Memo: the reason the new code is presented as a "package" is a bit subtle; it is because its loading will a priori not happen while LaTeX does \usepackage{sphinx} (this would only be the case with e.g. \usepackage[verbatimradius=5pt]{sphinx} or some earlier \PassOptionsToPackage) but at the next line \sphinxsetup{...} and doing \input there requires a \makeatletter. The sphinxlatexboxes code is made into a "package" which can be loaded in the preamble via \RequirePackage to not have to do \makeatletter/\makeatother. I hesitated about this as it is now not possible to set verbatimradius to a positive value from a raw latex directive if it has not already been positive at some point in the preamble and thus triggered the loading of sphinxlatexboxes.sty.

edit: also I called the file "sphinxpackageboxes.sty" and not "sphinxlatexboxes.sty" with the vague idea that it may grow in future... The hardest part is done, and is combined with the recent refactorings in "sphinxlatexliterals.sty" for subtle color issues; I experimented that "tcolorbox" has the similar color issues at page breaks with its "breakable" boxes, which they solve via a "use color stack" option but it is not available for xelatex and besides may alter vertical spacing. The Sphinx approach does not rely on multiple colors stacks.

Anyway, at some point we should probably convert all files sphinxlatex...sty into package files (this is a simple one-liner change at their start, and using in sphinx.sty \RequirePackage rather than \input). The reason this was not done originally is that the reason for the .sty extension is that .tex files in the LaTeX build directory are under the scope of the make latexpdf, so we needed other extension. I chose a few years back .sty in part because .tex.txt turns off syntax highlighting in my Emacs.

Via a new configuration verbatimradius of 'sphinxsetup', which defaults
to 0pt.

If this dimension is non zero, the LaTeX package pict2e will be loaded
to help construct frames with rounded corners for code-blocks.  And if
the LaTeX package pict2e was not found, a LaTeX warning is issued during
PDF build.
@jfbu
Copy link
Contributor Author

jfbu commented Jul 5, 2022

I completely forgot that \expanded was not available before TL2019 generally.

Anyway, pre-expansion was not needed. Updated and tested ok on a system with TeXLive 2013.

There was no need for pre-expansion via \expanded and the latter was not
available prior to TL2019
Copy link
Member

@tk0miya tk0miya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool!

@jfbu
Copy link
Contributor Author

jfbu commented Jul 6, 2022

Thanks @tk0miya and @AA-Turner for comments! I merge this now because I have time til Friday and plan to make a PR extending this with significant enhancements of LaTeX PDF rendering of display boxes (topic, admonitions and litteral-blocks like here):

  • padding parameters for top right bottom left
  • border width for top right bottom left
  • optional opened frames at pagebreaks
  • optional shadows for all boxes
  • optional separation of title from contents in admonition boxes
  • and of course optional rounded corners everywhere...

In short, try to obtain almost HTML-like styling possibilities
...of course with no change to existing default...

@jfbu jfbu merged commit 9da25be into sphinx-doc:5.x Jul 6, 2022
jfbu added a commit that referenced this pull request Jul 6, 2022
@AA-Turner
Copy link
Member

I completely forgot that \expanded was not available before TL2019 generally.

Anyway, pre-expansion was not needed. Updated and tested ok on a system with TeXLive 2013.

@jfbu -- what is our minimum supported TeXLive? I believe that the TUG/TeXLive maintainers only support the latest version -- would it make sense for us to adopt a policy of e.g. current & immediate previous TeXLive? (e.g. currently 2022 and 2021.)

That might allow for code simplifications, using the new programming layer in the kernel, etc? But I am not a LaTeX expert by any means!

A

@jfbu
Copy link
Contributor Author

jfbu commented Jul 6, 2022

@jfbu -- what is our minimum supported TeXLive?

Hi A @AA-Turner, well your question made me realize I have for some time now not followed up closely on our CI policy regarding LaTeX, and it seems we are not testing actual LaTeX runs as far as I can tell from, e.g., https://github.com/sphinx-doc/sphinx/runs/7220623547?check_suite_focus=true#step:8:632

tests/test_build_latex.py::test_build_latex_doc[pdflatex-howto] SKIPPED (not running latex, the required styles do not seem to be installed) [ 33%]
tests/test_build_latex.py::test_build_latex_doc[pdflatex-manual] SKIPPED (not running latex, the required styles do not seem to be installed) [ 33%]
tests/test_build_latex.py::test_build_latex_doc[lualatex-howto] SKIPPED (not running latex, the required styles do not seem to be installed) [ 33%]
tests/test_build_latex.py::test_build_latex_doc[lualatex-manual] SKIPPED (not running latex, the required styles do not seem to be installed) [ 33%]
tests/test_build_latex.py::test_build_latex_doc[xelatex-howto] SKIPPED (not running latex, the required styles do not seem to be installed) [ 33%]
tests/test_build_latex.py::test_build_latex_doc[xelatex-manual] SKIPPED (not running latex, the required styles do not seem to be installed) [ 33%]

I remember in the past that I was more knowledgeable. We do have this in our documentation:

The testing of Sphinx LaTeX is done on Ubuntu xenial whose TeX distribution is based on a TeXLive 2015 snapshot dated March 2016.

Changed in version 1.6: Formerly, testing had been done on Ubuntu precise (TeXLive 2009).

Changed in version 2.0: Formerly, testing had been done on Ubuntu trusty (TeXLive 2013).

And this was indeed true perhaps 2 or 3 years ago, now I don't know.

Back to your question:

I believe that the TUG/TeXLive maintainers only support the latest version -- would it make sense for us to adopt a policy of e.g. current & immediate previous TeXLive? (e.g. currently 2022 and 2021.)

That would definitely simplify maintenance but is way too drastic... The majority of Sphinx users are probably on Linux distros whose TeX distributions notoriously lag behind current TeX-Live by many years. Or at least did so in the past. You can see the above which indicates we always allowed at least 5 years back TeX installations.

That might allow for code simplifications, using the new programming layer in the kernel, etc? But I am not a LaTeX expert by any means!

TL:DR;: For time being I think it is better that we do not use in Sphinx LaTeX code the L3 programming layer and stick to old coding style. Update: I realize I focused on one way of understanding your question. Another way is to use packages which require recent LaTeX changes. Perhaps in the area of "tables" is where I see potential for this ; some years ago there were naturally queries for Sphinx to use "tabu" package which was a very innovative and widely used; but it became unmaintained with unsolved bugs so it is fortunate we did not use it. Some new packages have appeared which require recent LaTeX. However, Sphinx already has some structure to solve problems there for which there is no equivalent in the world of LaTeX packages: I am alluding to the merged cells of grid-tables... I don't see how to guarantee backwards compatibility if you jump on even formula one level racing package using fully modern LaTeX... OK, I have made my reply even longer, but at least I did catch some sleep in-between...


(lengthy musings)

This is complicated topic. After a long period of quasi immobility, the LaTeX kernel has evolved at a continuous rate since about 2015. In particular issues related to Unicode in filenames or labels, or multiple dots in filenames of graphics files have evolved positively. Their main preoccupations at this time seem to revolve around PDF tagging (for which some Adobe funding was granted) and integration into the kernel of hyperref. This will take many years. The programming layer encapsulates expert knowledge of core TeX tokenization and box model into some logically structured conventions and vocabulary which allow to package authors to achieve logically complicated tasks without in fact needing to have this expert knowledge of core TeX. But I don't see how the LaTeX user base, which at 99,9% never understood much to TeX macros (for example most people using LaTeX never really understand space tokens ; even authors of very big packages do not necessarily understand it well), would suddenly become fluent in things such as:

\par ->\scan_stop: \mode_if_horizontal:TF {\mode_if_inner:F {\tex_unskip:D \hoo
k_use:n {para/end}\@kernel@after@para@end \mode_if_horizontal:TF {\if_int_compa
re:w 11=\tex_lastnodetype:D \tex_hskip:D \c_zero_dim \fi: \tex_par:D \hook_use:
n {para/after}\@kernel@after@para@after }{\msg_error:nnnn {hooks}{para-mode}{en
d}{horizontal}}}}\tex_par:D 

\mode_if_horizontal:TF ->\if_mode_horizontal: \__prg_TF_true:w \fi: \use_ii:nn 

\use_ii:nn #1#2->#2
#1<-\mode_if_inner:F {\tex_unskip:D \hook_use:n {para/end}\@kernel@after@para@e
nd \mode_if_horizontal:TF {\if_int_compare:w 11=\tex_lastnodetype:D \tex_hskip:
D \c_zero_dim \fi: \tex_par:D \hook_use:n {para/after}\@kernel@after@para@after
 }{\msg_error:nnnn {hooks}{para-mode}{end}{horizontal}}}
#2<-\tex_par:D 

\g__para_standard_everypar_tl ->\box_gset_to_last:N \g_para_indent_box \group_b
egin: \tex_par:D \group_end: \tex_everypar:D {\msg_error:nnnn {hooks}{para-mode
}{before}{vertical}}\@kernel@before@para@before \hook_use:n {para/before}\group
_begin: \tex_everypar:D {}\skip_zero:N \tex_parskip:D \tex_noindent:D \group_en
d: \tex_everypar:D {\g__para_standard_everypar_tl }\@kernel@before@para@begin \
hook_use:n {para/begin}\if_mode_horizontal: \else: \msg_error:nnnn {hooks}{para
-mode}{begin}{vertical}\fi: \__para_handle_indent: \the \toks 11 

\box_gset_to_last:N #1->\tex_global:D \tex_setbox:D #1\tex_lastbox:D 
#1<-\g_para_indent_box 

\@kernel@before@para@before ->

\hook_use:n #1->\if_cs_exist:w __hook #1\cs_end: \cs:w __hook #1\exp_after:wN \
cs_end: \fi: 
#1<-para/before

\__hook para/before ->\__hook_toplevel para/before \__hook_next para/before 

\__hook_toplevel para/before ->

\__hook_next para/before ->

\skip_zero:N #1->#1=\c_zero_skip 
#1<-\tex_parskip:D 

\@kernel@before@para@begin ->

\hook_use:n #1->\if_cs_exist:w __hook #1\cs_end: \cs:w __hook #1\exp_after:wN \
cs_end: \fi: 
#1<-para/begin

\__hook para/begin ->\__hook_toplevel para/begin \__hook_next para/begin 

\__hook_toplevel para/begin ->

\__hook_next para/begin ->

\__para_handle_indent: ->\box_use_drop:N \g_para_indent_box 

\par ->\scan_stop: \mode_if_horizontal:TF {\mode_if_inner:F {\tex_unskip:D \hoo
k_use:n {para/end}\@kernel@after@para@end \mode_if_horizontal:TF {\if_int_compa
re:w 11=\tex_lastnodetype:D \tex_hskip:D \c_zero_dim \fi: \tex_par:D \hook_use:
n {para/after}\@kernel@after@para@after }{\msg_error:nnnn {hooks}{para-mode}{en
d}{horizontal}}}}\tex_par:D 

\mode_if_horizontal:TF ->\if_mode_horizontal: \__prg_TF_true:w \fi: \use_ii:nn 

\__prg_TF_true:w \fi: \use_ii:nn ->\fi: \use_i:nn 

\use_i:nn #1#2->#1
#1<-\mode_if_inner:F {\tex_unskip:D \hook_use:n {para/end}\@kernel@after@para@e
nd \mode_if_horizontal:TF {\if_int_compare:w 11=\tex_lastnodetype:D \tex_hskip:
D \c_zero_dim \fi: \tex_par:D \hook_use:n {para/after}\@kernel@after@para@after
 }{\msg_error:nnnn {hooks}{para-mode}{end}{horizontal}}}
#2<-\tex_par:D 

\mode_if_inner:F ->\if_mode_inner: \__prg_F_true:w \fi: \use:n 

\use:n #1->#1
#1<-\tex_unskip:D \hook_use:n {para/end}\@kernel@after@para@end \mode_if_horizo
ntal:TF {\if_int_compare:w 11=\tex_lastnodetype:D \tex_hskip:D \c_zero_dim \fi:
 \tex_par:D \hook_use:n {para/after}\@kernel@after@para@after }{\msg_error:nnnn
 {hooks}{para-mode}{end}{horizontal}}

\hook_use:n #1->\if_cs_exist:w __hook #1\cs_end: \cs:w __hook #1\exp_after:wN \
cs_end: \fi: 
#1<-para/end

\__hook para/end ->\__hook_toplevel para/end \__hook_next para/end 

\__hook_toplevel para/end ->

\__hook_next para/end ->

\@kernel@after@para@end ->

\mode_if_horizontal:TF ->\if_mode_horizontal: \__prg_TF_true:w \fi: \use_ii:nn 

\__prg_TF_true:w \fi: \use_ii:nn ->\fi: \use_i:nn 

\use_i:nn #1#2->#1
#1<-\if_int_compare:w 11=\tex_lastnodetype:D \tex_hskip:D \c_zero_dim \fi: \tex
_par:D \hook_use:n {para/after}\@kernel@after@para@after 
#2<-\msg_error:nnnn {hooks}{para-mode}{end}{horizontal}

\hook_use:n #1->\if_cs_exist:w __hook #1\cs_end: \cs:w __hook #1\exp_after:wN \
cs_end: \fi: 
#1<-para/after

\__hook para/after ->\__hook_toplevel para/after \__hook_next para/after 

\__hook_toplevel para/after ->

\__hook_next para/after ->

\@kernel@after@para@after ->

which is the trace with current LaTeX of this innocent input:

\documentclass{article}

\begin{document}

\tracingmacros1

Hello

\tracingmacros0

\end{document}

and trust me you don't want to see what happens if \end{document} is traced... certainly such changes in recent LaTeX makes it more "interesting" to decipher simple bugs from simply trying to trace things... already the handling of fonts causes hundreds of trace lines, now we have dozens of L3 lines... (this is not criticism; I am aware that since I became involved in Sphinx LaTeX I maybe have multiplied its size by 5 or 10... always pretending to solve layout issues and "simplify things" ;-) )

Notice also that a great many of the advantages of this programming layer is that it encapsulates extensions to the TeX/LaTeX of the 20th century with the e-TeX extensions of 1999 and more recent engine-level extensions. This is all hidden to casual student of this programming layer who will not know that this is what makes the thing tick.

Things such as \expanded which was first coming with LuaTeX, then around 2019 added to XeTeX and PDFTeX allows greatly simplify things for some macro programming tasks. One can use it directly and does not have to go through the L3 programming layer for that. Also, as my blunder showed, powerful things are not always needed: not only did I use \expanded which is not available prior to 2019, in fact I did not at all need to employ it at that place...

For time being I think it is better that we do not use in Sphinx LaTeX code the L3 programming layer and stick to old coding style.

@jfbu jfbu deleted the latex_roundedboxes branch July 7, 2022 06:28
@jfbu
Copy link
Contributor Author

jfbu commented Jul 14, 2022

was superseded by #10648

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 14, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
builder:latex type:enhancement enhance or introduce a new feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants