X Tutup
Skip to content

Commit d441dd5

Browse files
committed
Move curtsies.bpythonparse to bpython.curtsiesfrontent.parse
This is the bpython part of curtsies #44. Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
1 parent 8c11b56 commit d441dd5

File tree

5 files changed

+113
-5
lines changed

5 files changed

+113
-5
lines changed

bpython/curtsiesfrontend/interpreter.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import sys
44
from pygments.token import *
55
from pygments.formatter import Formatter
6-
from curtsies.bpythonparse import parse
6+
from bpython.curtsiesfrontend.parse import parse
77
from codeop import CommandCompiler
88
from pygments.lexers import get_lexer_by_name
99

@@ -27,7 +27,7 @@
2727
Name.Function:'d',
2828
Name.Class:'d',
2929
}
30-
30+
3131
class BPythonFormatter(Formatter):
3232
"""This is subclassed from the custom formatter for bpython.
3333
Its format() method receives the tokensource

bpython/curtsiesfrontend/parse.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
2+
from bpython.formatter import BPythonFormatter
3+
from bpython._py3compat import PythonLexer
4+
from bpython.config import Struct, loadini, default_config_path
5+
6+
from curtsies.termformatconstants import FG_COLORS, BG_COLORS, colors
7+
from curtsies.formatstring import fmtstr, FmtStr
8+
9+
from pygments import format
10+
from functools import partial
11+
12+
import re
13+
14+
cnames = dict(list(zip('krgybmcwd', colors + ('default',))))
15+
16+
def func_for_letter(l, default='k'):
17+
"""Returns FmtStr constructor for a bpython-style color code"""
18+
if l == 'd':
19+
l = default
20+
elif l == 'D':
21+
l = default.upper()
22+
return partial(fmtstr, fg=cnames[l.lower()], bold=(l.lower() != l))
23+
24+
def color_for_letter(l, default='k'):
25+
if l == 'd':
26+
l = default
27+
return cnames[l.lower()]
28+
29+
def parse(s):
30+
"""Returns a FmtStr object from a bpython-formatted colored string"""
31+
rest = s
32+
stuff = []
33+
while True:
34+
if not rest:
35+
break
36+
d, rest = peel_off_string(rest)
37+
stuff.append(d)
38+
return (sum([fs_from_match(d) for d in stuff[1:]], fs_from_match(stuff[0]))
39+
if len(stuff) > 0
40+
else FmtStr())
41+
42+
def fs_from_match(d):
43+
atts = {}
44+
if d['fg']:
45+
46+
# this isn't according to spec as I understand it
47+
if d['fg'] != d['fg'].lower():
48+
d['bold'] = True
49+
#TODO figure out why boldness isn't based on presence of \x02
50+
51+
color = cnames[d['fg'].lower()]
52+
if color != 'default':
53+
atts['fg'] = FG_COLORS[color]
54+
if d['bg']:
55+
if d['bg'] == 'I':
56+
color = colors[(colors.index(color) + (len(colors) // 2)) % len(colors)] # hack for finding the "inverse"
57+
else:
58+
color = cnames[d['bg'].lower()]
59+
if color != 'default':
60+
atts['bg'] = BG_COLORS[color]
61+
if d['bold']:
62+
atts['bold'] = True
63+
return fmtstr(d['string'], **atts)
64+
65+
def peel_off_string(s):
66+
r"""
67+
>>> r = peel_off_string('\x01RI\x03]\x04asdf')
68+
>>> r == ({'bg': 'I', 'string': ']', 'fg': 'R', 'colormarker': '\x01RI', 'bold': ''}, 'asdf')
69+
True
70+
"""
71+
p = r"""(?P<colormarker>\x01
72+
(?P<fg>[krgybmcwdKRGYBMCWD]?)
73+
(?P<bg>[krgybmcwdKRGYBMCWDI]?)?)
74+
(?P<bold>\x02?)
75+
\x03
76+
(?P<string>[^\x04]*)
77+
\x04
78+
(?P<rest>.*)
79+
"""
80+
m = re.match(p, s, re.VERBOSE | re.DOTALL)
81+
assert m, repr(s)
82+
d = m.groupdict()
83+
rest = d['rest']
84+
del d['rest']
85+
return d, rest
86+
87+
def string_to_fmtstr(x):
88+
config = Struct()
89+
loadini(config, default_config_path())
90+
return parse(format(PythonLexer().get_tokens(x), BPythonFormatter(config.color_scheme)))

bpython/curtsiesfrontend/repl.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@
2323

2424
import curtsies
2525
from curtsies import FSArray, fmtstr, FmtStr, Termmode
26-
from curtsies.bpythonparse import parse as bpythonparse
27-
from curtsies.bpythonparse import func_for_letter, color_for_letter
2826
from curtsies import fmtfuncs
2927
from curtsies import events
3028

@@ -44,6 +42,8 @@
4442
from bpython.curtsiesfrontend.interaction import StatusBar
4543
from bpython.curtsiesfrontend.manual_readline import edit_keys
4644
from bpython.curtsiesfrontend import events as bpythonevents
45+
from bpython.curtsiesfrontend.parse import parse as bpythonparse
46+
from bpython.curtsiesfrontend.parse import func_for_letter, color_for_letter
4747

4848
#TODO other autocomplete modes (also fix in other bpython implementations)
4949

bpython/curtsiesfrontend/replpainter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
import logging
33

44
from curtsies import fsarray, fmtstr
5-
from curtsies.bpythonparse import func_for_letter
65
from curtsies.formatstring import linesplit
76
from curtsies.fmtfuncs import bold
87

8+
from bpython.curtsiesfrontend.parse import func_for_letter
99
from bpython._py3compat import py3
1010
if not py3:
1111
import inspect
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import unittest
2+
3+
from bpython.curtsiesfrontend import parse
4+
from curtsies.fmtfuncs import yellow, cyan, green, bold
5+
6+
class TestExecArgs(unittest.TestCase):
7+
8+
def test_parse(self):
9+
self.assertEquals(parse.parse(u'\x01y\x03print\x04'),
10+
yellow(u'print'))
11+
12+
self.assertEquals(parse.parse(u'\x01y\x03print\x04\x01c\x03 \x04\x01g\x031\x04\x01c\x03 \x04\x01Y\x03+\x04\x01c\x03 \x04\x01g\x032\x04'),
13+
yellow(u'print')+cyan(u' ')+green(u'1')+cyan(u' ')+bold(yellow(u'+'))+cyan(' ')+green(u'2'))
14+
15+
def test_peal_off_string(self):
16+
self.assertEquals(parse.peel_off_string('\x01RI\x03]\x04asdf'),
17+
({'bg': 'I', 'string': ']', 'fg': 'R', 'colormarker':
18+
'\x01RI', 'bold': ''}, 'asdf'))

0 commit comments

Comments
 (0)
X Tutup