From 562bcafdc50d3366300ad71c301ed43682e87479 Mon Sep 17 00:00:00 2001
From: mmatera <matera@fisica.unlp.edu.ar>
Date: Thu, 10 Nov 2022 14:26:22 -0300
Subject: [PATCH 1/5] basic implementation of DisplayForm

---
 CHANGES.rst                  |  4 +++-
 mathics/builtin/makeboxes.py | 45 ++++++++++++++++++++++++++++++++++++
 mathics/core/evaluation.py   |  3 +++
 3 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/CHANGES.rst b/CHANGES.rst
index 836d64e9d..c7428cde4 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -15,6 +15,7 @@ New Builtins
 #. ``Accuracy``
 #. ``ClebschGordan``
 #. ``Curl`` (2-D and 3-D vector forms only)
+#. ``DisplayForm``
 #. ``Kurtosis``
 #. ``PauliMatrix``
 #. ``Remove``
@@ -57,7 +58,8 @@ Enhancements
 #. Better handling of comparisons with finite precision numbers.
 #. Improved implementation for  ``Precision``.
 #. Infix operators, like ``->`` render with their Unicode symbol when ``$CharacterEncoding`` is not "ASCII".
-
+#. Basic implementation of ``DisplayForm``
+   
 5.0.2
 -----
 
diff --git a/mathics/builtin/makeboxes.py b/mathics/builtin/makeboxes.py
index bc8ec6bbc..27c533d52 100644
--- a/mathics/builtin/makeboxes.py
+++ b/mathics/builtin/makeboxes.py
@@ -325,6 +325,47 @@ class BoxForms_(Predefined):
     summary_text = "the list of box formats"
 
 
+class DisplayForm(Builtin):
+    """
+    <dl>
+      <dt>'DisplayForm[$obj$]'
+      <dd>is a form that shows low-level box structures as the correspoding
+      print form.
+    </dl>
+
+    By default, box structures are shown without a format:
+    >> box = MakeBoxes[Infix[{a, b}," + "], StandardForm]
+     = RowBox[{a,  + , b}]
+    Wrapping the box structure in a $DisplayForm$ ensures to render the expression:
+    >> DisplayForm[box]
+     = a + b
+
+    The same is valid if the box is nested into an expression:
+    >> DisplayForm[F[box]]
+     = F[a + b]
+
+    If the argument does not have a box structure,  `DisplayForm` is ignored:
+    >> DisplayForm[a + b]
+     = a + b
+
+    """
+
+    def apply_makeboxes(self, expr, f, evaluation):
+        """MakeBoxes[DisplayForm[expr_], f_]"""
+
+        # This is a paratemer needed to remember if
+        # MakeBoxes is formatting an expression inside a DisplayForm.
+        # Hopefully, this is temporal and it is not going to be
+        # needed after the Format/MakeBoxes refactor.
+        evaluation.in_display_form = True
+        try:
+            result = MakeBoxes(expr, f).evaluate(evaluation)
+        except:
+            pass
+        evaluation.in_display_form = False
+        return result
+
+
 class MakeBoxes(Builtin):
     """
     <dl>
@@ -394,6 +435,10 @@ def apply_general(self, expr, f, evaluation):
         """MakeBoxes[expr_,
         f:TraditionalForm|StandardForm|OutputForm|InputForm|FullForm]"""
         if isinstance(expr, BoxElementMixin):
+            # If we are inside a DisplayForm block,
+            # BoxElementMixin are not processed.
+            if evaluation.in_display_form:
+                return expr
             expr = expr.to_expression()
         if isinstance(expr, Atom):
             return expr.atom_to_boxes(f, evaluation)
diff --git a/mathics/core/evaluation.py b/mathics/core/evaluation.py
index 3c1dfa174..5576d2f77 100644
--- a/mathics/core/evaluation.py
+++ b/mathics/core/evaluation.py
@@ -256,6 +256,9 @@ def __init__(
 
         self.quiet_all = False
         self.format = format
+
+        # See comment in mathics.builtin.makeboxes.DisplayForm
+        self.in_display_form = False
         self.catch_interrupt = catch_interrupt
         self.SymbolNull = SymbolNull
 

From 44b3efe18922f30da5bba324e46f03d17606c782 Mon Sep 17 00:00:00 2001
From: mmatera <matera@fisica.unlp.edu.ar>
Date: Thu, 10 Nov 2022 14:32:51 -0300
Subject: [PATCH 2/5] adding summary_text. Moving to mathics.builtin.forms

---
 mathics/builtin/forms/output.py | 44 +++++++++++++++++++++++++++++++++
 mathics/builtin/makeboxes.py    | 41 ------------------------------
 2 files changed, 44 insertions(+), 41 deletions(-)

diff --git a/mathics/builtin/forms/output.py b/mathics/builtin/forms/output.py
index b516e0b06..c71b73d80 100644
--- a/mathics/builtin/forms/output.py
+++ b/mathics/builtin/forms/output.py
@@ -149,6 +149,50 @@ def apply_makeboxes(self, expr, n, f, evaluation):
             )
 
 
+class DisplayForm(FormBaseClass):
+    """
+    <dl>
+      <dt>'DisplayForm[$obj$]'
+      <dd>is a form that shows low-level box structures as the correspoding
+      print form.
+    </dl>
+
+    By default, box structures are shown without a format:
+    >> box = MakeBoxes[Infix[{a, b}," + "], StandardForm]
+     = RowBox[{a,  + , b}]
+    Wrapping the box structure in a $DisplayForm$ ensures to render the expression:
+    >> DisplayForm[box]
+     = a + b
+
+    The same is valid if the box is nested into an expression:
+    >> DisplayForm[F[box]]
+     = F[a + b]
+
+    If the argument does not have a box structure,  `DisplayForm` is ignored:
+    >> DisplayForm[a + b]
+     = a + b
+
+    """
+
+    in_outputforms = True
+    summary_text = "render low-level box structures"
+
+    def apply_makeboxes(self, expr, f, evaluation):
+        """MakeBoxes[DisplayForm[expr_], f_]"""
+
+        # This is a paratemer needed to remember if
+        # MakeBoxes is formatting an expression inside a DisplayForm.
+        # Hopefully, this is temporal and it is not going to be
+        # needed after the Format/MakeBoxes refactor.
+        evaluation.in_display_form = True
+        try:
+            result = MakeBoxes(expr, f).evaluate(evaluation)
+        except:
+            pass
+        evaluation.in_display_form = False
+        return result
+
+
 class FullForm(FormBaseClass):
     """
     <url>
