forked from bpython/bpython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparse.py
More file actions
89 lines (70 loc) · 2.24 KB
/
parse.py
File metadata and controls
89 lines (70 loc) · 2.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# coding: utf-8
from __future__ import unicode_literals
from functools import partial
import re
from bpython.lazyre import LazyReCompile
from curtsies.termformatconstants import FG_COLORS, BG_COLORS, colors
from curtsies.formatstring import fmtstr, FmtStr
cnames = dict(zip('krgybmcwd', colors + ('default',)))
def func_for_letter(l, default='k'):
"""Returns FmtStr constructor for a bpython-style color code"""
if l == 'd':
l = default
elif l == 'D':
l = default.upper()
return partial(fmtstr, fg=cnames[l.lower()], bold=l.isupper())
def color_for_letter(l, default='k'):
if l == 'd':
l = default
return cnames[l.lower()]
def parse(s):
"""Returns a FmtStr object from a bpython-formatted colored string"""
rest = s
stuff = []
while True:
if not rest:
break
start, rest = peel_off_string(rest)
stuff.append(start)
return (sum((fs_from_match(d) for d in stuff[1:]), fs_from_match(stuff[0]))
if len(stuff) > 0
else FmtStr())
def fs_from_match(d):
atts = {}
if d['fg']:
# this isn't according to spec as I understand it
if d['fg'].isupper():
d['bold'] = True
# TODO figure out why boldness isn't based on presence of \x02
color = cnames[d['fg'].lower()]
if color != 'default':
atts['fg'] = FG_COLORS[color]
if d['bg']:
if d['bg'] == 'I':
# hack for finding the "inverse"
color = colors[(colors.index(color) + (len(colors) // 2)) %
len(colors)]
else:
color = cnames[d['bg'].lower()]
if color != 'default':
atts['bg'] = BG_COLORS[color]
if d['bold']:
atts['bold'] = True
return fmtstr(d['string'], **atts)
peel_off_string_re = LazyReCompile(
r"""(?P<colormarker>\x01
(?P<fg>[krgybmcwdKRGYBMCWD]?)
(?P<bg>[krgybmcwdKRGYBMCWDI]?)?)
(?P<bold>\x02?)
\x03
(?P<string>[^\x04]*)
\x04
(?P<rest>.*)
""", re.VERBOSE | re.DOTALL)
def peel_off_string(s):
m = peel_off_string_re.match(s)
assert m, repr(s)
d = m.groupdict()
rest = d['rest']
del d['rest']
return d, rest