diff --git a/mathics/builtin/atomic/strings.py b/mathics/builtin/atomic/strings.py index 2c2326e7a..ad4c42fc0 100644 --- a/mathics/builtin/atomic/strings.py +++ b/mathics/builtin/atomic/strings.py @@ -876,7 +876,7 @@ class ToString(Builtin): >> "U" <> ToString[2] = U2 >> ToString[Integrate[f[x],x], TeXForm] - = \\int f\\left(x\\right) \\, dx + = \\int f(x) \\, dx """ diff --git a/mathics/builtin/layout.py b/mathics/builtin/layout.py index 8ce757748..6caa1170f 100644 --- a/mathics/builtin/layout.py +++ b/mathics/builtin/layout.py @@ -74,7 +74,7 @@ class Format(Builtin): Format can be used to specify the request format: >> Format[Integrate[F[x], x], TeXForm] - = \\int F\\left(x\\right) \\, dx + = \\int F(x) \\, dx Format evaluates its first element before applying the format: >> Format[Integrate[Cos[x], x], TeXForm] diff --git a/mathics/builtin/list/associations.py b/mathics/builtin/list/associations.py index 2bd46eea3..72282cbe6 100644 --- a/mathics/builtin/list/associations.py +++ b/mathics/builtin/list/associations.py @@ -40,8 +40,8 @@ class Association(Builtin): >> <|a -> x, b -> y|> = <|a -> x, b -> y|> - >> Association[{a -> x, b -> y}] - = <|a -> x, b -> y|> + >> Association[{a -> x^2, b -> y}] + = <|a -> x ^ 2, b -> y|> Associations can be nested: >> <|a -> x, b -> y, <|a -> z, d -> t|>|> diff --git a/mathics/builtin/numbers/calculus.py b/mathics/builtin/numbers/calculus.py index 06ccebe54..79afa04fc 100644 --- a/mathics/builtin/numbers/calculus.py +++ b/mathics/builtin/numbers/calculus.py @@ -1007,8 +1007,8 @@ class Integrate(SympyFunction): = Integrate[1, {x, Infinity, 0}] Here how is an example of converting integral equation to TeX: - >> Integrate[f[x], {x, a, b}] // TeXForm - = \int_a^b f\left(x\right) \, dx + >> Integrate[f[x^2], {x, a, b}] // TeXForm + = \int_a^b f\left(x^2\right) \, dx Sometimes there is a loss of precision during integration. You can check the precision of your result with the following sequence \ diff --git a/mathics/doc/documentation/1-Manual.mdoc b/mathics/doc/documentation/1-Manual.mdoc index 433a65c38..80e6cde1f 100644 --- a/mathics/doc/documentation/1-Manual.mdoc +++ b/mathics/doc/documentation/1-Manual.mdoc @@ -942,7 +942,7 @@ For instance, you can override 'MakeBoxes' to format lists in a different way: = {1, 2, 3} >> {1, 2, 3} // TeXForm - = \left[1 2 3\right] + = [1 2 3] However, this will not be accepted as input to \Mathics anymore: >> [1 2 3] @@ -970,7 +970,7 @@ The desired effect can be achieved in the following way: = squared[1, 2] #> squared[1, 2] // TeXForm - = \text{squared}\left[1, 2\right]^2 + = \text{squared}[1, 2]^2 You can view the box structure of a formatted expression using 'ToBoxes': @@ -1115,7 +1115,7 @@ Three-dimensional plots are supported as well: Here are some examples written by Jan Pöschko that come from the very first version.
-Let\'s sketch the function +Let's sketch the function >> f[x_] := 4 x / (x ^ 2 + 3 x + 5) The derivatives are: diff --git a/mathics/docpipeline.py b/mathics/docpipeline.py index 6200150e4..403f3372f 100644 --- a/mathics/docpipeline.py +++ b/mathics/docpipeline.py @@ -274,7 +274,7 @@ def create_output(test_pipeline, tests): if output_format in ("latex", "xml"): def out_wrapper(expr): - return f"{expr} // StandardForm" + return f"StandardForm[{expr}]" else: diff --git a/mathics/format/render/latex.py b/mathics/format/render/latex.py index 797b82cef..d92585b03 100644 --- a/mathics/format/render/latex.py +++ b/mathics/format/render/latex.py @@ -50,6 +50,71 @@ # mathics_scanner does not generates this table in a way that we can load it here. # When it get fixed, we can use that table instead of this one: +BRACKET_INFO = { + ( + String("("), + String(")"), + ): { + "latex_open": "(", + "latex_closing": ")", + "latex_open_large": r"\left(", + "latex_closing_large": r"\right)", + }, + ( + String("{"), + String("}"), + ): { + "latex_open": r"\{", + "latex_closing": r"\}", + "latex_open_large": r"\left\{", + "latex_closing_large": r"\right\}", + }, + ( + String("["), + String("]"), + ): { + "latex_open": "[", + "latex_closing": "]", + "latex_open_large": r"\left[", + "latex_closing_large": r"\right]", + }, + ( + String("\u301A"), + String("\u301B"), + ): { + "latex_open": r"[[", + "latex_closing": "]]", + "latex_open_large": r"\left[\left[", + "latex_closing_large": r"\right]\right]", + }, + ( + String("\u2329"), + String("\u232A"), + ): { + "latex_open": "\\langle", + "latex_closing": "\\rangle", + "latex_open_large": r"\left\langle ", + "latex_closing_large": r"\right\rangle ", + }, + ( + String("\u2016"), + String("\u2016"), + ): { + "latex_open": r"\|", + "latex_closing": r"\|", + "latex_open_large": r"\left\|", + "latex_closing_large": r"\right\| ", + }, + ( + String("<|"), + String("|>"), + ): { + "latex_open": r"\langle\vert ", + "latex_closing": r"\vert\rangle ", + "latex_open_large": r"\left\langle\left\vert ", + "latex_closing_large": r"\right\vert\right\rangle ", + }, +} TEX_REPLACE = { "{": r"\{", @@ -347,14 +412,13 @@ def subsuperscriptbox(self, **options): add_conversion_fn(SubsuperscriptBox, subsuperscriptbox) -def rowbox(self, **options) -> str: - _options = self.box_options.copy() - _options.update(options) - options = _options +def rowbox_sequence(items, **options): parts_str = [ lookup_conversion_method(element, "latex")(element, **options) - for element in self.items + for element in items ] + if len(parts_str) == 0: + return "" if len(parts_str) == 1: return parts_str[0] # This loop integrate all the row adding spaces after a ",", followed @@ -376,6 +440,46 @@ def rowbox(self, **options) -> str: return result +def rowbox_parenthesized(items, **options): + if len(items) < 2: + return None + key = ( + items[0], + items[-1], + ) + items = items[1:-1] + try: + bracket_data = BRACKET_INFO[key] + except KeyError: + return None + + contain = rowbox_sequence(items, **options) if len(items) > 0 else "" + + if any(item.is_multiline for item in items): + return f'{bracket_data["latex_open_large"]}{contain}{bracket_data["latex_closing_large"]}' + return f'{bracket_data["latex_open"]}{contain}{bracket_data["latex_closing"]}' + + +def rowbox(self, **options) -> str: + _options = self.box_options.copy() + _options.update(options) + options = _options + items = self.items + # Handle special cases + if len(items) >= 3: + head, *rest = items + rest_latex = rowbox_parenthesized(rest, **options) + if rest_latex is not None: + # Must be a function-like expression f[] + head_latex = lookup_conversion_method(head, "latex")(head, **options) + return head_latex + rest_latex + if len(items) >= 2: + parenthesized_latex = rowbox_parenthesized(items, **options) + if parenthesized_latex is not None: + return parenthesized_latex + return rowbox_sequence(items, **options) + + add_conversion_fn(RowBox, rowbox) diff --git a/test/doc/test_latex.py b/test/doc/test_latex.py index d96d9b6bb..307a5d573 100644 --- a/test/doc/test_latex.py +++ b/test/doc/test_latex.py @@ -83,8 +83,8 @@ def test_load_latex_documentation(): r"\begin{testresult}o\end{testresult}\end{testcase}" ) assert ( - doc_in_section.latex(doc_data)[:40] - ).strip() == "Let\\'s sketch the function\n\\begin{tests}" + doc_in_section.latex(doc_data)[:39] + ).strip() == "Let's sketch the function\n\\begin{tests}" assert ( first_section.latex(doc_data)[:30] ).strip() == "\\section{Curve Sketching}{}" diff --git a/test/format/format_tests.yaml b/test/format/format_tests.yaml index 3a7ad203c..14d511606 100644 --- a/test/format/format_tests.yaml +++ b/test/format/format_tests.yaml @@ -288,8 +288,8 @@ latex: System`InputForm: '\text{$<$$\vert$a -$>$ x, b -$>$ y, c -$>$ $<$$\vert$d -$>$ t$\vert$$>$$\vert$$>$}' System`OutputForm: '\text{$<$$\vert$a -$>$ x, b -$>$ y, c -$>$ $<$$\vert$d -$>$ t$\vert$$>$$\vert$$>$}' - System`StandardForm: '\text{$<$$\vert$}a->x, b->y, c->\text{$<$$\vert$}d->t\text{$\vert$$>$}\text{$\vert$$>$}' - System`TraditionalForm: '\text{$<$$\vert$}a->x, b->y, c->\text{$<$$\vert$}d->t\text{$\vert$$>$}\text{$\vert$$>$}' + System`StandardForm: '\langle\vert a->x, b->y, c->\langle\vert d->t\vert\rangle \vert\rangle' + System`TraditionalForm: '\langle\vert a->x, b->y, c->\langle\vert d->t\vert\rangle \vert\rangle' mathml: System`InputForm: <|a -> x, b -> y, c -> <|d -> t|>|> System`OutputForm: '<|a -> x, b -> y, c -> <|d -> t|>|>' @@ -313,8 +313,8 @@ Association[a -> x, b -> y, c -> Association[d -> t, Association[e -> u]]]: latex: System`InputForm: '\text{$<$$\vert$a -$>$ x, b -$>$ y, c -$>$ $<$$\vert$d -$>$ t, e -$>$ u$\vert$$>$$\vert$$>$}' System`OutputForm: '\text{$<$$\vert$a -$>$ x, b -$>$ y, c -$>$ $<$$\vert$d -$>$ t, e -$>$ u$\vert$$>$$\vert$$>$}' - System`StandardForm: '\text{$<$$\vert$}a->x, b->y, c->\text{$<$$\vert$}d->t, e->u\text{$\vert$$>$}\text{$\vert$$>$}' - System`TraditionalForm: '\text{$<$$\vert$}a->x, b->y, c->\text{$<$$\vert$}d->t, e->u\text{$\vert$$>$}\text{$\vert$$>$}' + System`StandardForm: '\langle\vert a->x, b->y, c->\langle\vert d->t, e->u\vert\rangle \vert\rangle' + System`TraditionalForm: '\langle\vert a->x, b->y, c->\langle\vert d->t, e->u\vert\rangle \vert\rangle' mathml: System`InputForm: <|a -> x, b -> y, c -> <|d -> t, e -> u|>|> System`OutputForm: '<|a -> x, b -> y, c -> <|d -> t, e -> u|>|>' @@ -556,8 +556,8 @@ Integrate[F[x], {x, a, g[b]}]: latex: System`InputForm: \text{Integrate[F[x], \{x, a, g[b]\}]} System`OutputForm: '\text{Integrate[F[x], \{x, a, g[b]\}]}' - System`StandardForm: \int_a^{g\left[b\right]} F\left[x\right] \, dx - System`TraditionalForm: \int_a^{g\left(b\right)} F\left(x\right) \, dx + System`StandardForm: \int_a^{g[b]} F[x] \, dx + System`TraditionalForm: \int_a^{g(b)} F(x) \, dx mathml: System`InputForm: Integrate[F[x], {x, a, g[b]}] System`OutputForm: 'Integrate[F[x], {x, a, g[b]}]' @@ -840,8 +840,8 @@ a^(g[b]/c): latex: System`InputForm: \text{a${}^{\wedge}$(g[b]/c)} System`OutputForm: '\text{a ${}^{\wedge}$ (g[b] / c)}' - System`StandardForm: a^{\frac{g\left[b\right]}{c}} - System`TraditionalForm: a^{\frac{g\left(b\right)}{c}} + System`StandardForm: a^{\frac{g[b]}{c}} + System`TraditionalForm: a^{\frac{g(b)}{c}} mathml: System`InputForm: a^(g[b]/c) System`OutputForm: 'a ^ (g[b] / c)' @@ -905,7 +905,7 @@ a+PrecedenceForm[b+c,10]: msg: "PrecedenceForm" latex: System`OutputForm: '\text{a + (b + c)}' - System`StandardForm: 'a+\left(b+c\right)' + System`StandardForm: 'a+(b+c)' mathml: System`OutputForm: 'a + (b + c)' System`StandardForm: 'a + ( b + c )' diff --git a/test/format/test_latex.py b/test/format/test_latex.py index 374fad126..c50fb1c29 100644 --- a/test/format/test_latex.py +++ b/test/format/test_latex.py @@ -26,9 +26,9 @@ def get_latex(wl_expression): ('"_"', r"\text{\_}"), ('"["', r"\text{[}"), ('"]"', r"\text{]}"), - ("HoldForm[A[[1,2]]]", r"A\left[\left[1, 2\right]\right]"), + ("HoldForm[A[[1,2]]]", r"A[[1, 2]]"), ('"wrong ]"', r"\text{wrong ]}"), - ("Integrate[F[x],x]", r"\int F\left[x\right] \, dx"), + ("Integrate[F[x],x]", r"\int F[x] \, dx"), ("Cap[c,b]", r"c \cap b"), ("CupCap[c,b]", r"c \stackrel{\smile}{\frown} b"), ("Congruent[c,b]", r"c \equiv b"),