Skip to content

Commit 4a25494

Browse files
committed
Lots of little fixes...
General things -------------- Allow 2D rendering from asymptote. This is useful in debugging asymptote problems sometimess seen in the LaTeX document. Eliminate: ``` Set::setraw: Cannot assign to raw object colorful. ``` message on startup. Propagate non-meaning operators from MathicsScanner. More specifically ----------------- __main__.py: * add --{no-,}matplotlib and {no-,asymptote} options * DRY setting Settings`* asymptote.py: * Redo so that each image is in a temporary file. This is simpler and easier to debug. settings.m: * Remove setting any value that is set in the command line inputrc-no-unicode: Add all no-meaning operators. This is derived from changes in MathicsScanner format.py: Revise so that we can use asymptote for 2D graphs termshell.py: Don't try to set PygmentsStyle this way, this doesn't work and gives Set::setraw: Cannot assign to raw object colorful. due to a preexisting rewrite rule. PygmentsStyle is set in other places
1 parent 3657a35 commit 4a25494

File tree

7 files changed

+110
-68
lines changed

7 files changed

+110
-68
lines changed

mathicsscript/__main__.py

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,12 @@ def out(self, out):
140140

141141

142142
def interactive_eval_loop(
143-
shell: TerminalShellCommon, unicode, prompt, strict_wl_output: bool
143+
shell: TerminalShellCommon,
144+
unicode,
145+
prompt,
146+
matplotlib: bool,
147+
asymptote: bool,
148+
strict_wl_output: bool,
144149
):
145150
def identity(x: Any) -> Any:
146151
return x
@@ -337,6 +342,25 @@ def fmt_fun(query: Any) -> Any:
337342
help=("Most WL-output compatible (at the expense of usability)."),
338343
required=False,
339344
)
345+
@click.option(
346+
"--asymptote/--no-asymptote",
347+
default=True,
348+
show_default=True,
349+
help=(
350+
"Use asymptote for 2D and 3D Graphics; "
351+
"you need a working asymptote for this option."
352+
),
353+
)
354+
@click.option(
355+
"--matplotlib/--no-matplotlib",
356+
default=True,
357+
show_default=True,
358+
help=(
359+
"Use matplotlib for 2D Graphics; "
360+
"you need a working matplotlib for this option. "
361+
"If set, this will take precedence over asymptote for 2D Graphics."
362+
),
363+
)
340364
@click.argument("file", nargs=1, type=click.Path(readable=True), required=False)
341365
def main(
342366
full_form,
@@ -353,6 +377,8 @@ def main(
353377
style,
354378
pygments_tokens,
355379
strict_wl_output,
380+
asymptote,
381+
matplotlib,
356382
file,
357383
) -> int:
358384
"""A command-line interface to Mathics.
@@ -372,12 +398,14 @@ def main(
372398
# Set a default value for $ShowFullFormInput to False.
373399
# Then, it can be changed by the settings file (in WL)
374400
# and overwritten by the command line parameter.
375-
definitions.set_ownvalue(
376-
"Settings`$ShowFullFormInput", from_python(True if full_form else False)
377-
)
378-
definitions.set_ownvalue(
379-
"Settings`$PygmentsShowTokens", from_python(True if pygments_tokens else False)
380-
)
401+
for setting_name, setting_value in (
402+
("$ShowFullFormInput", full_form),
403+
("$UseAsymptote", asymptote),
404+
("$UseMatplotlib", matplotlib),
405+
):
406+
definitions.set_ownvalue(
407+
f"Settings`{setting_name}", from_python(True if setting_value else False)
408+
)
381409

382410
if post_mortem:
383411
try:
@@ -475,9 +503,6 @@ def main(
475503
"Settings`$ShowFullFormInput", SymbolTrue if full_form else SymbolFalse
476504
)
477505

478-
definitions.set_ownvalue(
479-
"Settings`$PygmentsStyle", from_python(shell.pygments_style)
480-
)
481506
definitions.set_ownvalue(
482507
"Settings`$PygmentsShowTokens", from_python(pygments_tokens)
483508
)
@@ -490,7 +515,9 @@ def main(
490515
)
491516

492517
definitions.set_line_no(0)
493-
interactive_eval_loop(shell, unicode, prompt, strict_wl_output)
518+
interactive_eval_loop(
519+
shell, unicode, prompt, asymptote, matplotlib, strict_wl_output
520+
)
494521
return exit_rc
495522

496523

mathicsscript/asymptote.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
import mathics
77
import os
88
import os.path as osp
9+
import subprocess
910

