Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
a35983e
formatting OutputForm
mmatera Nov 10, 2024
3b5a2ba
Merge branch 'master' into 1d_OutputForm
mmatera Feb 11, 2025
b5fd7da
Merge branch 'master' into 1d_OutputForm
mmatera Sep 7, 2025
3932011
merge
mmatera Dec 23, 2025
b6d0de4
Merge branch 'master' into 1d_OutputForm
mmatera Dec 26, 2025
1388dd5
fix typo
mmatera Dec 26, 2025
89678aa
merge
mmatera Dec 26, 2025
777b418
add Pane and PaneBox
mmatera Dec 27, 2025
9bd5cad
improve Pane in mathml
mmatera Dec 27, 2025
d8b8bff
Merge remote-tracking branch 'origin/master' into Pane
mmatera Dec 27, 2025
088e657
improve compatibility in OutputForm
mmatera Dec 27, 2025
0e7a3a4
reduce trivial changes
mmatera Dec 27, 2025
c00f0dc
merge
mmatera Dec 28, 2025
4cd237b
Update mathics/eval/makeboxes/makeboxes.py
mmatera Dec 28, 2025
89f5063
Update mathics/eval/makeboxes/makeboxes.py
mmatera Dec 28, 2025
1c8a7f7
Merge branch 'master' into 1d_OutputForm
mmatera Dec 28, 2025
72eb41a
system symbols
mmatera Dec 28, 2025
b1ad184
Merge remote-tracking branch 'origin/master' into 1d_OutputForm
mmatera Dec 29, 2025
4810a6c
tests for MakeBoxes
mmatera Dec 30, 2025
794ca77
add tests for the structure
mmatera Dec 30, 2025
65a1656
another round.
mmatera Dec 30, 2025
8c2d721
Merge remote-tracking branch 'origin/master' into 1d_OutputForm
mmatera Dec 30, 2025
a4963b6
fix parametrize
mmatera Dec 30, 2025
fa6b828
Merge remote-tracking branch 'origin/master' into 1d_OutputForm
mmatera Dec 31, 2025
9232a85
Merge remote-tracking branch 'origin/master' into 1d_OutputForm
mmatera Dec 31, 2025
b3984f3
merge
mmatera Dec 31, 2025
8029135
Merge branch 'test_makeboxes' into 1d_OutputForm
mmatera Dec 31, 2025
38a766a
Merge remote-tracking branch 'origin/master' into 1d_OutputForm
mmatera Dec 31, 2025
8cbe6dd
Merge branch 'master' into test_makeboxes
mmatera Dec 31, 2025
e93512e
basic implementation for OutputForm grid
mmatera Dec 31, 2025
2948b44
fix typos
mmatera Dec 31, 2025
f4a8d60
more typos
mmatera Dec 31, 2025
b56e59a
move more tests to the yaml file
mmatera Jan 2, 2026
5018aef
merge
mmatera Jan 2, 2026
82555bc
merge
mmatera Jan 3, 2026
211f07a
merge
mmatera Jan 3, 2026
7b02dbc
Merge remote-tracking branch 'origin/master' into 1d_OutputForm
mmatera Jan 4, 2026
25454a0
remove default options in boxes
mmatera Jan 4, 2026
5627a81
adjust format renders
mmatera Jan 4, 2026
555588b
add options to InterpretationBox. Add quotes to PaneBox.
mmatera Jan 4, 2026
ec30ffb
Merge branch 'remove_default_options' into 1d_OutputForm
mmatera Jan 4, 2026
f30c754
Merge remote-tracking branch 'origin/master' into 1d_OutputForm
mmatera Jan 5, 2026
67459c1
Merge branch 'master' into 1d_OutputForm
mmatera Jan 5, 2026
5b51ed6
Merge remote-tracking branch 'origin/1d_OutputForm' into 1d_OutputForm
mmatera Jan 5, 2026
6f2ef5e
remove unused imports. lexicographic order functions in `mathics.form…
mmatera Jan 5, 2026
d0857fd
more on mathics.format.outputform
mmatera Jan 6, 2026
ae5533f
Fix evaluation of InterpretationBox with options
mmatera Jan 7, 2026
108731b
merge
mmatera Jan 7, 2026
bf17739
Misc tweaks... (#1599)
rocky Jan 7, 2026
7e401fb
merge
mmatera Jan 8, 2026
340a023
Merge branch 'master' into 1d_OutputForm
mmatera Jan 9, 2026
4046386
Merge remote-tracking branch 'origin/1d_OutputForm' into 1d_OutputForm
mmatera Jan 9, 2026
80160ac
restore
mmatera Jan 9, 2026
736bbc8
comment out a test until we finish fixing TeXForm in another round
mmatera Jan 9, 2026
fa243fe
merge reorganization of mathics.builtin.forms
mmatera Jan 9, 2026
e0d8ce3
comment out
mmatera Jan 9, 2026
c840a6a
mypy
mmatera Jan 9, 2026
5fded9f
isort
mmatera Jan 9, 2026
2480ce5
Merge branch 'master' into 1d_OutputForm
mmatera Jan 9, 2026
5bcb2bb
fix Image.atom_to_boxes
mmatera Jan 10, 2026
8846c13
fix ImageBox.boxes_to_*
mmatera Jan 10, 2026
c098a32
== bool -> is bool
mmatera Jan 10, 2026
b9fd972
DRY input/outputform
mmatera Jan 10, 2026
1e554eb
adjust dtype comparison
mmatera Jan 10, 2026
d4908ca
Merge branch 'Image_to_boxes_1' into 1d_OutputForm
mmatera Jan 10, 2026
83972c6
remove form parameter
mmatera Jan 10, 2026
dbd4173
and more
mmatera Jan 10, 2026
98613ab
more on OutputForm implemetation
mmatera Jan 11, 2026
4c31671
adding messages to StringForm
mmatera Jan 11, 2026
8a17fea
Merge remote-tracking branch 'origin/master' into 1d_OutputForm
mmatera Jan 11, 2026
47bb5d3
remove prints
mmatera Jan 11, 2026
48dcc98
Merge remote-tracking branch 'origin/master' into 1d_OutputForm
mmatera Jan 11, 2026
60cc2fa
range in baseform
mmatera Jan 11, 2026
2816f8e
bracket->square_bracket
mmatera Jan 11, 2026
cba0ba3
merge
mmatera Jan 11, 2026
3cb0831
more on tex
mmatera Jan 11, 2026
0cb34b3
adjust docstring in square_bracket. Add process_options for OutputFor…
mmatera Jan 11, 2026
3669274
improve StringForm implementation
mmatera Jan 11, 2026
5dde908
Merge branch 'StringForm' into 1d_OutputForm
mmatera Jan 11, 2026
1f0c833
adding tests. Handlind escaped backquotes.
mmatera Jan 12, 2026
2644dd1
Merge remote-tracking branch 'origin/master' into StringForm
mmatera Jan 12, 2026
7d635f9
another trailing dot
mmatera Jan 12, 2026
47be1d8
merge
mmatera Jan 12, 2026
379fd01
NumberForm refactor
mmatera Jan 13, 2026
d4e9e4a
Merge remote-tracking branch 'origin/master' into 1d_OutputForm
mmatera Jan 14, 2026
749ebdd
merge
mmatera Jan 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
520 changes: 363 additions & 157 deletions mathics/builtin/forms/data.py

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions mathics/builtin/forms/print.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,16 @@ class OutputForm(FormBaseClass):
= -Graphics-
"""

formats = {"OutputForm[s_String]": "s"}
summary_text = "format expression in plain text"

def eval_makeboxes(self, expr, form, evaluation):
"""MakeBoxes[OutputForm[expr_], form_]"""
pane = eval_makeboxes_outputform(expr, evaluation, form)
return InterpretationBox(
pane, Expression(SymbolOutputForm, expr), **{"System`Editable": SymbolFalse}
)