diff --git a/mathics/builtin/makeboxes.py b/mathics/builtin/makeboxes.py
index 27c533d52..84d504c1a 100644
--- a/mathics/builtin/makeboxes.py
+++ b/mathics/builtin/makeboxes.py
@@ -325,47 +325,6 @@ class BoxForms_(Predefined):
     summary_text = "the list of box formats"
 
 
-class DisplayForm(Builtin):
-    """
-    <dl>
-      <dt>'DisplayForm[$obj$]'
-      <dd>is a form that shows low-level box structures as the correspoding
-      print form.
-    </dl>
-
-    By default, box structures are shown without a format:
-    >> box = MakeBoxes[Infix[{a, b}," + "], StandardForm]
-     = RowBox[{a,  + , b}]
-    Wrapping the box structure in a $DisplayForm$ ensures to render the expression:
-    >> DisplayForm[box]
-     = a + b
-
-    The same is valid if the box is nested into an expression:
-    >> DisplayForm[F[box]]
-     = F[a + b]
-
-    If the argument does not have a box structure,  `DisplayForm` is ignored:
-    >> DisplayForm[a + b]
-     = a + b
-
-    """
-
-    def apply_makeboxes(self, expr, f, evaluation):
-        """MakeBoxes[DisplayForm[expr_], f_]"""
-
-        # This is a paratemer needed to remember if
-        # MakeBoxes is formatting an expression inside a DisplayForm.
-        # Hopefully, this is temporal and it is not going to be
-        # needed after the Format/MakeBoxes refactor.
-        evaluation.in_display_form = True
-        try:
-            result = MakeBoxes(expr, f).evaluate(evaluation)
-        except:
-            pass
-        evaluation.in_display_form = False
-        return result
-
-
 class MakeBoxes(Builtin):
     """
     <dl>

From 7aedfc1448d28dc86ea1d9969a2b7690970800aa Mon Sep 17 00:00:00 2001
From: mmatera <matera@fisica.unlp.edu.ar>
Date: Thu, 10 Nov 2022 22:41:08 -0300
Subject: [PATCH 3/5] add URL. Fix typo. Fix Manifest

---
 SYMBOLS_MANIFEST.txt            | 1 +
 mathics/builtin/forms/output.py | 6 +++++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/SYMBOLS_MANIFEST.txt b/SYMBOLS_MANIFEST.txt
index 7a9a64774..9c3987010 100644
--- a/SYMBOLS_MANIFEST.txt
+++ b/SYMBOLS_MANIFEST.txt
@@ -316,6 +316,7 @@ System`Disk
 System`DiskBox
 System`DiskMatrix
 System`Dispatch
+System`DisplayForm
 System`Divide
 System`DivideBy
 System`Divisible
diff --git a/mathics/builtin/forms/output.py b/mathics/builtin/forms/output.py
index c71b73d80..666f29b1f 100644
--- a/mathics/builtin/forms/output.py
+++ b/mathics/builtin/forms/output.py
@@ -151,9 +151,13 @@ def apply_makeboxes(self, expr, n, f, evaluation):
 
 class DisplayForm(FormBaseClass):
     """
+    <url>
+      :WMA link:
+      https://reference.wolfram.com/language/ref/DisplayForm.html</url>
+
     <dl>
       <dt>'DisplayForm[$obj$]'
-      <dd>is a form that shows low-level box structures as the correspoding
+      <dd>is a form that shows low-level box structures as the corresponding\
       print form.
     </dl>
 

