55import os
66import os .path as osp
77import pathlib
8- import sys
9- from typing import Any , Optional , Union
8+ from typing import Any , Union
109
1110import mathics_scanner .location
1211
13- from colorama import init as colorama_init
1412from columnize import columnize
15- from mathics .core .atoms import String , Symbol
13+ from mathics .core .atoms import Symbol
1614from mathics .core .attributes import attribute_string_to_number
1715from mathics .core .expression import Expression , from_python # strip_context,
1816from mathics .core .rules import Rule
3230
3331mma_lexer = MathematicaLexer ()
3432
35- ALL_PYGMENTS_STYLES = list (get_all_styles ())
33+ ALL_PYGMENTS_STYLES = list (get_all_styles ()) + [ "None" ]
3634
3735color_scheme = TERMINAL_COLORS .copy ()
3836color_scheme [MToken .SYMBOL ] = ("yellow" , "ansibrightyellow" )
@@ -79,8 +77,7 @@ class TerminalShellCommon(MathicsLineFeeder):
7977 def __init__ (
8078 self ,
8179 definitions ,
82- style : Optional [str ],
83- _ : bool ,
80+ want_completion : bool ,
8481 use_unicode : bool ,
8582 prompt : bool ,
8683 ):
@@ -94,38 +91,16 @@ def __init__(
9491 self .lineno = 0
9592 self .terminal_formatter = None
9693 self .prompt = prompt
94+ self .want_completion = want_completion
9795
98- colorama_init ()
99- if style == "None" :
100- self .terminal_formatter = None
101- self .incolors = self .outcolors = ["" , "" , "" , "" ]
102- else :
103- # self.incolors = ["\033[34m", "\033[1m", "\033[22m", "\033[39m"]
104- self .incolors = ["\033 [32m" , "\033 [1m" , "\033 [22m" , "\033 [39m" ]
105- self .outcolors = ["\033 [31m" , "\033 [1m" , "\033 [22m" , "\033 [39m" ]
106- if style is not None and not is_pygments_style (style ):
107- style = None
108-
109- if style is None :
110- dark_background = is_dark_background ()
111- if dark_background :
112- style = "inkpot"
113- else :
114- style = "colorful"
115- try :
116- self .terminal_formatter = Terminal256Formatter (style = style )
117- except ClassNotFound :
118- print (f"Pygments style name '{ style } ' not found; No pygments style set" )
119-
120- self .pygments_style = style
12196 self .definitions = definitions
12297 self .definitions .set_ownvalue (
12398 "Settings`$PygmentsShowTokens" , from_python (False )
12499 )
125- self .definitions .set_ownvalue ("Settings`$PygmentsStyle" , from_python (style ))
126100 self .definitions .set_ownvalue ("Settings`$UseUnicode" , from_python (use_unicode ))
127101 self .definitions .set_ownvalue (
128- "Settings`PygmentsStylesAvailable" , from_python (ALL_PYGMENTS_STYLES )
102+ "Settings`PygmentsStylesAvailable" ,
103+ from_python (ALL_PYGMENTS_STYLES ),
129104 )
130105
131106 self .definitions .add_message (
@@ -149,20 +124,28 @@ def __init__(
149124 "Settings`PygmentsStylesAvailable" ,
150125 attribute_string_to_number ["System`Locked" ],
151126 )
127+
152128 self .definitions .set_attribute (
153129 "Settings`$UseUnicode" , attribute_string_to_number ["System`Locked" ]
154130 )
155131
156132 def change_pygments_style (self , style : str ):
157133 if not style or style == self .pygments_style :
158134 return False
135+ if style == "None" :
136+ self .terminal_formatter = None
137+ self .pygments_style = style
138+ self .incolors = self .outcolors = ["" , "" , "" , "" ]
139+ return True
159140 if is_pygments_style (style ):
141+ self .incolors = ["\033 [32m" , "\033 [1m" , "\033 [22m" , "\033 [39m" ]
142+ self .outcolors = ["\033 [31m" , "\033 [1m" , "\033 [22m" , "\033 [39m" ]
160143 self .terminal_formatter = Terminal256Formatter (style = style )
161144 self .pygments_style = style
162145 return True
163- else :
164- print ("Pygments style not changed" )
165- return False
146+
147+ print ("Pygments style not changed" )
148+ return False
166149
167150 def empty (self ):
168151 return False
@@ -189,19 +172,30 @@ def get_out_prompt(self, form: str) -> Union[str, Any]:
189172 default form, or the name of the Form which was used in output preceded by "//"
190173 """
191174 line_number = self .last_line_number
192- return "{2}Out[{3}{0}{4}]{5}{1}= " .format (line_number , form , * self .outcolors )
175+ if self .is_styled :
176+ return "{2}Out[{3}{0}{4}]{5}{1}= " .format (
177+ line_number , form , * self .outcolors
178+ )
179+ else :
180+ return f"Out[{ line_number } ]= "
193181
194182 @property
195183 def in_prompt (self ) -> Union [str , Any ]:
196184 next_line_number = self .last_line_number + 1
197185 if self .lineno > 0 :
198186 return " " * len (f"In[{ next_line_number } ]:= " )
199- else :
187+ elif self . is_styled :
200188 return "{1}In[{2}{0}{3}]:= {4}" .format (next_line_number , * self .incolors )
201- # if have_full_readline:
202- # return "{1}In[{2}{0}{3}]:= {4}".format(next_line_number, *self.incolors)
203- # else:
204- # return f"In[{next_line_number}]:= "
189+ else :
190+ return f"In[{ next_line_number } ]:= "
191+
192+ @property
193+ def is_styled (self ):
194+ """
195+ Returns True if a Pygments style (other than SymbolNull or "None" has been set.
196+ """
197+ style = self .definitions .get_ownvalue ("Settings`$PygmentsStyle" )
198+ return not (style is SymbolNull or style .value == "None" )
205199
206200 @property
207201 def last_line_number (self ) -> int :
@@ -213,7 +207,8 @@ def last_line_number(self) -> int:
213207 def out_callback (self , out ):
214208 print (self .to_output (str (out ), form = "" ))
215209
216- def read_line (self , prompt , completer = None , use_html = None ):
210+ # noinspection PyUnusedLocal
211+ def read_line (self , prompt , _completer = None , _use_html : bool = False ):
217212 if self .using_readline :
218213 line = self .rl_read_line (prompt )
219214 else :
@@ -253,6 +248,19 @@ def print_result(
253248 use_highlight = False
254249 else :
255250 out_str = '"' + out_str .replace ('"' , r"\"" ) + '"'
251+
252+ show_pygments_tokens = self .definitions .get_ownvalue (
253+ "Settings`$PygmentsShowTokens"
254+ ).to_python ()
255+ pygments_style = self .definitions .get_ownvalue (
256+ "Settings`$PygmentsStyle"
257+ ).get_string_value ()
258+ if pygments_style != self .pygments_style :
259+ if not self .change_pygments_style (pygments_style ):
260+ self .definitions .set_ownvalue (
261+ "Settings`$PygmentsStyle" , String (self .pygments_style )
262+ )
263+
256264 if eval_type == "System`Graph" :
257265 out_str = "-Graph-"
258266 elif self .terminal_formatter : # pygmentize
@@ -273,7 +281,8 @@ def print_result(
273281 if show_pygments_tokens :
274282 print (list (lex (out_str , mma_lexer )))
275283 if use_highlight :
276- out_str = highlight (out_str , mma_lexer , self .terminal_formatter )
284+ if self .terminal_formatter is not None :
285+ out_str = highlight (out_str , mma_lexer , self .terminal_formatter )
277286 form = (
278287 ""
279288 if not hasattr (result , "form" ) or result .form is None
@@ -296,10 +305,49 @@ def rl_read_line(self, prompt):
296305 def reset_lineno (self ):
297306 self .lineno = 0
298307
308+ def setup_pygments_style (self , style ):
309+ """Goes through what we need to do to setup or change a
310+ Pygments style.
311+ """
312+ if (
313+ isinstance (style , str )
314+ and style .lower () == "none"
315+ or style is None
316+ and os .environ .get ("NO_COLOR" , False )
317+ ):
318+ style = "None" # Canonicalize spelling
319+ self .terminal_formatter = None
320+ self .incolors = self .outcolors = ["" , "" , "" , "" ]
321+ else :
322+ # self.incolors = ["\033[34m", "\033[1m", "\033[22m", "\033[39m"]
323+ self .incolors = ["\033 [32m" , "\033 [1m" , "\033 [22m" , "\033 [39m" ]
324+ self .outcolors = ["\033 [31m" , "\033 [1m" , "\033 [22m" , "\033 [39m" ]
325+ if style is not None and not is_pygments_style (style ):
326+ style = None
327+
328+ # If no style given, choose one based on the background.
329+ if style is None :
330+ dark_background = is_dark_background ()
331+ if dark_background :
332+ style = "inkpot"
333+ else :
334+ style = "colorful"
335+ try :
336+ self .terminal_formatter = Terminal256Formatter (style = style )
337+ except ClassNotFound :
338+ print (f"Pygments style name '{ style } ' not found; No pygments style set" )
339+ style = "None"
340+
341+ self .definitions .set_ownvalue ("Settings`$PygmentsStyle" , from_python (style ))
342+ self .pygments_style = style
343+
299344 def to_output (self , text : str , form : str ) -> str :
300345 """
301346 Format an 'Out=' line that it lines after the first one indent properly.
302347 """
303348 line_number = self .last_line_number
304- newline = "\n " + " " * len (f"Out[{ line_number } ]{ form } = " )
349+ if self .is_styled :
350+ newline = "\n " + " " * len (f"Out[{ line_number } ]{ form } = " )
351+ else :
352+ newline = "\n " + " " * len (f"Out[{ line_number } ]= " )
305353 return newline .join (text .splitlines ())
0 commit comments