1011
from subprocess import Popen, PIPE, run
12+
from tempfile import NamedTemporaryFile
1113
from typing import Optional
1214

1315
asy_program = os.environ.get("ASY_PROG", "asy")
@@ -95,6 +97,16 @@ def __del__(self):
9597
self.session.wait()
9698

9799

100+
def write_asy_and_view(asy_string: str):
101+
# TODO: add option to let user decide whether or not to delete
102+
# image afterwards.
103+
with NamedTemporaryFile(
104+
mode="w", prefix="Mathics3-Graph-", suffix=".asy", delete=False
105+
) as asy_fp:
106+
asy_fp.write(asy_string + "\n")
107+
subprocess.run(args=[asy_program, "-View", asy_fp.name])
108+
109+
98110
if __name__ == "__main__":
99111
g = Asy()
100112
g.size(200)

mathicsscript/autoload/settings.m

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
(* -*- wolfram -*- *)
12
(**********************************************************************)
23
(* *)
34
(* Settings for mathicsscript *)
45
(* *)
5-
(* *)
6+
(* Values that can be set from the command line should not have a *)
7+
(* default value set here, just the "usage" value. *)
68
(* *)
79
(**********************************************************************)
810

@@ -24,11 +26,11 @@
2426
Settings`$UseUnicode::usage = "This Boolean variable sets whether Unicode is used in terminal input and output."
2527
Settings`$UseUnicode = True
2628

27-
Settings`$UseAsymptote::usage = "This Boolean variable sets whether 3D Graphics should render using Asymptote."
28-
Settings`$UseAsymptote = True
29+
Settings`$UseAsymptote::usage = "This Boolean variable sets whether 2D and 3D Graphics should render using Asymptote."
30+
Settings`$UseMatplotlib::usage = "This Boolean variable sets whether 2D Graphics should render using Matplotlib.
2931
30-
Settings`$UseMatplotlib::usage = "This Boolean variable sets whether 2D Graphics should render using Matplotlib."
31-
Settings`$UseMatplotlib = True
32+
If set, and $UseAsymptote is also set, matplotlib will take precedence for 2D graphics.
33+
"
3234