From 371a4c3768936af2892ac1fbab088491b068ae98 Mon Sep 17 00:00:00 2001
From: mmatera <matera@fisica.unlp.edu.ar>
Date: Thu, 10 Nov 2022 22:44:50 -0300
Subject: [PATCH 4/5] support nested displayform

---
 mathics/builtin/forms/output.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mathics/builtin/forms/output.py b/mathics/builtin/forms/output.py
index 666f29b1f..cedcfa275 100644
--- a/mathics/builtin/forms/output.py
+++ b/mathics/builtin/forms/output.py
@@ -188,12 +188,12 @@ def apply_makeboxes(self, expr, f, evaluation):
         # MakeBoxes is formatting an expression inside a DisplayForm.
         # Hopefully, this is temporal and it is not going to be
         # needed after the Format/MakeBoxes refactor.
-        evaluation.in_display_form = True
+        previous_df, evaluation.in_display_form = evaluation.in_display_form, True
         try:
             result = MakeBoxes(expr, f).evaluate(evaluation)
         except:
             pass
-        evaluation.in_display_form = False
+        evaluation.in_display_form = previous_df
         return result
 
 

From 3aea3456fc167d82fc0533ea851164d4a1bdb3c2 Mon Sep 17 00:00:00 2001
From: mmatera <matera@fisica.unlp.edu.ar>
Date: Sun, 13 Nov 2022 12:43:21 -0300
Subject: [PATCH 5/5] apply -> eval

---
 mathics/builtin/forms/output.py | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/mathics/builtin/forms/output.py b/mathics/builtin/forms/output.py
index cedcfa275..bdbb28f8e 100644
--- a/mathics/builtin/forms/output.py
+++ b/mathics/builtin/forms/output.py
@@ -115,7 +115,7 @@ class BaseForm(Builtin):
         "basf": "Requested base `1` must be between 2 and 36.",
     }
 
-    def apply_makeboxes(self, expr, n, f, evaluation):
+    def eval_makeboxes(self, expr, n, f, evaluation):
         """MakeBoxes[BaseForm[expr_, n_],
         f:StandardForm|TraditionalForm|OutputForm]"""
 
@@ -181,7 +181,7 @@ class DisplayForm(FormBaseClass):
     in_outputforms = True
     summary_text = "render low-level box structures"
 
-    def apply_makeboxes(self, expr, f, evaluation):
+    def eval_makeboxes(self, expr, f, evaluation):
         """MakeBoxes[DisplayForm[expr_], f_]"""
 
         # This is a paratemer needed to remember if
@@ -692,7 +692,7 @@ def default_NumberFormat(man, base, exp, options):
         else:
             return man
 
-    def apply_list_n(self, expr, n, evaluation, options) -> Expression:
+    def eval_list_n(self, expr, n, evaluation, options) -> Expression:
         "NumberForm[expr_List, n_, OptionsPattern[NumberForm]]"
         options = [
             Expression(SymbolRuleDelayed, Symbol(key), value)
@@ -705,7 +705,7 @@ def apply_list_n(self, expr, n, evaluation, options) -> Expression:
             ]
         )
 
-    def apply_list_nf(self, expr, n, f, evaluation, options) -> Expression:
+    def eval_list_nf(self, expr, n, f, evaluation, options) -> Expression:
         "NumberForm[expr_List, {n_, f_}, OptionsPattern[NumberForm]]"
         options = [
             Expression(SymbolRuleDelayed, Symbol(key), value)
@@ -718,7 +718,7 @@ def apply_list_nf(self, expr, n, f, evaluation, options) -> Expression:
             ],
         )
 
-    def apply_makeboxes(self, expr, form, evaluation, options={}):
+    def eval_makeboxes(self, expr, form, evaluation, options={}):
         """MakeBoxes[NumberForm[expr_, OptionsPattern[NumberForm]],
         form:StandardForm|TraditionalForm|OutputForm]"""
 
@@ -743,7 +743,7 @@ def apply_makeboxes(self, expr, form, evaluation, options={}):
             return number_form(expr, py_n, None, evaluation, py_options)
         return Expression(SymbolMakeBoxes, expr, form)
 
-    def apply_makeboxes_n(self, expr, n, form, evaluation, options={}):
+    def eval_makeboxes_n(self, expr, n, form, evaluation, options={}):
         """MakeBoxes[NumberForm[expr_, n_?NotOptionQ, OptionsPattern[NumberForm]],
         form:StandardForm|TraditionalForm|OutputForm]"""
 
@@ -763,7 +763,7 @@ def apply_makeboxes_n(self, expr, n, form, evaluation, options={}):
             return number_form(expr, py_n, None, evaluation, py_options)
         return Expression(SymbolMakeBoxes, expr, form)
 
-    def apply_makeboxes_nf(self, expr, n, f, form, evaluation, options={}):
+    def eval_makeboxes_nf(self, expr, n, f, form, evaluation, options={}):
         """MakeBoxes[NumberForm[expr_, {n_, f_}, OptionsPattern[NumberForm]],
         form:StandardForm|TraditionalForm|OutputForm]"""