diff --git a/mathics/format/box/formatvalues.py b/mathics/format/box/formatvalues.py index a52521bd0..262679cc4 100644 --- a/mathics/format/box/formatvalues.py +++ b/mathics/format/box/formatvalues.py @@ -25,7 +25,19 @@ SymbolPlus, SymbolTimes, ) -from mathics.core.systemsymbols import SymbolInputForm, SymbolMinus, SymbolOutputForm +from mathics.core.systemsymbols import ( + SymbolInfix, + SymbolInputForm, + SymbolMinus, + SymbolOutputForm, + SymbolPostfix, + SymbolPrefix, +) + +# Operator forms that display only the elements of their first argument, +# not the argument itself: in Format[f[x__]] := Infix[f[x], "~"], f[x] must +# not be formatted again. +OPERATOR_FORMS = (SymbolInfix, SymbolPostfix, SymbolPrefix) # These Strings are used in Boxing output StringElipsis = String("...") @@ -134,12 +146,25 @@ def format_expr(expr): and isinstance(expr, Expression) and head not in (SymbolGraphics, SymbolGraphics3D) ): + + def format_element(element): + return _element_formatters.get(type(element), do_format_element)( + element, evaluation, form + ) + new_elements = tuple( ( - _element_formatters.get(type(element), do_format_element)( - element, evaluation, form + ( + to_expression_with_specialization( + element.head, + *(format_element(e) for e in element.elements), + ) + if index == 0 + and head in OPERATOR_FORMS + and isinstance(element, Expression) + else format_element(element) ) - for element in expr.elements + for index, element in enumerate(expr.elements) ) ) expr_head = expr.head diff --git a/test/format/test_format.py b/test/format/test_format.py index 1d4e05b22..335f6eea5 100644 --- a/test/format/test_format.py +++ b/test/format/test_format.py @@ -268,6 +268,33 @@ def test_format_private_doctests(str_expr, str_expected, msg): None, ), ("r[1]", None, "ab", None), + # Infix, Prefix and Postfix display the elements of their first + # argument, so a format may wrap the expression it formats. + ( + 'Format[pInfix[t__]] := Infix[pInfix[t], "~"]; pInfix[a, b]', + (), + "a ~ b", + "Infix of the formatted expression itself", + ), + ("pInfix[a, pInfix[b, c]] + 1", (), "1 + a ~ b ~ c", "Nested, inside Plus"), + ( + 'Format[pLeft[t__]] := Infix[pLeft[t], "~", 300, Left]; pLeft[pLeft[a, b], c]', + (), + "a ~ b ~ c", + "With precedence and grouping", + ), + ( + 'Format[pPre[x_]] := Prefix[pPre[x], "!"]; pPre[a]', + (), + "!a", + "Prefix of the formatted expression itself", + ), + ( + 'Format[pPost[x_]] := Postfix[pPost[x], "!!"]; pPost[a]', + (), + "a!!", + "Postfix of the formatted expression itself", + ), (None, None, None, None), ], )