3335
Settings`MathicsScriptVersion::usage = "This string is the version of MathicsScript we are running."
3436

mathicsscript/data/inputrc-no-unicode

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
# GNU Readline input unicode translations
2-
# Autogenerated from mathics_scanner.generate.rl_inputrc on Wed Oct 26 04:49:35 PM EDT 2022
3-
41
"\ea'\e": "á"
52
"\ea-\e": "ā"
63
"\eau\e": "ă"
@@ -504,9 +501,11 @@
504501
"\e<--\e": "⟵"
505502
"\e<-->\e": "⟷"
506503
"\e-->\e": "⟶"
504+
"\eMlim\e": "\\[MaxLimit]"
507505
"\emath\e": "\\[MathematicaIcon]"
508506
"\emho\e": "℧"
509507
"\emi\e": "µ"
508+
"\emlim\e": "lim"
510509
"\e-+\e": "∓"
511510
"\em\e": "μ"
512511
"\env\e": "ň"

mathicsscript/format.py

Lines changed: 48 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
except ImportError:
4848
svg2png = None
4949

50-
from mathicsscript.asymptote import Asy
50+
from mathicsscript.asymptote import Asy, write_asy_and_view
5151

5252
have_asymptote = False
5353
try:
@@ -92,6 +92,7 @@ def eval_boxes(result, fn: Callable, obj, **options):
9292

9393
expr_type = expr.get_head_name()
9494
expr_head = expr.get_head()
95+
9596
if expr_head is SymbolMathMLForm:
9697
format = "xml"
9798
elements = expr.elements
@@ -102,57 +103,62 @@ def eval_boxes(result, fn: Callable, obj, **options):
102103
elements = expr.elements
103104
if len(elements) == 1:
104105
expr = elements[0]
105-
elif expr_head is SymbolImage:
106-
if get_settings_value(obj.definitions, "Settings`$UseMatplotlib") and plt:
107-
temp_png = NamedTemporaryFile(
108-
mode="w+b", suffix=".png", prefix="mathicsscript-"
106+
elif (
107+
expr_head is SymbolImage
108+
and get_settings_value(obj.definitions, "Settings`$UseMatplotlib")
109+
and plt
110+
):
111+
temp_png = NamedTemporaryFile(
112+
mode="w+b", suffix=".png", prefix="mathicsscript-"
113+
)
114+
try:
115+
png_expr = Expression(
116+
SymbolExport, String(temp_png.name), expr, String("PNG")
109117
)
110-
try:
111-
png_expr = Expression(
112-
SymbolExport, String(temp_png.name), expr, String("PNG")
113-
)
114-
result = png_expr.evaluate(obj)
115-
plt.axes().set_axis_off()
116-
img = mpimg.imread(temp_png)
117-
cmap = "gray" if expr.color_space == "Grayscale" else None
118-
plt.imshow(img, cmap=cmap)
119-
plt.show()
120-
except: # noqa
121-
pass
122-
temp_png.close()
123-
118+
result = png_expr.evaluate(obj)
119+
plt.axes().set_axis_off()
120+
img = mpimg.imread(temp_png)
121+
cmap = "gray" if expr.color_space == "Grayscale" else None
122+
plt.imshow(img, cmap=cmap)
123+
plt.show()
124+
except: # noqa
124125
pass
126+
temp_png.close()
125127

126-
elif expr_head in (SymbolGraphics, SymbolPlot):
127-
if (
128-
get_settings_value(obj.definitions, "Settings`$UseMatplotlib")
129-
and plt
130-
and svg2png
131-
):
132-
svg_expr = Expression(SymbolExportString, expr, String("SVG"))
133-
svg_str = svg_expr.evaluate(obj).to_python(string_quotes=False)
134-
temp_png = NamedTemporaryFile(
135-
mode="w+b", suffix=".png", prefix="mathicsscript-"
136-
)
137-
try:
138-
svg2png(bytestring=svg_str, write_to=temp_png.name)
139-
plt.axes().set_axis_off()
140-
img = mpimg.imread(temp_png)
141-
plt.imshow(img)
142-
plt.show()
143-
temp_png.close()
144-
except: # noqa
145-
pass
128+
elif (
129+
expr_head in (SymbolGraphics, SymbolPlot)
130+
and get_settings_value(obj.definitions, "Settings`$UseMatplotlib")
131+
and plt
132+
and svg2png
133+
):
134+
svg_expr = Expression(SymbolExportString, expr, String("SVG"))
135+
svg_str = svg_expr.evaluate(obj).to_python(string_quotes=False)
136+
temp_png = NamedTemporaryFile(
137+
mode="w+b", suffix=".png", prefix="mathicsscript-"
138+
)
139+
try:
140+
svg2png(bytestring=svg_str, write_to=temp_png.name)
141+
plt.axes().set_axis_off()
142+
img = mpimg.imread(temp_png)
143+
plt.imshow(img)
144+
plt.show()
145+
temp_png.close()
146+
except: # noqa
147+
pass
146148
return expr_type
147149
elif (
148-
expr_head in (SymbolGraphics3D,)
150+
expr_head in (SymbolGraphics, SymbolPlot, SymbolGraphics3D)
149151
and have_asymptote
150152
and get_settings_value(obj.definitions, "Settings`$UseAsymptote")
151153
):
152154
asy_expr = Expression(SymbolExportString, expr, String("asy"))
153155
asy_str = asy_expr.evaluate(obj).to_python(string_quotes=False)
154-
asymptote_graph.erase()
155-
asymptote_graph.send(asy_str)
156+
157+
# Alternate older version
158+
# asymptote_graph.erase()
159+
# asymptote_graph.send(asy_str)
160+
161+
write_asy_and_view(asy_str)
156162
return expr_type
157163

158164
if format == "text":

mathicsscript/termshell.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -*- coding: utf-8 -*-
2-
# Copyright (C) 2020-2022 Rocky Bernstein <[email protected]>
2+
# Copyright (C) 2020-2022, 2024 Rocky Bernstein <[email protected]>
33

44
from columnize import columnize
55

@@ -115,18 +115,13 @@ def __init__(
115115
try:
116116
self.terminal_formatter = Terminal256Formatter(style=style)
117117
except ClassNotFound:
118-
print(
119-
"Pygments style name '%s' not found; No pygments style set" % style
120-
)
118+
print(f"Pygments style name '{style}' not found; No pygments style set")
121119

122120
self.pygments_style = style
123121
self.definitions = definitions
124122
set_settings_value(
125123
self.definitions, "Settings`$PygmentsShowTokens", from_python(False)
126124
)
127-
set_settings_value(
128-
self.definitions, "Settings`$PygmentsStyle", from_python(style)
129-
)
130125
set_settings_value(
131126
self.definitions, "Settings`$UseUnicode", from_python(use_unicode)
132127
)

mathicsscript/user-settings.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
(* -*- wolfram -*- *)
12
(***********************************************************)
23
(* User settings config for mathicsscript *)
34
(* Customize this with Mathics definitions as desired. *)

0 commit comments

Comments
 (0)