From 5dd691a8d98a7085dfacc852360a728ed2d0f6b8 Mon Sep 17 00:00:00 2001 From: rocky Date: Thu, 5 Feb 2026 08:41:23 -0500 Subject: [PATCH 1/2] Revise render/latex.py for box attributes --- mathics/format/render/latex.py | 59 ++++++++++++++-------------------- 1 file changed, 25 insertions(+), 34 deletions(-) diff --git a/mathics/format/render/latex.py b/mathics/format/render/latex.py index 329f987fa..fbdeb6a99 100644 --- a/mathics/format/render/latex.py +++ b/mathics/format/render/latex.py @@ -284,12 +284,10 @@ def pane_box(box: PaneBox, **options): def fractionbox(box: FractionBox, **options) -> str: - _options = box.box_options.copy() - _options.update(options) - options = _options + child_options = {**options, **box.box_options} return "\\frac{%s}{%s}" % ( - lookup_conversion_method(box.num, "latex")(box.num, **options), - lookup_conversion_method(box.den, "latex")(box.den, **options), + lookup_conversion_method(box.num, "latex")(box.num, **child_options), + lookup_conversion_method(box.den, "latex")(box.den, **child_options), ) @@ -341,16 +339,15 @@ def boxes_to_tex(box, **options): def sqrtbox(box: SqrtBox, **options): - _options = box.box_options.copy() - _options.update(options) - options = _options + # Note: values set in `options` take precedence over `box_options` + child_options = {**options, **box.box_options} if box.index: return "\\sqrt[%s]{%s}" % ( lookup_conversion_method(box.radicand, "latex")(box.radicand, **options), lookup_conversion_method(box.index, "latex")(box.index, **options), ) return "\\sqrt{%s}" % lookup_conversion_method(box.radicand, "latex")( - box.radicand, **options + box.radicand, **child_options ) @@ -358,9 +355,7 @@ def sqrtbox(box: SqrtBox, **options): def superscriptbox(box: SuperscriptBox, **options): - _options = box.box_options.copy() - _options.update(options) - options = _options + child_options = {**options, **box.box_options} base_to_tex = lookup_conversion_method(box.base, "latex") tex1 = base_to_tex(box.base, **options) @@ -372,7 +367,7 @@ def superscriptbox(box: SuperscriptBox, **options): return "%s''" % tex1 base = box.tex_block(tex1, True) superidx_to_tex = lookup_conversion_method(box.superindex, "latex") - superindx = box.tex_block(superidx_to_tex(box.superindex, **options), True) + superindx = box.tex_block(superidx_to_tex(box.superindex, **child_options), True) if len(superindx) == 1 and isinstance(box.superindex, (String, StyleBox)): return "%s^%s" % ( base, @@ -388,14 +383,13 @@ def superscriptbox(box: SuperscriptBox, **options): def subscriptbox(box: SubscriptBox, **options): - _options = box.box_options.copy() - _options.update(options) - options = _options + # Note: values set in `options` take precedence over `box_options` + child_options = {**options, **box.box_options} base_to_tex = lookup_conversion_method(box.base, "latex") subidx_to_tex = lookup_conversion_method(box.subindex, "latex") return "%s_%s" % ( - box.tex_block(base_to_tex(box.base, **options), True), - box.tex_block(subidx_to_tex(box.subindex, **options)), + box.tex_block(base_to_tex(box.base, **child_options), True), + box.tex_block(subidx_to_tex(box.subindex, **child_options)), ) @@ -403,17 +397,16 @@ def subscriptbox(box: SubscriptBox, **options): def subsuperscriptbox(box: SubsuperscriptBox, **options): - _options = box.box_options.copy() - _options.update(options) - options = _options + # Note: values set in `options` take precedence over `box_options` + child_options = {**box.box_options, **options} base_to_tex = lookup_conversion_method(box.base, "latex") subidx_to_tex = lookup_conversion_method(box.subindex, "latex") superidx_to_tex = lookup_conversion_method(box.superindex, "latex") return "%s_%s^%s" % ( - box.tex_block(base_to_tex(box.base, **options), True), - box.tex_block(subidx_to_tex(box.subindex, **options)), - box.tex_block(superidx_to_tex(box.superindex, **options)), + box.tex_block(base_to_tex(box.base, **child_options), True), + box.tex_block(subidx_to_tex(box.subindex, **child_options)), + box.tex_block(superidx_to_tex(box.superindex, **child_options)), ) @@ -469,9 +462,8 @@ def rowbox_parenthesized(items, **options): def rowbox(box: RowBox, **options) -> str: - _options = box.box_options.copy() - _options.update(options) - options = _options + # Note: values set in `options` take precedence over `box_options` + child_options = {**box.box_options, **options} items = box.items # Handle special cases if len(items) >= 3: @@ -479,23 +471,22 @@ def rowbox(box: RowBox, **options) -> str: 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) + head_latex = lookup_conversion_method(head, "latex")(head, **child_options) return head_latex + rest_latex if len(items) >= 2: - parenthesized_latex = rowbox_parenthesized(items, **options) + parenthesized_latex = rowbox_parenthesized(items, **child_options) if parenthesized_latex is not None: return parenthesized_latex - return rowbox_sequence(items, **options) + return rowbox_sequence(items, **child_options) add_conversion_fn(RowBox, rowbox) def stylebox(box: StyleBox, **options) -> str: - _options = box.box_options.copy() - _options.update(options) - options = _options - return lookup_conversion_method(box.boxes, "latex")(box.boxes, **options) + # Note: values set in `options` take precedence over `box_options` + child_options = {**box.box_options, **options} + return lookup_conversion_method(box.boxes, "latex")(box.boxes, **child_options) add_conversion_fn(StyleBox, stylebox) From e99f676ec3d84890b47267732d0d0e7b522aaad8 Mon Sep 17 00:00:00 2001 From: rocky Date: Thu, 5 Feb 2026 09:17:46 -0500 Subject: [PATCH 2/2] Revise plain text rendering for box attributes --- mathics/format/render/latex.py | 1 + mathics/format/render/text.py | 123 ++++++++++++++++----------------- 2 files changed, 60 insertions(+), 64 deletions(-) diff --git a/mathics/format/render/latex.py b/mathics/format/render/latex.py index fbdeb6a99..c71dda479 100644 --- a/mathics/format/render/latex.py +++ b/mathics/format/render/latex.py @@ -284,6 +284,7 @@ def pane_box(box: PaneBox, **options): def fractionbox(box: FractionBox, **options) -> str: + # Note: values set in `options` take precedence over `box_options` child_options = {**options, **box.box_options} return "\\frac{%s}{%s}" % ( lookup_conversion_method(box.num, "latex")(box.num, **child_options), diff --git a/mathics/format/render/text.py b/mathics/format/render/text.py index a62f201cb..fa83a2b86 100644 --- a/mathics/format/render/text.py +++ b/mathics/format/render/text.py @@ -4,6 +4,7 @@ """ +from mathics.builtin.box.expression import BoxExpression from mathics.builtin.box.graphics import GraphicsBox from mathics.builtin.box.graphics3d import Graphics3DBox from mathics.builtin.box.layout import ( @@ -22,7 +23,10 @@ ) from mathics.core.atoms import String from mathics.core.exceptions import BoxConstructError -from mathics.core.formatter import add_conversion_fn, lookup_method +from mathics.core.formatter import ( + add_conversion_fn, + lookup_method as lookup_conversion_method, +) from mathics.core.symbols import Atom, SymbolTrue from mathics.format.box.graphics import prepare_elements as prepare_elements2d from mathics.format.box.graphics3d import prepare_elements as prepare_elements3d @@ -30,7 +34,7 @@ def boxes_to_text(boxes, **options) -> str: - return lookup_method(boxes, "text")(boxes, **options) + return lookup_conversion_method(boxes, "text")(boxes, **options) def string(s: String, **options) -> str: @@ -47,30 +51,28 @@ def string(s: String, **options) -> str: add_conversion_fn(String, string) -def interpretation_box(self, **options): - return boxes_to_text(self.boxes, **options) +def interpretation_box(box: InterpretationBox, **options): + return boxes_to_text(box.boxes, **options) add_conversion_fn(InterpretationBox, interpretation_box) -def pane_box(self, **options): - result = boxes_to_text(self.boxes, **options) - return result +def pane_box(box: PaneBox, **options): + return boxes_to_text(box.boxes, **options) add_conversion_fn(PaneBox, pane_box) -def fractionbox(self, **options) -> str: - _options = self.box_options.copy() - _options.update(options) - options = _options - num_text = boxes_to_text(self.num, **options) - den_text = boxes_to_text(self.den, **options) - if isinstance(self.num, RowBox): +def fractionbox(box: FractionBox, **options) -> str: + # Note: values set in `options` take precedence over `box_options` + child_options = {**options, **box.box_options} + num_text = boxes_to_text(box.num, **child_options) + den_text = boxes_to_text(box.den, **child_options) + if isinstance(box.num, RowBox): num_text = f"({num_text})" - if isinstance(self.den, RowBox): + if isinstance(box.den, RowBox): den_text = f"({den_text})" return " / ".join([num_text, den_text]) @@ -79,13 +81,13 @@ def fractionbox(self, **options) -> str: add_conversion_fn(FractionBox, fractionbox) -def gridbox(self, elements=None, **box_options) -> str: +def gridbox(box: GridBox, elements=None, **box_options) -> str: if not elements: - elements = self.items + elements = box.items evaluation = box_options.get("evaluation", None) - items, options = self.get_array(elements, evaluation) + items, options = box.get_array(elements, evaluation) - box_options.update(self.options) + box_options.update(box.options) if not items: return "" @@ -112,27 +114,25 @@ def gridbox(self, elements=None, **box_options) -> str: add_conversion_fn(GridBox, gridbox) -def sqrtbox(self, **options) -> str: - _options = self.box_options.copy() - _options.update(options) - options = _options - if self.index: +def sqrtbox(box: SqrtBox, **options) -> str: + # Note: values set in `options` take precedence over `box_options` + child_options = {**options, **box.box_options} + if box.index: return "Sqrt[%s,%s]" % ( - boxes_to_text(self.radicand, **options), - boxes_to_text(self.index, **options), + boxes_to_text(box.radicand, **child_options), + boxes_to_text(box.index, **child_options), ) - return "Sqrt[%s]" % (boxes_to_text(self.radicand, **options)) + return "Sqrt[%s]" % (boxes_to_text(box.radicand, **child_options)) add_conversion_fn(SqrtBox, sqrtbox) -def superscriptbox(self, **options) -> str: - _options = self.box_options.copy() - _options.update(options) - options = _options +def superscriptbox(box: SuperscriptBox, **options) -> str: + # Note: values set in `options` take precedence over `box_options` + child_options = {**options, **box.box_options} no_parenthesize = True - index = self.superindex + index = box.superindex while not isinstance(index, Atom): if isinstance(index, StyleBox): index = index.boxes @@ -143,46 +143,43 @@ def superscriptbox(self, **options) -> str: fmt_str = "%s^%s" if no_parenthesize else "%s^(%s)" return fmt_str % ( - boxes_to_text(self.base, **options), - boxes_to_text(self.superindex, **options), + boxes_to_text(box.base, **child_options), + boxes_to_text(box.superindex, **child_options), ) add_conversion_fn(SuperscriptBox, superscriptbox) -def subscriptbox(self, **options) -> str: - _options = self.box_options.copy() - _options.update(options) - options = _options +def subscriptbox(box: SubscriptBox, **options) -> str: + # Note: values set in `options` take precedence over `box_options` + child_options = {**box.box_options, **options} return "Subscript[%s, %s]" % ( - boxes_to_text(self.base, **options), - boxes_to_text(self.subindex, **options), + boxes_to_text(box.base, **child_options), + boxes_to_text(box.subindex, **child_options), ) add_conversion_fn(SubscriptBox, subscriptbox) -def subsuperscriptbox(self, **options) -> str: - _options = self.box_options.copy() - _options.update(options) - options = _options +def subsuperscriptbox(box: SubsuperscriptBox, **options) -> str: + # Note: values set in `options` take precedence over `box_options` + child_options = {**box.box_options, **options} return "Subsuperscript[%s, %s, %s]" % ( - boxes_to_text(self.base, **options), - boxes_to_text(self.subindex, **options), - boxes_to_text(self.superindex, **options), + boxes_to_text(box.base, **child_options), + boxes_to_text(box.subindex, **child_options), + boxes_to_text(box.superindex, **child_options), ) add_conversion_fn(SubsuperscriptBox, subsuperscriptbox) -def rowbox(self, elements=None, **options) -> str: - _options = self.box_options.copy() - _options.update(options) - options = _options - parts_str = [boxes_to_text(element, **options) for element in self.items] +def rowbox(box: RowBox, elements=None, **options) -> str: + # Note: values set in `options` take precedence over `box_options` + child_options = {**box.box_options, **options} + parts_str = [boxes_to_text(element, **child_options) for element in box.items] if len(parts_str) == 0: return "" if len(parts_str) == 1: @@ -209,39 +206,37 @@ def rowbox(self, elements=None, **options) -> str: add_conversion_fn(RowBox, rowbox) -def stylebox(self, **options) -> str: - options.pop("evaluation", None) - _options = self.box_options.copy() - _options.update(options) - options = _options - return boxes_to_text(self.boxes, **options) +def stylebox(box: StyleBox, **options) -> str: + # Note: values set in `options` take precedence over `box_options` + child_options = {**box.box_options, **options} + return boxes_to_text(box.boxes, **child_options) add_conversion_fn(StyleBox, stylebox) -def graphicsbox(self, elements=None, **options) -> str: +def graphicsbox(box: GraphicsBox, elements=None, **options) -> str: assert elements is None - prepare_elements2d(self, self.content, options) # to test for Box errors + prepare_elements2d(box, box.content, options) # to test for Box errors return "-Graphics-" add_conversion_fn(GraphicsBox, graphicsbox) -def graphics3dbox(self, elements=None, **options) -> str: +def graphics3dbox(box: Graphics3DBox, elements=None, **options) -> str: assert elements is None - prepare_elements3d(self, self.content, options) # to test for Box errors + prepare_elements3d(box, box.content, options) # to test for Box errors return "-Graphics3D-" add_conversion_fn(Graphics3DBox, graphics3dbox) -def tag_and_form_box(self, **options): - return boxes_to_text(self.boxes, **options) +def tag_and_form_box(box: BoxExpression, **options): + return boxes_to_text(box.boxes, **options) add_conversion_fn(FormBox, tag_and_form_box)