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: add styling to general index, similar to domain indices #5583

Merged
merged 3 commits into from Nov 6, 2018

Conversation

jfbu
Copy link
Contributor

@jfbu jfbu commented Oct 31, 2018

Closes: #5579. Also closes #5576.

With this here is for example how CPython 3.7 library.pdf renders:

capture d ecran 2018-10-31 a 19 16 38

and

capture d ecran 2018-10-31 a 19 16 52

Compare to the images posted at #5579.

About the underscore character, it shows fine because CPython uses xelatex for pdf builds and this means another font is used than the Sphinx default Courier. Unfortunately the Courier font used by default for monospace font by Sphinx has an underscore glyph which creates continuous lines... one can see that in Sphinx own pdf doc, see top left.

capture d ecran 2018-10-31 a 19 09 22

Sphinx own doc uses \footnotesize\raggedright which explains smaller size.

It fixes #5576 in a way different from #5577: the regex argument of visit_index() in latex.py is used for something completely different: separate from the index a parenthesized comment ("extra") and style it especially as in Python Module Index.

Another slightly breaking change is in \sphinxstyleindexextra, the parentheses stay upright. I feel it looks better. (I will do more detailed review some time later)

@jfbu jfbu added this to the 1.8.2 milestone Oct 31, 2018
@codecov
Copy link

codecov bot commented Oct 31, 2018

Codecov Report

Merging #5583 into 1.8 will increase coverage by <.01%.
The diff coverage is 93.93%.

Impacted file tree graph

@@            Coverage Diff             @@
##              1.8    #5583      +/-   ##
==========================================
+ Coverage   82.05%   82.06%   +<.01%     
==========================================
  Files         306      306              
  Lines       40390    40408      +18     
  Branches     6241     6244       +3     
