|
43 | 43 | from bpython.line import LinePart
|
44 | 44 | from bpython._py3compat import py3, try_decode
|
45 | 45 | from bpython.lazyre import LazyReCompile
|
46 |
| -from bpython.simpleeval import safe_eval, EvaluationError |
| 46 | +from bpython.simpleeval import (safe_eval, evaluate_current_expression, |
| 47 | + EvaluationError) |
47 | 48 |
|
48 | 49 | if not py3:
|
49 | 50 | from types import InstanceType, ClassType
|
@@ -241,7 +242,7 @@ def matches(self, cursor_offset, line, **kwargs):
|
241 | 242 | if r is None:
|
242 | 243 | return None
|
243 | 244 |
|
244 |
| - if locals_ is None: |
| 245 | + if locals_ is None: # TODO add a note about why |
245 | 246 | locals_ = __main__.__dict__
|
246 | 247 |
|
247 | 248 | assert '.' in r.word
|
@@ -524,6 +525,41 @@ def locate(self, current_offset, line):
|
524 | 525 | return lineparts.current_string_literal_attr(current_offset, line)
|
525 | 526 |
|
526 | 527 |
|
| 528 | +class ExpressionAttributeCompletion(AttrCompletion): |
| 529 | + # could replace ArrayItemMember completion and attr completion |
| 530 | + # as a more general case |
| 531 | + def locate(self, current_offset, line): |
| 532 | + return lineparts.current_expression_attribute(current_offset, line) |
| 533 | + |
| 534 | + def matches(self, cursor_offset, line, **kwargs): |
| 535 | + if 'locals_' not in kwargs: |
| 536 | + return None |
| 537 | + locals_ = kwargs['locals_'] |
| 538 | + |
| 539 | + if locals_ is None: |
| 540 | + locals_ = __main__.__dict__ |
| 541 | + |
| 542 | + attr = self.locate(cursor_offset, line) |
| 543 | + |
| 544 | + try: |
| 545 | + obj = evaluate_current_expression(cursor_offset, line, locals_) |
| 546 | + except EvaluationError: |
| 547 | + return set() |
| 548 | + with inspection.AttrCleaner(obj): |
| 549 | + # strips leading dot |
| 550 | + matches = [m[1:] for m in self.attr_lookup(obj, '', attr.word)] |
| 551 | + |
| 552 | + if attr.word.startswith('__'): |
| 553 | + pass |
| 554 | + elif attr.word.startswith('_'): |
| 555 | + matches = set(match for match in matches |
| 556 | + if not match.startswith('__')) |
| 557 | + else: |
| 558 | + matches = set(match for match in matches |
| 559 | + if not match.split('.')[-1].startswith('_')) |
| 560 | + return matches |
| 561 | + |
| 562 | + |
527 | 563 | try:
|
528 | 564 | import jedi
|
529 | 565 | except ImportError:
|
@@ -638,8 +674,9 @@ def get_default_completer(mode=SIMPLE):
|
638 | 674 | CumulativeCompleter((GlobalCompletion(mode=mode),
|
639 | 675 | ParameterNameCompletion(mode=mode)),
|
640 | 676 | mode=mode),
|
641 |
| - ArrayItemMembersCompletion(mode=mode), |
642 | 677 | AttrCompletion(mode=mode),
|
| 678 | + ExpressionAttributeCompletion(mode=mode), |
| 679 | + ArrayItemMembersCompletion(mode=mode), |
643 | 680 | )
|
644 | 681 |
|
645 | 682 |
|
|
0 commit comments