1
1
import ast
2
2
import keyword
3
3
import re
4
- from typing import TYPE_CHECKING , Any , Dict , Iterable , List
4
+ from enum import Enum
5
+ from typing import TYPE_CHECKING , Any , Callable , Dict , Iterable , List , Optional
5
6
6
7
from prompt_toolkit .completion import (
7
8
CompleteEvent ,
12
13
from prompt_toolkit .contrib .regular_languages .compiler import compile as compile_grammar
13
14
from prompt_toolkit .contrib .regular_languages .completion import GrammarCompleter
14
15
from prompt_toolkit .document import Document
16
+ from prompt_toolkit .formatted_text import fragment_list_to_text , to_formatted_text
15
17
16
18
from ptpython .utils import get_jedi_script_from_document
17
19
18
20
if TYPE_CHECKING :
19
21
from prompt_toolkit .contrib .regular_languages .compiler import _CompiledGrammar
20
22
21
- __all__ = ["PythonCompleter" ]
23
+ __all__ = ["PythonCompleter" , "CompletePrivateAttributes" , "HidePrivateCompleter" ]
24
+
25
+
26
+ class CompletePrivateAttributes (Enum ):
27
+ """
28
+ Should we display private attributes in the completion pop-up?
29
+ """
30
+
31
+ NEVER = "NEVER"
32
+ IF_NO_PUBLIC = "IF_NO_PUBLIC"
33
+ ALWAYS = "ALWAYS"
22
34
23
35
24
36
class PythonCompleter (Completer ):
25
37
"""
26
38
Completer for Python code.
27
39
"""
28
40
29
- def __init__ (self , get_globals , get_locals , get_enable_dictionary_completion ):
41
+ def __init__ (
42
+ self , get_globals , get_locals , get_enable_dictionary_completion
43
+ ) -> None :
30
44
super ().__init__ ()
31
45
32
46
self .get_globals = get_globals
@@ -35,8 +49,8 @@ def __init__(self, get_globals, get_locals, get_enable_dictionary_completion):
35
49
36
50
self .dictionary_completer = DictionaryCompleter (get_globals , get_locals )
37
51
38
- self ._path_completer_cache = None
39
- self ._path_completer_grammar_cache = None
52
+ self ._path_completer_cache : Optional [ GrammarCompleter ] = None
53
+ self ._path_completer_grammar_cache : Optional [ "_CompiledGrammar" ] = None
40
54
41
55
@property
42
56
def _path_completer (self ) -> GrammarCompleter :
@@ -158,7 +172,7 @@ def get_completions(
158
172
159
173
if script :
160
174
try :
161
- completions = script .completions ()
175
+ jedi_completions = script .completions ()
162
176
except TypeError :
163
177
# Issue #9: bad syntax causes completions() to fail in jedi.
164
178
# https://github.com/jonathanslenders/python-prompt-toolkit/issues/9
@@ -196,12 +210,12 @@ def get_completions(
196
210
# Supress all other Jedi exceptions.
197
211
pass
198
212
else :
199
- for c in completions :
213
+ for jc in jedi_completions :
200
214
yield Completion (
201
- c .name_with_symbols ,
202
- len (c .complete ) - len (c .name_with_symbols ),
203
- display = c .name_with_symbols ,
204
- style = _get_style_for_name (c .name_with_symbols ),
215
+ jc .name_with_symbols ,
216
+ len (jc .complete ) - len (jc .name_with_symbols ),
217
+ display = jc .name_with_symbols ,
218
+ style = _get_style_for_name (jc .name_with_symbols ),
205
219
)
206
220
207
221
@@ -464,6 +478,49 @@ def sort_key(name: str):
464
478
return sorted (names , key = sort_key )
465
479
466
480
481
+ class HidePrivateCompleter (Completer ):
482
+ """
483
+ Wrapper around completer that hides private fields, deponding on whether or
484
+ not public fields are shown.
485
+
486
+ (The reason this is implemented as a `Completer` wrapper is because this
487
+ way it works also with `FuzzyCompleter`.)
488
+ """
489
+
490
+ def __init__ (
491
+ self ,
492
+ completer : Completer ,
493
+ complete_private_attributes : Callable [[], CompletePrivateAttributes ],
494
+ ) -> None :
495
+ self .completer = completer
496
+ self .complete_private_attributes = complete_private_attributes
497
+
498
+ def get_completions (
499
+ self , document : Document , complete_event : CompleteEvent
500
+ ) -> Iterable [Completion ]:
501
+
502
+ completions = list (self .completer .get_completions (document , complete_event ))
503
+ complete_private_attributes = self .complete_private_attributes ()
504
+ hide_private = False
505
+
506
+ def is_private (completion : Completion ) -> bool :
507
+ text = fragment_list_to_text (to_formatted_text (completion .display ))
508
+ return text .startswith ("_" )
509
+
510
+ if complete_private_attributes == CompletePrivateAttributes .NEVER :
511
+ hide_private = True
512
+
513
+ elif complete_private_attributes == CompletePrivateAttributes .IF_NO_PUBLIC :
514
+ hide_private = any (not is_private (completion ) for completion in completions )
515
+
516
+ if hide_private :
517
+ completions = [
518
+ completion for completion in completions if not is_private (completion )
519
+ ]
520
+
521
+ return completions
522
+
523
+
467
524
class ReprFailedError (Exception ):
468
525
" Raised when the repr() call in `DictionaryCompleter` fails. "
469
526
0 commit comments