X Tutup
Skip to content

Commit f1edce9

Browse files
dictionary completion working! Bring on the custom completion!
1 parent acde8ab commit f1edce9

File tree

6 files changed

+48
-26
lines changed

6 files changed

+48
-26
lines changed

bpython/autocomplete.py

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import __builtin__
2626
import __main__
2727
import rlcompleter
28-
import line
28+
import line as lineparts
2929
import re
3030
import os
3131
from glob import glob
@@ -210,6 +210,10 @@ def get_completer(cursor_offset, current_line, locals_, argspec, config, magic_m
210210
if matches is not None:
211211
return sorted(set(matches)), FilenameCompletion
212212

213+
matches = DictKeyCompletion.matches(cursor_offset, current_line, locals_=locals_, config=config)
214+
if matches is not None:
215+
return sorted(set(matches)), DictKeyCompletion
216+
213217
matches = AttrCompletion.matches(cursor_offset, current_line, locals_=locals_, config=config)
214218
if matches is not None:
215219
cw = AttrCompletion.locate(cursor_offset, current_line)[2]
@@ -264,18 +268,18 @@ def substitute(cls, cursor_offset, line, match):
264268

265269
class ImportCompletion(BaseCompletionType):
266270
matches = staticmethod(importcompletion.complete)
267-
locate = staticmethod(line.current_word)
271+
locate = staticmethod(lineparts.current_word)
268272
format = staticmethod(after_last_dot)
269273

270274
class FilenameCompletion(BaseCompletionType):
271275
shown_before_tab = False
272276
@classmethod
273277
def matches(cls, cursor_offset, current_line):
274-
cs = line.current_string(cursor_offset, current_line)
278+
cs = lineparts.current_string(cursor_offset, current_line)
275279
if cs is None:
276280
return None
277281
return filename_matches(cs[2])
278-
locate = staticmethod(line.current_string)
282+
locate = staticmethod(lineparts.current_string)
279283
format = staticmethod(last_part_of_filename)
280284

281285
class AttrCompletion(BaseCompletionType):
@@ -292,9 +296,25 @@ def matches(cls, cursor_offset, line, locals_, config):
292296
# possibly be raised here, so if anyone wants to do that, feel free to send me
293297
# a patch. XXX: Make sure you raise here if you're debugging the completion
294298
# stuff !
295-
e = True
296-
raise
297-
else:
298-
e = False
299-
locate = staticmethod(line.current_word)
299+
pass
300+
return None
301+
locate = staticmethod(lineparts.current_word)
300302
format = staticmethod(after_last_dot)
303+
304+
class DictKeyCompletion(BaseCompletionType):
305+
locate = staticmethod(lineparts.current_dict_key)
306+
@classmethod
307+
def matches(cls, cursor_offset, line, locals_, config):
308+
r = cls.locate(cursor_offset, line)
309+
if r is None:
310+
return None
311+
start, end, orig = r
312+
_, _, dexpr = lineparts.current_dict(cursor_offset, line)
313+
obj = eval(dexpr, locals_)
314+
if obj and isinstance(obj, type({})) and obj.keys():
315+
return ["{!r}]".format(k) for k in obj.keys() if repr(k).startswith(orig)]
316+
else:
317+
return []
318+
@classmethod
319+
def format(cls, match):
320+
return match[:-1]

bpython/cli.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1436,7 +1436,12 @@ def tab(self, back=False):
14361436

14371437
# 3. check to see if we can expand the current word
14381438
if self.matches_iter.is_cseq():
1439-
self.cursor_offset, self.s = self.matches_iter.substitute_cseq()
1439+
#TODO resolve this error-prone situation:
1440+
# can't assign at same time to self.s and self.cursor_offest
1441+
# because for cursor_offset
1442+
# property to work correctly, self.s must already be set
1443+
temp_cursor_offset, self.s = self.matches_iter.substitute_cseq()
1444+
self.cursor_offset = temp_cursor_offset
14401445
self.print_line(self.s)
14411446
if not self.matches_iter:
14421447
self.complete()

bpython/curtsiesfrontend/repl.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -738,7 +738,7 @@ def paint(self, about_to_exit=False, user_quit=False):
738738
visible_space_below = min_height - current_line_end_row - 1
739739

740740
info_max_rows = max(visible_space_above, visible_space_below)
741-
infobox = paint.paint_infobox(info_max_rows, int(width * self.config.cli_suggestion_width), self.matches_iter.matches, self.argspec, self.current_match, self.docstring, self.config)
741+
infobox = paint.paint_infobox(info_max_rows, int(width * self.config.cli_suggestion_width), self.matches_iter.matches, self.argspec, self.current_match, self.docstring, self.config, self.matches_iter.completer.format)
742742

743743
if visible_space_above >= infobox.height and self.config.curtsies_list_above:
744744
arr[current_line_start_row - infobox.height:current_line_start_row, 0:infobox.width] = infobox

bpython/curtsiesfrontend/replpainter.py

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,22 +39,17 @@ def paint_current_line(rows, columns, current_display_line):
3939
lines = display_linize(current_display_line, columns, True)
4040
return fsarray(lines, width=columns)
4141

42-
def matches_lines(rows, columns, matches, current, config):
42+
def matches_lines(rows, columns, matches, current, config, format):
4343
highlight_color = func_for_letter(config.color_scheme['operator'].lower())
4444

4545
if not matches:
4646
return []
4747
color = func_for_letter(config.color_scheme['main'])
4848
max_match_width = max(len(m) for m in matches)
4949
words_wide = max(1, (columns - 1) // (max_match_width + 1))
50-
if os.path.sep in matches[0]: # filename completion
51-
pass
52-
elif '.' in matches[0]:
53-
matches = [m.rstrip('.').rsplit('.')[-1] for m in matches]
54-
if current:
55-
current = current.rstrip('.').rsplit('.')[-1]
56-
else:
57-
pass
50+
matches = [format(m) for m in matches]
51+
if current:
52+
current = format(current)
5853

5954
matches_lines = [fmtstr(' ').join(color(m.ljust(max_match_width))
6055
if m != current
@@ -147,13 +142,13 @@ def formatted_docstring(docstring, columns, config):
147142
return sum(([color(x) for x in (display_linize(line, columns) if line else fmtstr(''))]
148143
for line in docstring.split('\n')), [])
149144

150-
def paint_infobox(rows, columns, matches, argspec, match, docstring, config):
145+
def paint_infobox(rows, columns, matches, argspec, match, docstring, config, format):
151146
"""Returns painted completions, argspec, match, docstring etc."""
152147
if not (rows and columns):
153148
return fsarray(0, 0)
154149
width = columns - 4
155150
lines = ((formatted_argspec(argspec, width, config) if argspec else []) +
156-
(matches_lines(rows, width, matches, match, config) if matches else []) +
151+
(matches_lines(rows, width, matches, match, config, format) if matches else []) +
157152
(formatted_docstring(docstring, width, config) if docstring else []))
158153

159154
output_lines = []

bpython/repl.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,6 @@ def cur_line(self):
308308

309309
def substitute(self, match):
310310
"""Returns a cursor offset and line with match substituted in"""
311-
if match.startswith("'"):
312-
raise ValueError(match)
313311
start, end, word = self.completer.locate(self.orig_cursor_offset, self.orig_line)
314312
result = start + len(match), self.orig_line[:start] + match + self.orig_line[end:]
315313
return result
@@ -321,9 +319,12 @@ def substitute_cseq(self):
321319
"""Returns a new line by substituting a common sequence in, and update matches"""
322320
cseq = os.path.commonprefix(self.matches)
323321
new_cursor_offset, new_line = self.substitute(cseq)
324-
self.update(new_cursor_offset, new_line, self.matches, self.completer)
325322
if len(self.matches) == 1:
326323
self.clear()
324+
else:
325+
self.update(new_cursor_offset, new_line, self.matches, self.completer)
326+
if len(self.matches) == 1:
327+
self.clear()
327328
return new_cursor_offset, new_line
328329

329330
def update(self, cursor_offset, current_line, matches, completer):
@@ -335,7 +336,7 @@ def update(self, cursor_offset, current_line, matches, completer):
335336
assert matches is not None
336337
self.matches = matches
337338
self.completer = completer
338-
assert self.completer.locate(self.orig_cursor_offset, self.orig_line) is not None
339+
assert self.completer.locate(self.orig_cursor_offset, self.orig_line) is not None, (self.completer.locate, self.orig_cursor_offset, self.orig_line)
339340
self.index = -1
340341
self.start, self.end, self.current_word = self.completer.locate(self.orig_cursor_offset, self.orig_line)
341342

bpython/test/test_line_properties.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ def test_simple(self):
131131
self.assertAccess('asdf[<(1,>|]')
132132
self.assertAccess('asdf[<(1, >|]')
133133
self.assertAccess('asdf[<(1, 2)>|]')
134+
self.assertAccess('d[d[<12|>')
134135

135136
class TestCurrentDict(LineTestCase):
136137
def setUp(self):

0 commit comments

Comments
 (0)
X Tutup