diff --git a/SYMBOLS_MANIFEST.txt b/SYMBOLS_MANIFEST.txt index 35e37ac65..f4e4c96dc 100644 --- a/SYMBOLS_MANIFEST.txt +++ b/SYMBOLS_MANIFEST.txt @@ -12,6 +12,7 @@ ImportExport`RegisterExport ImportExport`RegisterImport Internal`RealValuedNumberQ Internal`RealValuedNumericQ +JSON`Import`JSONImport System`$Aborted System`$Assumptions System`$BaseDirectory @@ -486,6 +487,7 @@ System`FoldList System`FontColor System`For System`Format +System`FormatType System`FormatValues System`FractionBox System`FractionalPart diff --git a/mathics/builtin/atomic/symbols.py b/mathics/builtin/atomic/symbols.py index a9253138b..5af79bb99 100644 --- a/mathics/builtin/atomic/symbols.py +++ b/mathics/builtin/atomic/symbols.py @@ -407,12 +407,21 @@ class FormatValues(Builtin): :WMA link:https://reference.wolfram.com/language/tutorial/PatternsAndTransformationRules.html#6025
'FormatValues'[$symbol$] -
gives the list of formatvalues associated with $symbol$. +
gives the list of format rules associated with $symbol$.
+ First, use 'Format' to set a formatting rule for a form: + >> Format[F[x_], OutputForm]:= Subscript[x, F] + + Now, to see the rules, we can use 'FormatValues': + >> FormatValues[F] - = {HoldPattern[Format[Subscript[x_, F], OutputForm]] :> Subscript[x, F]} + = {HoldPattern[Subscript[x_, F]] :> Subscript[x, F]} + + The replacment pattern on the right in the delayed rule is formatted according to the top-level form. To see the rule input, we can use 'InputForm': + >> FormatValues[F] //InputForm + = {HoldPattern[Format[F[x_], OutputForm]] :> Subscript[x, F]} """ summary_text = ( diff --git a/mathics/builtin/layout.py b/mathics/builtin/layout.py index eb9884e32..8ce757748 100644 --- a/mathics/builtin/layout.py +++ b/mathics/builtin/layout.py @@ -46,12 +46,15 @@ class Format(Builtin):
'Format'[$expr$] -
holds values specifying how $expr$ should be printed. +
used on the left-hand side of an assignment to specify how $expr$ should be printed.
- Assign values to 'Format' to control how particular expressions - should be formatted when printed to the user. + First, we set up a 'Format' definition for 'f' to display its arguments as if it were equivalent to an infix operator "~": + >> Format[f[x___]] := Infix[{x}, "~"] + + Now, to see this format in use: + >> f[1, 2, 3] = 1 ~ 2 ~ 3 >> f[1] @@ -68,12 +71,57 @@ class Format(Builtin): Formats must be attached to the head of an expression: >> f /: Format[g[f]] = "my f"; : Tag f not found or too deep for an assigned rule. + + Format can be used to specify the request format: + >> Format[Integrate[F[x], x], TeXForm] + = \\int F\\left(x\\right) \\, dx + + Format evaluates its first element before applying the format: + >> Format[Integrate[Cos[x], x], TeXForm] + = ... + but the result keeps the structure: + >> % //FullForm + = Format[Sin[x], TeXForm] + + If the second parameter is omitted, 'Format' is ignored: + >> Format[F[x]] + = F[x] + + If the second argument is not one of '$PrintForms', a message \ + is shown, and the argument is discarded: + >> Format[F[x], NoFormat] + : Value of option FormatType -> NoFormat is not valid. + = F[x] + + Mathics3 'Format' output can differ slightly from WMA in what we hope \ + is a more useful way. + + Use 'InputForm' if you want to get a 'Format' definition that can be used as \ + Mathics3 input: + + >> Format[{a->Integrate[F[x], x]}, StandardForm] //InputForm + = Format[{a -> Integrate[F[x], x]}, StandardForm] + + In WMA, you might not get something that can be used as input. + + Similarly, use 'Fullform' to get a valid FullForm equivalent expression: + + >> Format[{a->Integrate[F[x], x]}, StandardForm] //FullForm + = Format[{Rule[a, Integrate[F[x], x]]}, StandardForm] """ messages = {"fttp": "Format type `1` is not a symbol."} summary_text = ( "settable low-level translator from various forms to evaluatable expressions" ) + rules = {"MakeBoxes[Format[expr_], fmt_]": "MakeBoxes[expr, fmt]"} + + def eval_Makeboxes(self, expr, form, evaluation): + """MakeBoxes[Format[expr_, form_], _]""" + if form not in evaluation.definitions.printforms: + evaluation.message("FormatType", "ftype", form) + return format_element(expr, evaluation) + return format_element(expr, evaluation, form) class Grid(Builtin): diff --git a/mathics/builtin/options.py b/mathics/builtin/options.py index 4e650bfbd..34fc0eeb8 100644 --- a/mathics/builtin/options.py +++ b/mathics/builtin/options.py @@ -171,6 +171,20 @@ def matched(): return ListExpression(*list(matched())) +class FormatType(Predefined): + """ + :WMA link:https://reference.wolfram.com/language/ref/FormatType.html +
+
'FormatType' +
is an option for output streams, graphics and functions like 'Text' \ + that specifies the default format. +
+ """ + + messages = {"ftype": "Value of option FormatType -> `` is not valid."} + summary_text = "specify the request format" + + class None_(Predefined): """ :WMA link:https://reference.wolfram.com/language/ref/None.html diff --git a/mathics/format/form/outputform.py b/mathics/format/form/outputform.py index 4d4afce4f..002b04fbf 100644 --- a/mathics/format/form/outputform.py +++ b/mathics/format/form/outputform.py @@ -264,6 +264,21 @@ def render_output_form(expr: BaseElement, evaluation: Evaluation, **kwargs): return _default_render_output_form(format_expr, evaluation, **kwargs) +@register_outputform("System`Format") +def format_format(expr, evaluation, **kwargs): + """Format[expr_, form___]""" + elements = expr.elements + if len(elements) == 1: + return render_output_form(elements[0], evaluation, **kwargs) + if len(elements) == 2: + expr, form = elements + if form not in evaluation.definitions.printforms: + evaluation.message("FormatType", "ftype", form) + return render_output_form(expr, evaluation, **kwargs) + return other_forms(Expression(form, expr), evaluation, **kwargs) + raise _WrongFormattedExpression + + @register_outputform("System`Graphics") def graphics(expr: Expression, evaluation: Evaluation, **kwargs) -> str: if not isinstance(expr.head, Symbol):