==========================================
+ Hits        33144    33159      +15     
- Misses       5862     5863       +1     
- Partials     1384     1386       +2
Impacted Files Coverage Δ
tests/test_build_latex.py 95.27% <100%> (ø) ⬆️
sphinx/writers/latex.py 84.12% <92%> (+0.05%) ⬆️
sphinx/builders/html.py 82.83% <0%> (-0.1%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 47bd24e...00a75b2. Read the comment docs.

@@ -1623,8 +1623,11 @@

% additional customizable styling
\def\sphinxstyleindexentry #1{\texttt{#1}}
\def\sphinxstyleindexextra #1{ \emph{(#1)}}
\def\sphinxstyleindexextra #1{ (\emph{#1})}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I moved the parentheses outside the scope of \emph. imho, it looks better this way.

\def\sphinxstyleindexpageref #1{, \pageref{#1}}
\def\sphinxstyleindexpagemain#1{\textbf{#1}}
\protected\def\spxentry#1{#1}% will get \let to \sphinxstyleindexentry in index
\protected\def\spxextra#1{#1}% will get \let to \sphinxstyleindexextra in index
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The visit_index() from LaTeX writer will use \spxentry and \spxextra, this makes smaller LaTeX file than using everywhere \sphinxstyleindexentry, \sphinxstyleindexextra. The macros need to be \protected because they are used inside \index{} macro, and this may occur for example in a tabulary environment (same reason why verbatim can't be used inside tabulary).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I decided to re-use the same \sphinxstyleindexentry and \sphinxstyleindexextra already used by LaTeX writer for domain indices at

def generate_indices(self):
.

An alternative would be to define independent macros \sphinxstylegeneralindexentry, etc...

The \spxentry/\spxextra are privately used, only \sphinxstyleindexentry/... should get redefined by user. The reason for \spxentry/\spxextra is for shorter macro names, hence smaller file.

On the xindy side I looked a bit about using markup-indexentry which currently (in sphinx.xdy) is

(markup-indexentry :open "~n  \item "           :depth 0)

but did not see a way to add there the \spxentry{..} wrapper. Because in case of sub-items, a closing } for example would enclose all sub-items, causing errors. And anyway, the @\spxentry{...} works both with makeindex and xindy. Furthermore I later decided (to match the domain indices) to use \spxentry{...}\spxextra{...}, not \spxentry{...\spxextra{...}}, which I had started with.

(markup-locref :open "\textbf{\hyperpage{" :close "}}" :attr "textbf")
(markup-locref :open "\textit{\hyperpage{" :close "}}" :attr "textit")
(markup-locref :open "\emph{\hyperpage{" :close "}}" :attr "emph")
(markup-locref :open "\spxpagem{\hyperpage{" :close "}}" :attr "spxpagem")
(markup-locref :open "\hyperpage{" :close "}" :attr "default")
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Initially I had also added a spxpage attribute so that one would would have \spxpage{\hyperpage{37}} for example, allowing to style the page number. But this would mean all \index macros would end in \index{...|spxpage] increasing size and overhead of LaTeX file. Then I thought about simply modifying the "default" above to do ...\spxpage{\hyperpage{..., but this method would have been xindy-only. Only the \index{....|spxpage} would have also affected makeindex way.

In the end I dropped this: it is always possible if wanted to style the index page number at LaTeX macro level by modifying \hyperpage.

@@ -193,6 +194,9 @@
(markup-index :open "\begin{sphinxtheindex}
\let\lettergroup\sphinxstyleindexlettergroup
\let\lettergroupDefault\sphinxstyleindexlettergroupDefault
\let\spxpagem\sphinxstyleindexpagemain
\let\spxentry\sphinxstyleindexentry
\let\spxextra\sphinxstyleindexextra
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Regarding \sphinxstyleindexentry and \sphinxstyleindexextra they are the macros used by the LaTeX writer for the mark-up associated with domain indices. The method above allows same mark-up also in general index. But it means too that separate customization will mean from user some extra measure. One method would add to preamble some definition of \stylegeneralindexentry, \stylegeneralindexextra macros, and insert \let\sphinxstyleindexentry\stylegeneralindexentry\let\... before the final index via the latex_elements 'printindex' key.

I also hesitated about moving these \let to the definition of the sphinxtheindex environment, but the latter is used for all indices, including domain indices, where \spxentry and \spxextra do not arise.

@@ -1884,7 +1884,7 @@ def depart_attribution(self, node):
# type: (nodes.Node) -> None
self.body.append('\n\\end{flushright}\n')

def visit_index(self, node, scre=re.compile(r';\s*')):
def visit_index(self, node, extrare=re.compile(r'^(.*\S)\s+\(([^()]*)\)\s*$')):
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is breaking change for extensions who counted on the third argument of visit_index to be the regex allowing to recognize semi-colon. A priori this was not used as public API? so I felt there is no problem using this for something completely different.

The aim of the regex is to identify strings of the type "text (extra in parentheses)". Then the extra in parenthesis will be styled especially. This is a new feature which has drawback that sometimes the parentheses were used by Sphinx user with a somewhat different intent. I found an example in Sphinx own docs, at line 125 of doc/man/sphinx-quickstart.rst:

.. option:: --use-make-mode (-m), --no-use-make-mode (-M)

In this case this will produce in LaTeX file:

\index{--use-make-mode (-m), --no-use-make-mode (-M)@\spxentry{--use-make-mode (-m), --no-use-make-mode}\spxextra{-M}!...}

which causes the -M to be emphasized. In general any

.. option:: --long-name (-l)

will get the -l styled by \spxextra, where the --long-name gets styled by \spxentry.

But this syntax is not the one described at https://www.sphinx-doc.org/en/master/usage/restructuredtext/domains.html#directive-option, so maybe this is not really breaking change. And it only affects typography.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, I agree with this is not a public API. But this must be a breaking change. So -1 for changing signature of method.

I think marking scre keyword as deprecated is better. And I think extrare is not needed to substitute. So how about moving it to constant?

EXTRA_RE = re.compile('...')

...

def visit_index(self, node, scre=None):
    if scre:
        warnings.warn('scre option for visit_index() is deprecated')

    ...

def style(string):
match = extrare.match(string)
if match:
return match.expand(r'\\spxentry{\1}\\spxextra{\2}')
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This mark-up is modeled on

if entry[4]:
# add "extra" info
ret.append('\\sphinxstyleindexextra{%s}' % self.encode(entry[4]))
ret.append('\\sphinxstyleindexpageref{%s:%s}\n' %
(entry[2], self.idescape(entry[3])))

which applies to entries for domain indices. But here the "extra" is recovered from this input syntax:

.. index::
   single: foo (bar)

except ValueError:
p = escape(split_into(1, 'single', string)[0])
P = style(p)
self.body.append(r'\index{%s@%s%s}' % (p, P, m))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This also fixes #5576.

r'\index{%s@\spxentry{%s}!%s, %s@\spxentry{%s, %s}%s}'
r'\index{%s@\spxentry{%s}!%s %s@\spxentry{%s %s}%s}' %
(p1, p1, p2, p3, p2, p3, m, p2, p2, p3, p1, p3, p1, m,
p3, p3, p1, p2, p1, p2, m))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Here for triples I dropped addition of \spxextra styling. But I should add it, I guess.

Copy link
Contributor Author

@jfbu jfbu Nov 1, 2018

Choose a reason for hiding this comment

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

I will push update to incorporate \spxextra styling for p1, p2, p3 if they use foo (bar) style also in this "triple" case. (done at 0f45cf7)

elif type == 'see':
p1, p2 = [escape(x) for x in split_into(2, 'see', string)]
self.body.append(r'\index{%s|see{%s}}' % (p1, p2))
P1 = style(p1)
self.body.append(r'\index{%s@%s|see{%s}}' % (p1, P1, p2))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did not make any attempt into adding mark-up in the see{%s} part as I expected problems, especially to maintain compatibility with both makeindex and xindy.

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.

LGTM with nits

@@ -1884,7 +1884,7 @@ def depart_attribution(self, node):
# type: (nodes.Node) -> None
self.body.append('\n\\end{flushright}\n')

def visit_index(self, node, scre=re.compile(r';\s*')):
def visit_index(self, node, extrare=re.compile(r'^(.*\S)\s+\(([^()]*)\)\s*$')):
Copy link
Member

Choose a reason for hiding this comment

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

Yes, I agree with this is not a public API. But this must be a breaking change. So -1 for changing signature of method.

I think marking scre keyword as deprecated is better. And I think extrare is not needed to substitute. So how about moving it to constant?

EXTRA_RE = re.compile('...')

...

def visit_index(self, node, scre=None):
    if scre:
        warnings.warn('scre option for visit_index() is deprecated')

    ...

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.

LGTM!

@jfbu
Copy link
Contributor Author

jfbu commented Nov 6, 2018

@tk0miya thanks for quick reviewing! I will merge now into 1.8.2 although this is less minimal change than #5577. My estimate indeed is that absence of styling of general index in LaTeX output was a bug.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants