Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
28 changes: 22 additions & 6 deletions mathicsscript/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
from mathics.core.evaluation import Evaluation, Output
from mathics.core.expression import from_python
from mathics.core.parser import MathicsFileLineFeeder
from mathics.core.symbols import Symbol, SymbolFalse, SymbolTrue
from mathics.core.symbols import Symbol, SymbolNull, SymbolFalse, SymbolTrue
from mathics.core.systemsymbols import SymbolTeXForm
from mathics.session import autoload_files

Expand Down Expand Up @@ -113,7 +113,10 @@ def ensure_settings():
return settings_file


def load_settings(shell):
def load_settings_file(shell):
"""
Read in or "autoload" Mathics3 code to initialize some settings.
"""
autoload_files(shell.definitions, get_srcdir(), "autoload")
settings_file = ensure_settings()
if settings_file == "":
Expand Down Expand Up @@ -182,6 +185,7 @@ def fmt_fun(query: Any) -> Any:
style = style.get_string_value()
if shell.terminal_formatter:
fmt = fmt_fun
shell.pygments_style = style or "None"

evaluation = Evaluation(shell.definitions, output=TerminalOutput(shell))

Expand All @@ -200,7 +204,10 @@ def fmt_fun(query: Any) -> Any:
):
current_pos = GNU_readline.get_current_history_length()
for pos in range(last_pos, current_pos - 1):
GNU_readline.remove_history_item(pos)
try:
GNU_readline.remove_history_item(pos)
except ValueError:
pass
wl_input = source_code.rstrip()
if unicode:
wl_input = replace_wl_with_plain_text(wl_input)
Expand Down Expand Up @@ -434,6 +441,10 @@ def main(
f"Settings`{setting_name}", from_python(True if setting_value else False)
)

if os.environ.get("NO_COLOR", False) and style not in (None, "None"):
print('Environment variable NO_COLOR set when "style" option given.')
print("NO_COLOR setting ignored.")

