Skip to content

Commit

Permalink
Lots of little fixes...
Browse files Browse the repository at this point in the history
General things
--------------

Allow 2D rendering from asymptote. This is useful in debugging asymptote
problem such as seen in the LaTeX doc.

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 settin Settings`*

asymptote.py:
* Redo so that each image is its own 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 aymptote 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 other places
  • Loading branch information
rocky committed Dec 16, 2024
1 parent 3657a35 commit ba3b412
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 68 deletions.
49 changes: 38 additions & 11 deletions mathicsscript/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,12 @@ def out(self, out):


def interactive_eval_loop(
shell: TerminalShellCommon, unicode, prompt, strict_wl_output: bool
shell: TerminalShellCommon,
unicode,
prompt,
matplotlib: bool,
asymptote: bool,
strict_wl_output: bool,
):
def identity(x: Any) -> Any:
return x
Expand Down Expand Up @@ -337,6 +342,25 @@ def fmt_fun(query: Any) -> Any:
help=("Most WL-output compatible (at the expense of usability)."),
required=False,
)
@click.option(
"--asymptote/--no-asymptote",
default=True,
show_default=True,
help=(
"Use asymptote for 2D and 3D Graphics; "
"you need a working asymptote for this option."
),
)
@click.option(
"--matplotlib/--no-matplotlib",
default=True,
show_default=True,
help=(
"Use matplotlib for 2D Graphics; "
"you need a working matplotlib for this option. "
"If set, this will take precedence over asymptote for 2D Graphics."
),
)
@click.argument("file", nargs=1, type=click.Path(readable=True), required=False)
def main(
full_form,
Expand All @@ -353,6 +377,8 @@ def main(
style,
pygments_tokens,
strict_wl_output,
asymptote,
matplotlib,
file,
) -> int:
"""A command-line interface to Mathics.
Expand All @@ -372,12 +398,14 @@ def main(
# Set a default value for $ShowFullFormInput to False.
# Then, it can be changed by the settings file (in WL)
# and overwritten by the command line parameter.
definitions.set_ownvalue(
"Settings`$ShowFullFormInput", from_python(True if full_form else False)
)
definitions.set_ownvalue(
"Settings`$PygmentsShowTokens", from_python(True if pygments_tokens else False)
)
for setting_name, setting_value in (
("$ShowFullFormInput", full_form),
("$UseAsymptote", asymptote),
("$UseMatplotlib", matplotlib),
):
definitions.set_ownvalue(
f"Settings`{setting_name}", from_python(True if setting_value else False)
)

if post_mortem:
try:
Expand Down Expand Up @@ -475,9 +503,6 @@ def main(
"Settings`$ShowFullFormInput", SymbolTrue if full_form else SymbolFalse
)

definitions.set_ownvalue(
"Settings`$PygmentsStyle", from_python(shell.pygments_style)
)
definitions.set_ownvalue(
"Settings`$PygmentsShowTokens", from_python(pygments_tokens)
)
Expand All @@ -490,7 +515,9 @@ def main(
)

definitions.set_line_no(0)
interactive_eval_loop(shell, unicode, prompt, strict_wl_output)
interactive_eval_loop(
shell, unicode, prompt, asymptote, matplotlib, strict_wl_output
)
return exit_rc


Expand Down
12 changes: 12 additions & 0 deletions mathicsscript/asymptote.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
import mathics
import os
import os.path as osp
import subprocess

from subprocess import Popen, PIPE, run
from tempfile import NamedTemporaryFile
from typing import Optional

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


def write_asy_and_view(asy_string: str):
# TODO: add option to let user decide whether or not to delete
# image afterwards.
with NamedTemporaryFile(
mode="w", prefix="Mathics3-Graph-", suffix=".asy", delete=False
) as asy_fp:
asy_fp.write(asy_string + "\n")
subprocess.run(args=[asy_program, "-View", asy_fp.name])


if __name__ == "__main__":
g = Asy()
g.size(200)
Expand Down
12 changes: 7 additions & 5 deletions mathicsscript/autoload/settings.m
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
(* -*- wolfram -*- *)
(**********************************************************************)
(* *)
(* Settings for mathicsscript *)
(* *)
(* *)
(* Values that can be set from the command line should not have a *)
(* default value set here, just the "usage" value. *)
(* *)
(**********************************************************************)

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

Settings`$UseAsymptote::usage = "This Boolean variable sets whether 3D Graphics should render using Asymptote."
Settings`$UseAsymptote = True
Settings`$UseAsymptote::usage = "This Boolean variable sets whether 2D and 3D Graphics should render using Asymptote."
Settings`$UseMatplotlib::usage = "This Boolean variable sets whether 2D Graphics should render using Matplotlib.
Settings`$UseMatplotlib::usage = "This Boolean variable sets whether 2D Graphics should render using Matplotlib."
Settings`$UseMatplotlib = True
If set, and $UseAsymptote is also set, matplotlib will take precedence for 2D graphics.
"

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

Expand Down
5 changes: 2 additions & 3 deletions mathicsscript/data/inputrc-no-unicode
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
# GNU Readline input unicode translations
# Autogenerated from mathics_scanner.generate.rl_inputrc on Wed Oct 26 04:49:35 PM EDT 2022

