From 7be68b7c4b89ca97caca783f2c8a2e2a172aefe1 Mon Sep 17 00:00:00 2001 From: jfbu Date: Mon, 30 Sep 2019 11:52:34 +0200 Subject: [PATCH 1/3] Add latexpdf support for Greek as main language (via xelatex use) Closes: #6710 --- CHANGES | 1 + doc/latex.rst | 5 +++++ doc/usage/configuration.rst | 12 +++++++++++- sphinx/builders/latex/__init__.py | 2 ++ sphinx/writers/latex.py | 7 +++++++ tests/test_build_latex.py | 11 +++++++++++ 6 files changed, 37 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 7d4015556..b2de57f36 100644 --- a/CHANGES +++ b/CHANGES @@ -17,6 +17,7 @@ Bugs fixed ---------- * #6641: LaTeX: Undefined control sequence ``\sphinxmaketitle`` +* #6710: LaTeX not well configured for Greek language as main language Testing -------- diff --git a/doc/latex.rst b/doc/latex.rst index 39c87484d..2501d1594 100644 --- a/doc/latex.rst +++ b/doc/latex.rst @@ -289,6 +289,11 @@ into the generated ``.tex`` files. Its ``'sphinxsetup'`` key is described .. attention:: + If Greek is main language, do not use this key. Since Sphinx 2.2.1, + ``xelatex`` will be used automatically as :confval:`latex_engine`. + Formerly, Sphinx did not support producing PDF via LaTeX with Greek as + main language. + Prior to 2.0, Unicode Greek letters were escaped to use LaTeX math mark-up. This is not the case anymore, and the above must be used (only in case of ``'pdflatex'`` engine) if the source contains such diff --git a/doc/usage/configuration.rst b/doc/usage/configuration.rst index 6619c5015..02b40256d 100644 --- a/doc/usage/configuration.rst +++ b/doc/usage/configuration.rst @@ -1841,7 +1841,17 @@ These options influence LaTeX output. ``'xelatex'`` or ``'lualatex'`` and making sure to use an OpenType font with wide-enough glyph coverage is often easier than trying to make ``'pdflatex'`` work with the extra Unicode characters. Since Sphinx 2.0 - the default is the GNU FreeFont which covers well Latin, Cyrillic and Greek. + the default is the GNU FreeFont which covers well Latin, Cyrillic and + Greek. + + .. versionchanged:: 2.1.0 + + Use ``xelatex`` (and LaTeX package ``xeCJK``) by default for Chinese + documents. + + .. versionchanged:: 2.2.1 + + Use ``xelatex`` by default for Greek documents. Contrarily to :ref:`MathJaX math rendering in HTML output `, LaTeX requires some extra configuration to support Unicode literals in diff --git a/sphinx/builders/latex/__init__.py b/sphinx/builders/latex/__init__.py index 69735ec47..a8d811a49 100644 --- a/sphinx/builders/latex/__init__.py +++ b/sphinx/builders/latex/__init__.py @@ -418,6 +418,8 @@ def default_latex_engine(config: Config) -> str: return 'platex' elif (config.language or '').startswith('zh'): return 'xelatex' + elif (config.language or '') == 'el': + return 'xelatex' else: return 'pdflatex' diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 5fdcb5b93..832d34dfa 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -116,6 +116,10 @@ XELATEX_DEFAULT_FONTPKG = r''' BoldItalicFont = *BoldOblique, ] ''' +XELATEX_GREEK_DEFAULT_FONTPKG = (XELATEX_DEFAULT_FONTPKG + + '\n\\newfontfamily\\greekfont{FreeSerif}' + + '\n\\newfontfamily\\greekfontsf{FreeSans}' + + '\n\\newfontfamily\\greekfonttt{FreeMono}') LUALATEX_DEFAULT_FONTPKG = XELATEX_DEFAULT_FONTPKG DEFAULT_SETTINGS = { @@ -226,6 +230,9 @@ ADDITIONAL_SETTINGS = { ('xelatex', 'zh'): { 'fontenc': '\\usepackage{xeCJK}', }, + ('xelatex', 'el'): { + 'fontpkg': XELATEX_GREEK_DEFAULT_FONTPKG, + }, } # type: Dict[Any, Dict[str, Any]] EXTRA_RE = re.compile(r'^(.*\S)\s+\(([^()]*)\)\s*$') diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py index 67491ddc9..802632731 100644 --- a/tests/test_build_latex.py +++ b/tests/test_build_latex.py @@ -175,6 +175,17 @@ def test_latex_additional_settings_for_language_code(app, status, warning): assert r'\usepackage{xeCJK}' in result +@pytest.mark.sphinx('latex', testroot='basic', confoverrides={'language': 'el'}) +def test_latex_additional_settings_for_greek(app, status, warning): + app.builder.build_all() + result = (app.outdir / 'test.tex').text(encoding='utf8') + print(result) + print(status.getvalue()) + print(warning.getvalue()) + assert '\\usepackage{polyglossia}\n\\setmainlanguage{greek}' in result + assert '\\newfontfamily\\greekfonttt{FreeMono}' in result + + @pytest.mark.sphinx('latex', testroot='latex-title') def test_latex_title_after_admonitions(app, status, warning): app.builder.build_all() From 6a1ea849c2235bc10d862e8b900009c11592b02b Mon Sep 17 00:00:00 2001 From: jfbu Date: Sun, 6 Oct 2019 21:18:38 +0200 Subject: [PATCH 2/3] Remove superfluous ``or ''`` from a conditional --- sphinx/builders/latex/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/builders/latex/__init__.py b/sphinx/builders/latex/__init__.py index a8d811a49..9c34b5568 100644 --- a/sphinx/builders/latex/__init__.py +++ b/sphinx/builders/latex/__init__.py @@ -418,7 +418,7 @@ def default_latex_engine(config: Config) -> str: return 'platex' elif (config.language or '').startswith('zh'): return 'xelatex' - elif (config.language or '') == 'el': + elif config.language == 'el': return 'xelatex' else: return 'pdflatex' From 0b719faabb640bf620d62d947b51166715d2477e Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 20 Oct 2019 13:33:44 +0900 Subject: [PATCH 3/3] Fix mypy violations (for mypy-0.740) --- setup.py | 2 +- sphinx/domains/cpp.py | 5 +++-- sphinx/util/docutils.py | 2 +- sphinx/util/matching.py | 4 ++-- sphinx/util/pycompat.py | 2 +- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/setup.py b/setup.py index 1f3999490..17d4f8fc6 100644 --- a/setup.py +++ b/setup.py @@ -47,7 +47,7 @@ extras_require = { 'html5lib', 'flake8>=3.5.0', 'flake8-import-order', - 'mypy>=0.730', + 'mypy>=0.740', 'docutils-stubs', ], } diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index 417bdb2b6..2d948b853 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -32,7 +32,8 @@ from sphinx.util.nodes import make_refnode if False: # For type annotation - from typing import Any, Callable, Dict, Iterator, List, Match, Pattern, Tuple, Union # NOQA + from docutils.nodes import TextElement + from typing import Any, Callable, Dict, Iterator, List, Match, Pattern, Tuple, Type, Union # NOQA from sphinx.application import Sphinx # NOQA from sphinx.builders import Builder # NOQA from sphinx.config import Config # NOQA @@ -6980,7 +6981,7 @@ class CPPExprRole: if asCode: # render the expression as inline code self.class_type = 'cpp-expr' - self.node_type = nodes.literal + self.node_type = nodes.literal # type: Type[TextElement] else: # render the expression as inline text self.class_type = 'cpp-texpr' diff --git a/sphinx/util/docutils.py b/sphinx/util/docutils.py index 0f732411c..e455d0aad 100644 --- a/sphinx/util/docutils.py +++ b/sphinx/util/docutils.py @@ -187,7 +187,7 @@ class sphinx_domains: def __enter__(self) -> None: self.enable() - def __exit__(self, exc_type: "Type[Exception]", exc_value: Exception, traceback: Any) -> bool: # NOQA + def __exit__(self, exc_type: "Type[Exception]", exc_value: Exception, traceback: Any) -> bool: # type: ignore # NOQA self.disable() return False diff --git a/sphinx/util/matching.py b/sphinx/util/matching.py index 97eeff40f..cd8e16e20 100644 --- a/sphinx/util/matching.py +++ b/sphinx/util/matching.py @@ -9,7 +9,7 @@ """ import re -from typing import Callable, Dict, List, Match, Pattern +from typing import Callable, Dict, Iterable, List, Match, Pattern from sphinx.util.osutil import canon_path @@ -96,7 +96,7 @@ def patmatch(name: str, pat: str) -> Match[str]: return _pat_cache[pat].match(name) -def patfilter(names: List[str], pat: str) -> List[str]: +def patfilter(names: Iterable[str], pat: str) -> List[str]: """Return the subset of the list NAMES that match PAT. Adapted from fnmatch module. diff --git a/sphinx/util/pycompat.py b/sphinx/util/pycompat.py index 06d3bcc2c..18c44ad18 100644 --- a/sphinx/util/pycompat.py +++ b/sphinx/util/pycompat.py @@ -55,7 +55,7 @@ class UnicodeMixin: def __str__(self): warnings.warn('UnicodeMixin is deprecated', RemovedInSphinx40Warning, stacklevel=2) - return self.__unicode__() + return self.__unicode__() # type: ignore def execfile_(filepath: str, _globals: Any, open: Callable = open) -> None: