**********************
Sage, LaTeX 及其朋友们
**********************

Sage 与 TeX 的 LaTeX 方言之间存在着密切的协同关系。
本节旨在介绍各种交互方式，从最基本的开始，然后介绍一些不常见的用法。

基本使用
========

Sage 中的每个“对象”都必须有 LaTeX 表示。你可以通过执行 ``latex(foo)`` 来获取这种表示，
其中 ``foo`` 是 Sage 中的某个对象。输出是一个字符串，当在 TeX 的数学模式中使用时
（例如，包围在一对单美元符号之间），该字符串应该能够准确地呈现 ``foo``。以下是一些示例。 ::

    sage: var('z')
    z
    sage: latex(z^12)
    z^{12}
    sage: latex(sqrt(z^2 + 1/2))
    \sqrt{z^{2} + \frac{1}{2}}
    sage: latex('a string')
    \text{\texttt{a{ }string}}
    sage: latex(QQ)
    \Bold{Q}
    sage: latex(ZZ['x'])
    \Bold{Z}[x]
    sage: latex(matrix(QQ, 2, 3, [[2,4,6],[-1,-1,-1]]))
    \left(\begin{array}{rrr}
    2 & 4 & 6 \\
    -1 & -1 & -1
    \end{array}\right)

通过这种方式，Sage 可以有效地用于构建 LaTeX 文档的各个部分：
在 Sage 中创建或计算一个对象 ``foo``，对该对象执行 ``latex(foo)``，
然后将 LaTeX 字符串剪切并粘贴到你的文档中。

命令 ``view(foo)`` 会显示对象 ``foo`` 的渲染后的 LaTeX 表示。
在后台，该命令会运行 ``latex(foo)`` 并将 LaTeX 字符串合并到一个简单的 LaTeX 文档中，
用系统范围内的 TeX 安装处理该文档，然后调用合适的查看器来显示输出。

在 Jupyter Notebook 中，你可以自动看到输入命令输出的渲染 LaTeX 表示。
你可以通过执行 ``%display latex`` 来启动自动渲染（并通过执行 ``%display plain`` 停止）。

.. ONLY:: html

    因此，在 Jupyter notebook 中，你得到

    .. JUPYTER-EXECUTE::

        %display latex
        var('z')
        z^12

    .. JUPYTER-EXECUTE::

        sqrt(z^2 + 1/2)

    .. JUPYTER-EXECUTE::

        'a string'

    .. JUPYTER-EXECUTE::

        QQ

    .. JUPYTER-EXECUTE::

        ZZ['x']

    .. JUPYTER-EXECUTE::

        matrix(QQ, 2, 3, [[2,4,6],[-1,-1,-1]])

    .. JUPYTER-EXECUTE::

        %display plain

Jupyter Notebook 使用 `MathJax <http://www.mathjax.org>`_ 在网页浏览器中清晰地渲染数学内容。
MathJax 是一个开源的 JavaScript 数学显示引擎，可以在所有现代浏览器中使用。
它能够渲染大部分 LaTex，但并不支持完整的 LaTeX，是 LaTex 的子集。
它不支持复杂表格、分段或文档管理，因为它主要用于准确渲染 LaTeX 数学片段。

在 Jupyter Notebook 中自动 LaTeX 渲染（启用 ``%display latex``）
是通过 :class:`sage.misc.html.MathJax` 类内部实现的。
该类的对象将 Sage 对象通过 ``latex()`` 转换为 MathJax 需要的 HTML 形式，然后将其包装在 HTML 中。  ::

    sage: from sage.misc.html import MathJax
    sage: mj = MathJax()
    sage: var('z')
    z
    sage: mj(z^12)
    <html>\[z^{12}\]</html>
    sage: mj(sqrt(z^2 + 1/2))
    <html>\[\sqrt{z^{2} + \frac{1}{2}}\]</html>
    sage: mj('a string')
    <html>\[\verb|a|\verb| |\verb|string|\]</html>
    sage: mj(QQ)
    <html>\[\newcommand{\Bold}[1]{\mathbf{#1}}\Bold{Q}\]</html>
    sage: mj(ZZ['x'])
    <html>\[\newcommand{\Bold}[1]{\mathbf{#1}}\Bold{Z}[x]\]</html>
    sage: mj(matrix(QQ, 2, 3, [[2,4,6],[-1,-1,-1]]))
    <html>\[\left(\begin{array}{rrr}
    2 & 4 & 6 \\
    -1 & -1 & -1
    \end{array}\right)\]</html>

如果你需要了解 Sage 对象的 LaTeX 渲染，那么了解这一点很有用。


.. _sec-custom-generation:

自定义 LaTeX 生成
=================

有几种方法可以自定义由 ``latex()`` 命令生成的实际 LaTeX 代码。
预定义对象 ``latex`` 包含多个方法，可以通过输入 ``latex.`` （注意这里有一个点）后按 :kbd:`Tab` 键来列出这些方法。

``latex.matrix_delimiters`` 方法是一个很好的例子。
它可以用来更改矩阵周围的符号 -- 大括号、方括号、花括号、竖线。
不强制执行任何样式，你可以随意混合搭配。
注意，LaTeX 所需的反斜杠在 Python 字符串中需要额外加一个斜杠以便正确转义。  ::

    sage: A = matrix(ZZ, 2, 2, range(4))
    sage: latex(A)
    \left(\begin{array}{rr}
    0 & 1 \\
    2 & 3
    \end{array}\right)
    sage: latex.matrix_delimiters(left='[', right=']')
    sage: latex(A)
    \left[\begin{array}{rr}
    0 & 1 \\
    2 & 3
    \end{array}\right]
    sage: latex.matrix_delimiters(left='\\{', right='\\}')
    sage: latex(A)
    \left\{\begin{array}{rr}
    0 & 1 \\
    2 & 3
    \end{array}\right\}

``latex.vector_delimiters`` 方法的工作原理与之类似。

常见环和域（整数、有理数、实数等）的排版方式可以通过 ``latex.blackboard_bold`` 方法来控制。
这些集合默认以粗体排版，但有时可以选择以双重划线格式书写，如某些书面作品所做的那样。
这可以通过重新定义 Sage 内置的 ``\Bold{}`` 宏来实现。 ::

    sage: latex(QQ)
    \Bold{Q}
    sage: from sage.misc.html import MathJax
    sage: mj = MathJax()
    sage: mj(QQ)
    <html>\[\newcommand{\Bold}[1]{\mathbf{#1}}\Bold{Q}\]</html>
    sage: latex.blackboard_bold(True)
    sage: mj(QQ)
    <html>\[\newcommand{\Bold}[1]{\mathbb{#1}}\Bold{Q}\]</html>
    sage: latex.blackboard_bold(False)

.. ONLY:: html

    在 Jupyter notebook 中，

    .. JUPYTER-EXECUTE::

        %display latex
        QQ

    .. JUPYTER-EXECUTE::

        latex.blackboard_bold(True)
        QQ

    .. JUPYTER-EXECUTE::

        latex.blackboard_bold(False)
        %display plain

可以通过加入新的宏来利用 LaTeX 的可扩展性。可以添加单个宏，以便在 MathJax 解释 LaTeX 片段时使用。 ::

    sage: latex.add_macro(r"\newcommand{\sqrt}[1]{(#1)^\frac{1}{2}}")
    sage: latex.extra_macros()
    '\\newcommand{\\sqrt}[1]{(#1)^\\frac{1}{2}}'
    sage: var('x y')
    (x, y)
    sage: latex(sqrt(x+y))
    \sqrt{x + y}
    sage: from sage.misc.html import MathJax
    sage: mj = MathJax()
    sage: mj(sqrt(x + y))
    <html>\[\newcommand{\sqrt}[1]{(#1)^\frac{1}{2}}\sqrt{x + y}\]</html>
    sage: latex.extra_macros('')

.. ONLY:: html

    在 Jupyter notebook 中，

    .. JUPYTER-EXECUTE::

        %display latex
        var('x y')
        sqrt(x + y)

    .. JUPYTER-EXECUTE::

        latex.add_macro(r"\newcommand{\sqrt}[1]{(#1)^\frac{1}{2}}")
        sqrt(x + y)

    .. JUPYTER-EXECUTE::

        latex.extra_macros('')
        %display plain


.. _sec-custom-processing:

自定义 LaTeX 处理
=================

系统范围内的 TeX 被调用来处理完整的 LaTeX 文档，例如，当你 ``view(foo)`` 时，
其中 ``foo`` 是一个复杂的 Sage 对象，太复杂以至于 ``MathJax`` 无法处理。
命令 ``latex_extra_preamble`` 用于构建完整 LaTeX 文档的导言部分，下面将展示如何完成这项工作。
如往常一样，请注意 Python 字符串中需要双反斜杠。 ::

    sage: latex.extra_macros('')
    sage: latex.extra_preamble('')
    sage: from sage.misc.latex import latex_extra_preamble
    sage: print(latex_extra_preamble())
    \newcommand{\ZZ}{\Bold{Z}}
    ...
    \newcommand{\Bold}[1]{\mathbf{#1}}
    sage: latex.add_macro("\\newcommand{\\foo}{bar}")
    sage: print(latex_extra_preamble())
    \newcommand{\ZZ}{\Bold{Z}}
    ...
    \newcommand{\Bold}[1]{\mathbf{#1}}
    \newcommand{\foo}{bar}

同样，对于更大或更复杂的 LaTeX 表达式，可以将包（或其他任意内容）添加到 LaTeX 文件的导言部分。
任意内容都可以通过 ``latex.add_to_preamble`` 命令加入导言部分，
专用命令 ``latex.add_package_to_preamble_if_available`` 会首先检查某个包是否实际存在，
然后尝试将其添加到导言部分。

这里我们将几何包添加到导言部分并用它来设置 TeX 将在页面上使用的区域尺寸（有效地设置边距）。
如往常一样，请注意 Python 字符串中需要双反斜杠。 ::

    sage: from sage.misc.latex import latex_extra_preamble
    sage: latex.extra_macros('')
    sage: latex.extra_preamble('')
    sage: latex.add_to_preamble('\\usepackage{geometry}')
    sage: latex.add_to_preamble('\\geometry{letterpaper,total={8in,10in}}')
    sage: latex.extra_preamble()
    '\\usepackage{geometry}\\geometry{letterpaper,total={8in,10in}}'
    sage: print(latex_extra_preamble())
    \usepackage{geometry}\geometry{letterpaper,total={8in,10in}}
    \newcommand{\ZZ}{\Bold{Z}}
    ...
    \newcommand{\Bold}[1]{\mathbf{#1}}

可以通过检查其存在性来添加特定包，以下示例展示了这种情况。作为示例，我们将尝试向导言部分添加一个可能不存在的包。 ::

    sage: latex.extra_preamble('')
    sage: latex.extra_preamble()
    ''
    sage: latex.add_to_preamble('\\usepackage{foo-bar-unchecked}')
    sage: latex.extra_preamble()
    '\\usepackage{foo-bar-unchecked}'
    sage: latex.add_package_to_preamble_if_available('foo-bar-checked')
    sage: latex.extra_preamble()
    '\\usepackage{foo-bar-unchecked}'

使用哪种 TeX 方言，以及输出和相关查看器的性质，也可以定制。

.. NOTE::

    Sage 几乎包括了构建和使用 Sage 所需的一切，但一个重要的例外是 TeX 本身。
    因此，在以下情况下，你需要安装完整的 TeX 系统以及一些相关的转换工具。
    许多版本的 Linux 都有基于 TeXLive 的软件包，macOS 有 MacTeX，Windows 有 MiKTeX。

可以使用 ``latex.engine()`` 命令控制是否使用系统范围内的 ``latex``, ``pdflatex`` 或 ``xelatex`` 可执行文件。
当调用 ``view()`` 并且引擎设置为 ``latex`` 时，会生成一个 dvi 文件，Sage 会使用 dvi 查看器（如 xdvi）来显示结果。
相比之下，当引擎设置为 ``pdflatex`` 时，调用 ``view()`` 会生成 PDF 文件，
并且 Sage 会调用系统的 PDF 文件查看工具（如 acrobat, okular, evince 等）。

对于使用这些工具的练习，有一些预先打包好的示例。
要使用这些示例，需要导入 ``sage.misc.latex.latex_examples`` 对象，
这是 :class:`sage.misc.latex.LatexExamples` 类的一个实例，如下所示。
目前该类有交换图、组合图、扭结理论和 pstricks 的示例，分别使用以下包：xy，tkz-graph，xypic，pstricks。
导入后，对 ``latex_examples`` 使用 tab 补全查看内置示例。
调用每个示例会返回一些关于如何正确呈现该示例的说明。要实际查看示例，需要使用 ``view(foo)`` （导言部分、引擎等均设置正确）。 ::

    sage: from sage.misc.latex import latex_examples
    sage: foo = latex_examples.diagram()
    sage: foo
    LaTeX example for testing display of a commutative diagram produced
    by xypic.
    <BLANKLINE>
    To use, try to view this object -- it will not work.  Now try
    'latex.add_to_preamble("\\usepackage[matrix,arrow,curve,cmtip]{xy}")',
    and try viewing again. You should get a picture (a part of the diagram arising
    from a filtered chain complex).

为了展示如何处理复杂的 LaTeX 表达式，让我们看一下使用 ``tkz-graph`` LaTeX 包的组合图示例。

.. NOTE::

    ``tkz-graph`` LaTeX 包建立在 ``pgf`` 库的 ``tikz`` 前端之上。
    渲染组合图需要 ``pgf`` 库以及文件 ``tkz-graph.sty`` 和 ``tkz-berge.sty``。
    它们很可能已经是系统范围内 TeX 安装的一部分。即使不是，也应当很容易找到安装指南。

首先，我们通过将相关包添加到 LaTeX 文档的导言部分来确保它们被包含在内。 ::

    sage: latex.extra_preamble('\\usepackage{tikz}\n\\usepackage{tkz-graph}\n'
    ....:                      '\\usepackage{tkz-berge}\n\\usetikzlibrary{arrows,shapes}')

当使用 dvi 文件作为中间格式时，图形无法正确生成，因此最好将 LaTeX 引擎设置为 ``pdflatex`` 可执行文件。 ::

    sage: latex.engine('pdflatex')

此时，像 ``view(graphs.CompleteGraph(4))`` 这样的命令应该生成一个带有完整图 `K_4` 适当图像的 PDF。

实际上，可以省略前面的步骤，因为导言部分会自动正确设置，并且 ``pdflatex`` 是 Sage 的默认 LaTeX 引擎。
重新启动 Sage 后再次尝试该命令。

注意，通过 ``tkz-graph`` 有多种选项可以影响 LaTeX 中图形的呈现方式，这超出了本节的范围。
请参阅参考手册 :ref:`sage.graphs.graph_latex` 章节获取指令和详细信息。


SageTeX
=======

SageTeX 是一个可以进一步集成 TeX 和 Sage 的程序。
它是一组 TeX 宏，允许 LaTeX 文档包含指令，让 Sage 计算各种对象并使用 ``latex()`` 格式化对象。
更多信息请参见 :ref:`sec-sagetex`。