class StandardForm(FormBaseClass):
"""
Expand Down
25 changes: 6 additions & 19 deletions mathics/builtin/list/predicates.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,8 @@ class ContainsOnly(Builtin):

summary_text = "test if all the elements of a list appears into another list"

def check_options(self, expr, evaluation, options):
for key in options:
if key != "System`SameTest":
if expr is None:
evaluation.message("ContainsOnly", "optx", Symbol(key))
else:
evaluation.message("ContainsOnly", "optx", Symbol(key), expr)

return None

def eval(self, list1, list2, evaluation, options={}):
"ContainsOnly[list1_List, list2_List, OptionsPattern[ContainsOnly]]"
"ContainsOnly[list1_List, list2_List, OptionsPattern[]]"

same_test = self.get_option(options, "SameTest", evaluation)

Expand All @@ -71,31 +61,28 @@ def sameQ(a, b) -> bool:
result = Expression(same_test, a, b).evaluate(evaluation)
return result is SymbolTrue

self.check_options(None, evaluation, options)
for a in list1.elements:
if not any(sameQ(a, b) for b in list2.elements):
return SymbolFalse
return SymbolTrue

def eval_msg(self, e1, e2, evaluation, options={}):
"ContainsOnly[e1_, e2_, OptionsPattern[ContainsOnly]]"

def eval_msg(self, e1, e2, evaluation, expression, options={}):
"expression:(ContainsOnly[e1_, e2_, OptionsPattern[]])"
opts = (
options_to_rules(options)
if len(options) <= 1
else [ListExpression(*options_to_rules(options))]
)
expr = Expression(SymbolContainsOnly, e1, e2, *opts)

if not isinstance(e1, Symbol) and not e1.has_form("List", None):
evaluation.message("ContainsOnly", "lsa", e1)
return self.check_options(expr, evaluation, options)
return expression

if not isinstance(e2, Symbol) and not e2.has_form("List", None):
evaluation.message("ContainsOnly", "lsa", e2)
return self.check_options(expr, evaluation, options)
return expression

return self.check_options(expr, evaluation, options)
return expression


# TODO: ContainsAll, ContainsNone ContainsAny ContainsExactly
3 changes: 2 additions & 1 deletion mathics/builtin/makeboxes.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
format_element,
parenthesize,
)
from mathics.settings import SYSTEM_CHARACTER_ENCODING

# TODO: Differently from the current implementation, MakeBoxes should only
# accept as its format field the symbols in `$BoxForms`. This is something to
Expand Down Expand Up @@ -96,7 +97,7 @@ class MakeBoxes(Builtin):
'MakeBoxes[Infix[head[elements], StringForm["~`1`~", head]], f]'
),
"MakeBoxes[expr_]": "MakeBoxes[expr, StandardForm]",
"MakeBoxes[(form:StandardForm|TraditionalForm|OutputForm|TeXForm|"
"MakeBoxes[(form:StandardForm|TraditionalForm|TeXForm|"
"MathMLForm)[expr_], StandardForm|TraditionalForm]": ("MakeBoxes[expr, form]"),
"MakeBoxes[(form:StandardForm|OutputForm|MathMLForm|TeXForm)[expr_], OutputForm]": "MakeBoxes[expr, form]",
"MakeBoxes[PrecedenceForm[expr_, prec_], f_]": "MakeBoxes[expr, f]",
Expand Down
6 changes: 3 additions & 3 deletions mathics/builtin/numbers/calculus.py
Original file line number Diff line number Diff line change
Expand Up @@ -1410,9 +1410,9 @@ class NIntegrate(Builtin):
messages.update(
{
"bdmtd": "The Method option should be a "
+ "built-in method name in {`"
+ "`, `".join(list(methods))
+ "`}. Using `Automatic`"
+ r"built-in method name in {\`"
+ r"\`, \`".join(list(methods))
+ r"\`}. Using \`Automatic\`."
}
)

Expand Down
8 changes: 4 additions & 4 deletions mathics/core/atoms/numerics.py
Original file line number Diff line number Diff line change
Expand Up @@ -522,11 +522,11 @@ def is_machine_precision(self) -> bool:
return True

def make_boxes(self, form):
from mathics.eval.makeboxes import NumberForm_to_String
from mathics.eval.makeboxes import numberform_to_boxes

_number_form_options["_Form"] = form # passed to _NumberFormat
n = 6 if form == "System`OutputForm" else None
num_str = NumberForm_to_String(self, n, None, None, _number_form_options)
num_str = numberform_to_boxes(self, n, None, None, _number_form_options)
return num_str

@property
Expand Down Expand Up @@ -641,11 +641,11 @@ def is_zero(self) -> bool:
return self.value.is_zero or False

def make_boxes(self, form):
from mathics.eval.makeboxes import NumberForm_to_String
from mathics.eval.makeboxes import numberform_to_boxes

_number_form_options["_Form"] = form # passed to _NumberFormat
digits = dps(self.get_precision()) if form == "System`OutputForm" else None
return NumberForm_to_String(self, digits, None, None, _number_form_options)
return numberform_to_boxes(self, digits, None, None, _number_form_options)

def round(self, d: Optional[int] = None) -> Union[MachineReal, "PrecisionReal"]:
if d is None:
Expand Down
3 changes: 2 additions & 1 deletion mathics/core/parser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
MathicsMultiLineFeeder,
MathicsSingleLineFeeder,
)
from mathics.core.parser.operators import all_operator_names
from mathics.core.parser.operators import all_operator_names, operator_precedences
from mathics.core.parser.util import parse, parse_builtin_rule

__all__ = [
Expand All @@ -29,6 +29,7 @@
"MathicsSingleLineFeeder",
"all_operator_names",
"is_symbol_name",
"operator_precedences",
"parse",
"parse_builtin_rule",
]
3 changes: 3 additions & 0 deletions mathics/core/systemsymbols.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@
SymbolNIntegrate = Symbol("System`NIntegrate")
SymbolNValues = Symbol("System`NValues")
SymbolNeeds = Symbol("System`Needs")
SymbolNonAssociative = Symbol("System`NonAssociative")
SymbolNone = Symbol("System`None")
SymbolNorm = Symbol("System`Norm")
SymbolNormal = Symbol("System`Normal")
Expand Down Expand Up @@ -235,9 +236,11 @@
SymbolPlus = Symbol("System`Plus")
SymbolPoint = Symbol("System`Point")
SymbolPolygon = Symbol("System`Polygon")
SymbolPostfix = Symbol("System`Postfix")
SymbolPossibleZeroQ = Symbol("System`PossibleZeroQ")
SymbolPower = Symbol("System`Power")
SymbolPrecision = Symbol("System`Precision")
SymbolPrefix = Symbol("System`Prefix")
SymbolPreserveImageOptions = Symbol("System`PreserveImageOptions")
SymbolProlog = Symbol("System`Prolog")
SymbolQuantity = Symbol("System`Quantity")
Expand Down
12 changes: 7 additions & 5 deletions mathics/doc/documentation/1-Manual.mdoc
Original file line number Diff line number Diff line change
Expand Up @@ -901,9 +901,11 @@ This will even apply to 'TeXForm', because 'TeXForm' implies 'StandardForm':
>> b // TeXForm
= c

Except some other form is applied first:
>> b // OutputForm // TeXForm
= b
## This test requires another round of changes in order to
## pass:
## Except some other form is applied first:
## >> b // OutputForm // TeXForm
## = \text{b}
'MakeBoxes' for another form:

>> MakeBoxes[b, TeXForm] = "d";
Expand Down Expand Up @@ -934,12 +936,12 @@ For instance, you can override 'MakeBoxes' to format lists in a different way:
>> {1, 2, 3}
= {1, 2, 3}

#> {1, 2, 3} // TeXForm
>> {1, 2, 3} // TeXForm
= \left[1 2 3\right]

However, this will not be accepted as input to \Mathics anymore:
>> [1 2 3]
: Expression cannot begin with "[1 2 3]" (line 1 of "<test-Formatting Output-28>").
: Expression cannot begin with "[1 2 3]" (line 1 of "<test-Formatting Output-27>").

>> Clear[MakeBoxes]

Expand Down
11 changes: 9 additions & 2 deletions mathics/eval/makeboxes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@
eval_generic_makeboxes,
eval_makeboxes,
eval_makeboxes_fullform,
eval_makeboxes_outputform,
format_element,
int_to_string_shorter_repr,
to_boxes,
)
from mathics.eval.makeboxes.numberform import NumberForm_to_String, eval_baseform
from mathics.eval.makeboxes.numberform import (
eval_baseform,
get_numberform_parameters,
numberform_to_boxes,
)
from mathics.eval.makeboxes.operators import eval_infix, eval_postprefix
from mathics.eval.makeboxes.outputforms import (
eval_mathmlform,
Expand All @@ -26,7 +31,7 @@
)

__all__ = [
"NumberForm_to_String",
"numberform_to_boxes",
"StringLParen",
"StringRParen",
"_boxed_string",
Expand All @@ -38,11 +43,13 @@
"eval_infix",
"eval_makeboxes",
"eval_makeboxes_fullform",
"eval_makeboxes_outputform",
"eval_mathmlform",
"eval_postprefix",
"eval_tableform",
"eval_texform",
"format_element",
"get_numberform_parameters",
"int_to_string_shorter_repr",
"parenthesize",
"render_input_form",
Expand Down
39 changes: 39 additions & 0 deletions mathics/eval/makeboxes/makeboxes.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,20 @@ def int_to_string_shorter_repr(value: int, form: Symbol, max_digits=640):
return String(value_str)


def eval_makeboxes_outputform(expr, evaluation, form, **kwargs):
"""
Build a 2D representation of the expression using only keyboard characters.
"""
from mathics.builtin.box.layout import PaneBox
from mathics.form.outputform import expression_to_outputform_text

text_outputform = str(
expression_to_outputform_text(expr, evaluation, form, **kwargs)
)
elem1 = PaneBox(String('"' + text_outputform + '"'))
return elem1


# TODO: evaluation is needed because `atom_to_boxes` uses it. Can we remove this
# argument?
def eval_makeboxes_fullform(
Expand Down Expand Up @@ -271,10 +285,35 @@ def format_element(
"""
Applies formats associated to the expression, and then calls Makeboxes
"""
# Halt any potential evaluation tracing while performing boxing.
evaluation.is_boxing = True
while element.get_head() is form:
element = element.elements[0]

# By now, eval_makeboxes_outputform is only used when we explicitly
# ask for MakeBoxes[OutputForm[expr], fmt]
# When it get ready, we can uncomment this.
# if form is SymbolOutputForm:
# return eval_makeboxes_outputform(element, evaluation, form, **kwargs)

if element.has_form("FullForm", 1):
return eval_makeboxes_fullform(element.elements[0], evaluation)

# In order to work like in WMA, `format_element`
# should evaluate `MakeBoxes[element//form, StandardForm]`
# Then, MakeBoxes[expr_, StandardForm], for any expr,
# should apply Format[...] rules, and then
# MakeBoxes[...] rules. These rules should be stored
# as FormatValues[...]
# As a first step in that direction, let's mimic this behaviour
# just for the case of OutputForm:
if element.has_form("OutputForm", 1):
return eval_makeboxes_outputform(element.elements[0], evaluation, form)

formatted_expr = do_format(element, evaluation, form)
if formatted_expr is None:
return None

result_box = eval_makeboxes(formatted_expr, evaluation, form)
if isinstance(result_box, String):
return result_box
Expand Down
Loading
Loading