11import ast
22import keyword
33import 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
56
67from prompt_toolkit .completion import (
78 CompleteEvent ,
1213from prompt_toolkit .contrib .regular_languages .compiler import compile as compile_grammar
1314from prompt_toolkit .contrib .regular_languages .completion import GrammarCompleter
1415from prompt_toolkit .document import Document
16+ from prompt_toolkit .formatted_text import fragment_list_to_text , to_formatted_text
1517
1618from ptpython .utils import get_jedi_script_from_document
1719
1820if TYPE_CHECKING :
1921 from prompt_toolkit .contrib .regular_languages .compiler import _CompiledGrammar
2022
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"
2234
2335
2436class PythonCompleter (Completer ):
2537 """
2638 Completer for Python code.
2739 """
2840
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 :
3044 super ().__init__ ()
3145
3246 self .get_globals = get_globals
@@ -35,8 +49,8 @@ def __init__(self, get_globals, get_locals, get_enable_dictionary_completion):
3549
3650 self .dictionary_completer = DictionaryCompleter (get_globals , get_locals )
3751
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
4054
4155 @property
4256 def _path_completer (self ) -> GrammarCompleter :
@@ -158,7 +172,7 @@ def get_completions(
158172
159173 if script :
160174 try :
161- completions = script .completions ()
175+ jedi_completions = script .completions ()
162176 except TypeError :
163177 # Issue #9: bad syntax causes completions() to fail in jedi.
164178 # https://github.com/jonathanslenders/python-prompt-toolkit/issues/9
@@ -196,12 +210,12 @@ def get_completions(
196210 # Supress all other Jedi exceptions.
197211 pass
198212 else :
199- for c in completions :
213+ for jc in jedi_completions :
200214 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 ),
205219 )
206220
207221
@@ -464,6 +478,49 @@ def sort_key(name: str):
464478 return sorted (names , key = sort_key )
465479
466480
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+
467524class ReprFailedError (Exception ):
468525 " Raised when the repr() call in `DictionaryCompleter` fails. "
469526
0 commit comments