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):