if post_mortem:
try:
from trepan.post_mortem import post_mortem_excepthook
Expand All @@ -448,15 +459,20 @@ def main(
readline = "none" if (code or file and not persist) else readline.lower()
if readline == "prompt":
shell = TerminalShellPromptToolKit(
definitions, style, completion, charset, prompt, edit_mode
definitions, completion, charset, prompt, edit_mode
)
else:
want_readline = readline == "gnu"
shell = TerminalShellGNUReadline(
definitions, style, want_readline, completion, charset, prompt
definitions, want_readline, completion, charset, prompt
)

load_settings(shell)
load_settings_file(shell)
style_from_settings_file = definitions.get_ownvalue("Settings`$PygmentsStyle")
if style_from_settings_file is SymbolNull and style is None:
style = style_from_settings_file
shell.setup_pygments_style(style)

if file:
with open(file, "r") as ifile:
feeder = MathicsFileLineFeeder(ifile)
Expand Down
33 changes: 0 additions & 33 deletions mathicsscript/bindkeys.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,11 @@
from prompt_toolkit.enums import EditingMode
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.filters import Condition
from prompt_toolkit.layout import Float, FloatContainer
from prompt_toolkit.widgets import Dialog, Button, Label
from sys import version_info
import contextlib
import pathlib
import re

from mathicsscript.termshell import ALL_PYGMENTS_STYLES
from mathicsscript.settings import definitions
from mathics.session import get_settings_value

Expand Down Expand Up @@ -149,36 +146,6 @@ def _group_autocomplete_toggle(event):
app.group_autocomplete = not app.group_autocomplete


# Add an additional key binding for toggling this flag.
@bindings.add("f5")
def _next_pygments_style(event):
"""Set Pygments style to the next sytle in ALL_PYGMENTS_STYLE."""
app = event.app

try:
i = ALL_PYGMENTS_STYLES.index(app.pygments_style)
except ValueError:
pass
else:
i = (i + 1) % len(ALL_PYGMENTS_STYLES)
app.pygments_style = ALL_PYGMENTS_STYLES[i]


# Add an additional key binding for toggling this flag.
@bindings.add("f6")
def _prev_pygments_style(event):
"""Set Pygments style to the previous sytle in ALL_PYGMENTS_STYLE."""
app = event.app

try:
i = ALL_PYGMENTS_STYLES.index(app.pygments_style)
except ValueError:
pass
else:
i = (i - 1) % len(ALL_PYGMENTS_STYLES)
app.pygments_style = ALL_PYGMENTS_STYLES[i]


def read_inputrc(read_init_file_fn: Callable, use_unicode: bool) -> None:
"""
Read GNU Readline style inputrc
Expand Down
136 changes: 92 additions & 44 deletions mathicsscript/termshell.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@
import os
import os.path as osp
import pathlib
import sys
from typing import Any, Optional, Union
from typing import Any, Union

import mathics_scanner.location

from colorama import init as colorama_init
from columnize import columnize
from mathics.core.atoms import String, Symbol
from mathics.core.atoms import Symbol
from mathics.core.attributes import attribute_string_to_number
from mathics.core.expression import Expression, from_python # strip_context,
from mathics.core.rules import Rule
Expand All @@ -32,7 +30,7 @@

mma_lexer = MathematicaLexer()

ALL_PYGMENTS_STYLES = list(get_all_styles())
ALL_PYGMENTS_STYLES = list(get_all_styles()) + ["None"]

color_scheme = TERMINAL_COLORS.copy()
color_scheme[MToken.SYMBOL] = ("yellow", "ansibrightyellow")
Expand Down Expand Up @@ -79,8 +77,7 @@ class TerminalShellCommon(MathicsLineFeeder):
def __init__(
self,
definitions,
style: Optional[str],
_: bool,
want_completion: bool,
use_unicode: bool,
prompt: bool,
):
Expand All @@ -94,38 +91,16 @@ def __init__(
self.lineno = 0
self.terminal_formatter = None
self.prompt = prompt
self.want_completion = want_completion

colorama_init()
if style == "None":
self.terminal_formatter = None
self.incolors = self.outcolors = ["", "", "", ""]
else:
# self.incolors = ["\033[34m", "\033[1m", "\033[22m", "\033[39m"]
self.incolors = ["\033[32m", "\033[1m", "\033[22m", "\033[39m"]
self.outcolors = ["\033[31m", "\033[1m", "\033[22m", "\033[39m"]
if style is not None and not is_pygments_style(style):
style = None

if style is None:
dark_background = is_dark_background()
if dark_background:
style = "inkpot"
else:
style = "colorful"
try:
self.terminal_formatter = Terminal256Formatter(style=style)
except ClassNotFound:
print(f"Pygments style name '{style}' not found; No pygments style set")

self.pygments_style = style
self.definitions = definitions
self.definitions.set_ownvalue(
"Settings`$PygmentsShowTokens", from_python(False)
)
self.definitions.set_ownvalue("Settings`$PygmentsStyle", from_python(style))
self.definitions.set_ownvalue("Settings`$UseUnicode", from_python(use_unicode))
self.definitions.set_ownvalue(
"Settings`PygmentsStylesAvailable", from_python(ALL_PYGMENTS_STYLES)
"Settings`PygmentsStylesAvailable",
from_python(ALL_PYGMENTS_STYLES),
)

self.definitions.add_message(
Expand All @@ -149,20 +124,28 @@ def __init__(
"Settings`PygmentsStylesAvailable",
attribute_string_to_number["System`Locked"],
)

self.definitions.set_attribute(
"Settings`$UseUnicode", attribute_string_to_number["System`Locked"]
)

def change_pygments_style(self, style: str):
if not style or style == self.pygments_style:
return False
if style == "None":
self.terminal_formatter = None
self.pygments_style = style
self.incolors = self.outcolors = ["", "", "", ""]
return True
if is_pygments_style(style):
self.incolors = ["\033[32m", "\033[1m", "\033[22m", "\033[39m"]
self.outcolors = ["\033[31m", "\033[1m", "\033[22m", "\033[39m"]
self.terminal_formatter = Terminal256Formatter(style=style)
self.pygments_style = style
return True
else:
print("Pygments style not changed")
return False

print("Pygments style not changed")
return False

def empty(self):
return False
Expand All @@ -189,19 +172,30 @@ def get_out_prompt(self, form: str) -> Union[str, Any]:
default form, or the name of the Form which was used in output preceded by "//"
"""
line_number = self.last_line_number
return "{2}Out[{3}{0}{4}]{5}{1}= ".format(line_number, form, *self.outcolors)
if self.is_styled:
return "{2}Out[{3}{0}{4}]{5}{1}= ".format(
line_number, form, *self.outcolors
)
else:
return f"Out[{line_number}]= "

@property
def in_prompt(self) -> Union[str, Any]:
next_line_number = self.last_line_number + 1
if self.lineno > 0:
return " " * len(f"In[{next_line_number}]:= ")
else:
elif self.is_styled:
return "{1}In[{2}{0}{3}]:= {4}".format(next_line_number, *self.incolors)
# if have_full_readline:
# return "{1}In[{2}{0}{3}]:= {4}".format(next_line_number, *self.incolors)
# else:
# return f"In[{next_line_number}]:= "
else:
return f"In[{next_line_number}]:= "

@property
def is_styled(self):
"""
Returns True if a Pygments style (other than SymbolNull or "None" has been set.
"""
style = self.definitions.get_ownvalue("Settings`$PygmentsStyle")
return not (style is SymbolNull or style.value == "None")

@property
def last_line_number(self) -> int:
Expand All @@ -213,7 +207,8 @@ def last_line_number(self) -> int:
def out_callback(self, out):
print(self.to_output(str(out), form=""))

def read_line(self, prompt, completer=None, use_html=None):
# noinspection PyUnusedLocal
def read_line(self, prompt, _completer=None, _use_html: bool = False):
if self.using_readline:
line = self.rl_read_line(prompt)
else:
Expand Down Expand Up @@ -253,6 +248,19 @@ def print_result(
use_highlight = False
else:
out_str = '"' + out_str.replace('"', r"\"") + '"'

show_pygments_tokens = self.definitions.get_ownvalue(
"Settings`$PygmentsShowTokens"
).to_python()
pygments_style = self.definitions.get_ownvalue(
"Settings`$PygmentsStyle"
).get_string_value()
if pygments_style != self.pygments_style:
if not self.change_pygments_style(pygments_style):
self.definitions.set_ownvalue(
"Settings`$PygmentsStyle", String(self.pygments_style)
)

if eval_type == "System`Graph":
out_str = "-Graph-"
elif self.terminal_formatter: # pygmentize
Expand All @@ -273,7 +281,8 @@ def print_result(
if show_pygments_tokens:
print(list(lex(out_str, mma_lexer)))
if use_highlight:
out_str = highlight(out_str, mma_lexer, self.terminal_formatter)
if self.terminal_formatter is not None:
out_str = highlight(out_str, mma_lexer, self.terminal_formatter)
form = (
""
if not hasattr(result, "form") or result.form is None
Expand All @@ -296,10 +305,49 @@ def rl_read_line(self, prompt):
def reset_lineno(self):
self.lineno = 0

def setup_pygments_style(self, style):
"""Goes through what we need to do to setup or change a
Pygments style.
"""
if (
isinstance(style, str)
and style.lower() == "none"
or style is None
and os.environ.get("NO_COLOR", False)
):
style = "None" # Canonicalize spelling
self.terminal_formatter = None
self.incolors = self.outcolors = ["", "", "", ""]
else:
# self.incolors = ["\033[34m", "\033[1m", "\033[22m", "\033[39m"]
self.incolors = ["\033[32m", "\033[1m", "\033[22m", "\033[39m"]
self.outcolors = ["\033[31m", "\033[1m", "\033[22m", "\033[39m"]
if style is not None and not is_pygments_style(style):
style = None

# If no style given, choose one based on the background.
if style is None:
dark_background = is_dark_background()
if dark_background:
style = "inkpot"
else:
style = "colorful"
try:
self.terminal_formatter = Terminal256Formatter(style=style)
except ClassNotFound:
print(f"Pygments style name '{style}' not found; No pygments style set")
style = "None"

self.definitions.set_ownvalue("Settings`$PygmentsStyle", from_python(style))
self.pygments_style = style

def to_output(self, text: str, form: str) -> str:
"""
Format an 'Out=' line that it lines after the first one indent properly.
"""
line_number = self.last_line_number
newline = "\n" + " " * len(f"Out[{line_number}]{form}= ")
if self.is_styled:
newline = "\n" + " " * len(f"Out[{line_number}]{form}= ")
else:
newline = "\n" + " " * len(f"Out[{line_number}]= ")
return newline.join(text.splitlines())
7 changes: 2 additions & 5 deletions mathicsscript/termshell_gnu.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2020-2022 Rocky Bernstein <rb@dustyfeet.com>
# Copyright (C) 2020-2022, 2025 Rocky Bernstein <rb@dustyfeet.com>

import atexit
import os
Expand Down Expand Up @@ -59,15 +59,12 @@ class TerminalShellGNUReadline(TerminalShellCommon):
def __init__(
self,
definitions,
style: str,
want_readline: bool,
want_completion: bool,
use_unicode: bool,
prompt: bool,
):
super(TerminalShellGNUReadline, self).__init__(
definitions, style, want_completion, use_unicode, prompt
)
super().__init__(definitions, want_completion, use_unicode, prompt)

# Try importing readline to enable arrow keys support etc.
self.using_readline = False
Expand Down
Loading
Loading