Skip to content

Commit 5eba4f1

Browse files
committed
🎨 Centralize color handling
1 parent 2a35131 commit 5eba4f1

File tree

1 file changed

+37
-14
lines changed

1 file changed

+37
-14
lines changed

‎combinator.py‎

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,31 @@
3434
from colored import Fore, Style
3535

3636

37+
is_terminal = sys.stdout.isatty()
38+
colors = {n: '' for n in ["off", "input_prompt", "var", "freevar", "combinator", "lambda", "output_prompt"]}
39+
if is_terminal:
40+
for k in colors:
41+
match k:
42+
case "input_prompt":
43+
newval = Fore.rgb(242, 45, 57)
44+
case "output_prompt":
45+
newval = Fore.rgb(45, 242, 57)
46+
case "var":
47+
newval= Fore.rgb(242, 185, 45)
48+
case "freevar":
49+
newval= Fore.rgb(255, 64, 23)
50+
case "combinator":
51+
newval = Fore.rgb(255, 0, 163)
52+
case "lambda":
53+
newval = Fore.rgb(45, 135, 242)
54+
case "off":
55+
newval = Style.reset
56+
case _:
57+
print(f'unhandled color {k}')
58+
sys.exit(1)
59+
colors[k] = newval
60+
61+
3762
# These are the characters accepted and used s variable names. The list
3863
# could be extended here and everything else should just work. But it
3964
# should be noted that
@@ -189,8 +214,6 @@ class Var(Obj):
189214
"""Object to represent a variable in the lambda expression graph. This implements
190215
the de Bruijn notation by representing each new variable with a unique number."""
191216
varcnt: ClassVar[int] = 1
192-
color: ClassVar[str] = Fore.rgb(242, 185, 45)
193-
color_free: ClassVar[str] = Fore.rgb(255, 64, 23)
194217

195218
def __init__(self, freename: Optional[str] = None):
196219
self.id = Var.varcnt
@@ -210,7 +233,7 @@ def __str__(self):
210233
@override
211234
def fmt(self, varmap: Naming, highlight: bool) -> str:
212235
res = self.freename or varmap.get(self)
213-
return f'{Var.color_free if self.freename else Var.color}{res}{Style.reset}' if highlight else res
236+
return f'{colors["freevar" if self.freename else "var"]}{res}{colors["off"]}'
214237

215238
@override
216239
def replace(self, v: Var, expr: Obj) -> Obj:
@@ -262,8 +285,6 @@ def fmt(self, varmap: Naming, highlight: bool) -> str:
262285

263286
class Combinator(Obj):
264287
"""Object to represent a recombined combinator."""
265-
color: ClassVar[str] = Fore.rgb(255, 0, 163)
266-
267288
def __init__(self, combinator: str, arguments: Optional[List[Obj]] = None):
268289
self.combinator = combinator
269290
self.arguments = [] if arguments is None else arguments
@@ -280,7 +301,7 @@ def __str__(self):
280301

281302
@override
282303
def fmt(self, varmap: Naming, highlight: bool) -> str:
283-
combres = f'{Combinator.color}{self.combinator}{Style.reset}' if highlight else self.combinator
304+
combres = f'{colors["combinator"]}{self.combinator}{colors["off"]}'
284305
if self.arguments:
285306
combres += ' ' + ' '.join([a.fmt(varmap, highlight) for a in self.arguments])
286307
return combres
@@ -341,8 +362,6 @@ def beta(self) -> Obj:
341362

342363
class Lambda(Obj):
343364
"""Object to represent a lambda expression in the lambda expression graph."""
344-
color: ClassVar[str] = Fore.rgb(45, 135, 242)
345-
346365
def __init__(self, params: List[Var], code: Obj):
347366
if not params:
348367
raise SyntaxError('lambda parameter list cannot be empty')
@@ -368,7 +387,7 @@ def fmt(self, varmap: Naming, highlight: bool) -> str:
368387
nvarmap = Naming(varmap.avoid)
369388
paramstr = ''.join([a.fmt(nvarmap, highlight) for a in self.params])
370389
varmap.add(nvarmap)
371-
la = f'{Lambda.color}λ{Style.reset}' if highlight else 'λ'
390+
la = f'{colors["lambda"]}λ{colors["off"]}'
372391
return f'({la}{paramstr}.{remove_braces(self.code.fmt(varmap, highlight))})'
373392

374393
@override
@@ -574,17 +593,20 @@ def handle(al: List[str], echo: bool, is_terminal: bool = False) -> int:
574593
"""Loop over given list of strings, parse, simplify, and print the lambda
575594
expression."""
576595
ec = 0
577-
pr = f'{Fore.rgb(45, 242, 57)}⇒{Style.reset} ' if is_terminal else '⇒ ' if is_terminal else ''
596+
input_prompt = f'{colors["input_prompt"]}»{colors["off"]} '
597+
output_prompt = f'{colors["output_prompt"]}⇒{colors["off"]} ' if is_terminal else ''
598+
separator_len = os.get_terminal_size()[0] if is_terminal else 72
599+
578600
for a in al:
579601
if echo and is_terminal:
580-
print(f'{Fore.rgb(242, 45, 57)}»{Style.reset} {a}' if is_terminal else f'» {a}')
602+
print(f'{input_prompt}{a}')
581603
try:
582-
print(f'{pr}{to_string(from_string(a), is_terminal)}')
604+
print(f'{output_prompt}{to_string(from_string(a), is_terminal)}')
583605
except SyntaxError as e:
584606
print(f'eval("{a}") failed: {e.args[0]}')
585607
ec = 1
586608
if not echo:
587-
print('\u2501' * (os.get_terminal_size()[0] if is_terminal else 72))
609+
print('\u2501' * separator_len)
588610
return ec
589611

590612

@@ -593,8 +615,9 @@ def repl() -> int:
593615
ec = 0
594616
try:
595617
is_terminal = sys.stdout.isatty()
618+
input_prefix = f'{colors["input_prompt"]}»{colors["off"]} '
596619
while True:
597-
s = input(f'{Fore.rgb(242, 45, 57)}»{Style.reset} ' if is_terminal else '» ')
620+
s = input(input_prefix)
598621
if not s:
599622
break
600623
ec = ec | handle([s], False, is_terminal)

0 commit comments

Comments
 (0)