"\ea'\e": "á"
"\ea-\e": "ā"
"\eau\e": "ă"
Expand Down Expand Up @@ -504,9 +501,11 @@
"\e<--\e": "⟵"
"\e<-->\e": "⟷"
"\e-->\e": "⟶"
"\eMlim\e": "\\[MaxLimit]"
"\emath\e": "\\[MathematicaIcon]"
"\emho\e": "℧"
"\emi\e": "µ"
"\emlim\e": "lim"
"\e-+\e": "∓"
"\em\e": "μ"
"\env\e": "ň"
Expand Down
90 changes: 48 additions & 42 deletions mathicsscript/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
except ImportError:
svg2png = None

from mathicsscript.asymptote import Asy
from mathicsscript.asymptote import Asy, write_asy_and_view

have_asymptote = False
try:
Expand Down Expand Up @@ -92,6 +92,7 @@ def eval_boxes(result, fn: Callable, obj, **options):

expr_type = expr.get_head_name()
expr_head = expr.get_head()

if expr_head is SymbolMathMLForm:
format = "xml"
elements = expr.elements
Expand All @@ -102,57 +103,62 @@ def eval_boxes(result, fn: Callable, obj, **options):
elements = expr.elements
if len(elements) == 1:
expr = elements[0]
elif expr_head is SymbolImage:
if get_settings_value(obj.definitions, "Settings`$UseMatplotlib") and plt:
temp_png = NamedTemporaryFile(
mode="w+b", suffix=".png", prefix="mathicsscript-"
elif (
expr_head is SymbolImage
and get_settings_value(obj.definitions, "Settings`$UseMatplotlib")
and plt
):
temp_png = NamedTemporaryFile(
mode="w+b", suffix=".png", prefix="mathicsscript-"
)
try:
png_expr = Expression(
SymbolExport, String(temp_png.name), expr, String("PNG")
)
try:
png_expr = Expression(
SymbolExport, String(temp_png.name), expr, String("PNG")
)
result = png_expr.evaluate(obj)
plt.axes().set_axis_off()
img = mpimg.imread(temp_png)
cmap = "gray" if expr.color_space == "Grayscale" else None
plt.imshow(img, cmap=cmap)
plt.show()
except: # noqa
pass
temp_png.close()

result = png_expr.evaluate(obj)
plt.axes().set_axis_off()
img = mpimg.imread(temp_png)
cmap = "gray" if expr.color_space == "Grayscale" else None
plt.imshow(img, cmap=cmap)
plt.show()
except: # noqa
pass
temp_png.close()

elif expr_head in (SymbolGraphics, SymbolPlot):
if (
get_settings_value(obj.definitions, "Settings`$UseMatplotlib")
and plt
and svg2png
):
svg_expr = Expression(SymbolExportString, expr, String("SVG"))
svg_str = svg_expr.evaluate(obj).to_python(string_quotes=False)
temp_png = NamedTemporaryFile(
mode="w+b", suffix=".png", prefix="mathicsscript-"
)
try:
svg2png(bytestring=svg_str, write_to=temp_png.name)
plt.axes().set_axis_off()
img = mpimg.imread(temp_png)
plt.imshow(img)
plt.show()
temp_png.close()
except: # noqa
pass
elif (
expr_head in (SymbolGraphics, SymbolPlot)
and get_settings_value(obj.definitions, "Settings`$UseMatplotlib")
and plt
and svg2png
):
svg_expr = Expression(SymbolExportString, expr, String("SVG"))
svg_str = svg_expr.evaluate(obj).to_python(string_quotes=False)
temp_png = NamedTemporaryFile(
mode="w+b", suffix=".png", prefix="mathicsscript-"
)
try:
svg2png(bytestring=svg_str, write_to=temp_png.name)
plt.axes().set_axis_off()
img = mpimg.imread(temp_png)
plt.imshow(img)
plt.show()
temp_png.close()
except: # noqa
pass
return expr_type
elif (
expr_head in (SymbolGraphics3D,)
expr_head in (SymbolGraphics, SymbolPlot, SymbolGraphics3D)
and have_asymptote
and get_settings_value(obj.definitions, "Settings`$UseAsymptote")
):
asy_expr = Expression(SymbolExportString, expr, String("asy"))
asy_str = asy_expr.evaluate(obj).to_python(string_quotes=False)
asymptote_graph.erase()
asymptote_graph.send(asy_str)

# Alternate older version
# asymptote_graph.erase()
# asymptote_graph.send(asy_str)

write_asy_and_view(asy_str)
return expr_type

if format == "text":
Expand Down
9 changes: 2 additions & 7 deletions mathicsscript/termshell.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2020-2022 Rocky Bernstein <[email protected]>
# Copyright (C) 2020-2022, 2024 Rocky Bernstein <[email protected]>

from columnize import columnize

Expand Down Expand Up @@ -115,18 +115,13 @@ def __init__(
try:
self.terminal_formatter = Terminal256Formatter(style=style)
except ClassNotFound:
print(
"Pygments style name '%s' not found; No pygments style set" % style
)
print(f"Pygments style name '{style}' not found; No pygments style set")

self.pygments_style = style
self.definitions = definitions
set_settings_value(
self.definitions, "Settings`$PygmentsShowTokens", from_python(False)
)
set_settings_value(
self.definitions, "Settings`$PygmentsStyle", from_python(style)
)
set_settings_value(
self.definitions, "Settings`$UseUnicode", from_python(use_unicode)
)
Expand Down
1 change: 1 addition & 0 deletions mathicsscript/user-settings.m
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
(* -*- wolfram -*- *)
(***********************************************************)
(* User settings config for mathicsscript *)
(* Customize this with Mathics definitions as desired. *)
Expand Down

0 comments on commit ba3b412

Please sign in to comment.