You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ORPA-pyOpenRPA/WPy32-3720/python-3.7.2/Lib/site-packages/ptpython/completer.py

167 lines
6.8 KiB

6 years ago
from __future__ import unicode_literals
from prompt_toolkit.completion import Completer, Completion, PathCompleter
from prompt_toolkit.contrib.regular_languages.compiler import compile as compile_grammar
from prompt_toolkit.contrib.regular_languages.completion import GrammarCompleter
from ptpython.utils import get_jedi_script_from_document
import re
__all__ = (
'PythonCompleter',
)
class PythonCompleter(Completer):
"""
Completer for Python code.
"""
def __init__(self, get_globals, get_locals):
super(PythonCompleter, self).__init__()
self.get_globals = get_globals
self.get_locals = get_locals
self._path_completer_cache = None
self._path_completer_grammar_cache = None
@property
def _path_completer(self):
if self._path_completer_cache is None:
self._path_completer_cache = GrammarCompleter(
self._path_completer_grammar, {
'var1': PathCompleter(expanduser=True),
'var2': PathCompleter(expanduser=True),
})
return self._path_completer_cache
@property
def _path_completer_grammar(self):
"""
Return the grammar for matching paths inside strings inside Python
code.
"""
# We make this lazy, because it delays startup time a little bit.
# This way, the grammar is build during the first completion.
if self._path_completer_grammar_cache is None:
self._path_completer_grammar_cache = self._create_path_completer_grammar()
return self._path_completer_grammar_cache
def _create_path_completer_grammar(self):
def unwrapper(text):
return re.sub(r'\\(.)', r'\1', text)
def single_quoted_wrapper(text):
return text.replace('\\', '\\\\').replace("'", "\\'")
def double_quoted_wrapper(text):
return text.replace('\\', '\\\\').replace('"', '\\"')
grammar = r"""
# Text before the current string.
(
[^'"#] | # Not quoted characters.
''' ([^'\\]|'(?!')|''(?!')|\\.])* ''' | # Inside single quoted triple strings
"" " ([^"\\]|"(?!")|""(?!^)|\\.])* "" " | # Inside double quoted triple strings
\#[^\n]*(\n|$) | # Comment.
"(?!"") ([^"\\]|\\.)*" | # Inside double quoted strings.
'(?!'') ([^'\\]|\\.)*' # Inside single quoted strings.
# Warning: The negative lookahead in the above two
# statements is important. If we drop that,
# then the regex will try to interpret every
# triple quoted string also as a single quoted
# string, making this exponentially expensive to
# execute!
)*
# The current string that we're completing.
(
' (?P<var1>([^\n'\\]|\\.)*) | # Inside a single quoted string.
" (?P<var2>([^\n"\\]|\\.)*) # Inside a double quoted string.
)
"""
return compile_grammar(
grammar,
escape_funcs={
'var1': single_quoted_wrapper,
'var2': double_quoted_wrapper,
},
unescape_funcs={
'var1': unwrapper,
'var2': unwrapper,
})
def _complete_path_while_typing(self, document):
char_before_cursor = document.char_before_cursor
return document.text and (
char_before_cursor.isalnum() or char_before_cursor in '/.~')
def _complete_python_while_typing(self, document):
char_before_cursor = document.char_before_cursor
return document.text and (
char_before_cursor.isalnum() or char_before_cursor in '_.')
def get_completions(self, document, complete_event):
"""
Get Python completions.
"""
# Do Path completions
if complete_event.completion_requested or self._complete_path_while_typing(document):
for c in self._path_completer.get_completions(document, complete_event):
yield c
# If we are inside a string, Don't do Jedi completion.
if self._path_completer_grammar.match(document.text_before_cursor):
return
# Do Jedi Python completions.
if complete_event.completion_requested or self._complete_python_while_typing(document):
script = get_jedi_script_from_document(document, self.get_locals(), self.get_globals())
if script:
try:
completions = script.completions()
except TypeError:
# Issue #9: bad syntax causes completions() to fail in jedi.
# https://github.com/jonathanslenders/python-prompt-toolkit/issues/9
pass
except UnicodeDecodeError:
# Issue #43: UnicodeDecodeError on OpenBSD
# https://github.com/jonathanslenders/python-prompt-toolkit/issues/43
pass
except AttributeError:
# Jedi issue #513: https://github.com/davidhalter/jedi/issues/513
pass
except ValueError:
# Jedi issue: "ValueError: invalid \x escape"
pass
except KeyError:
# Jedi issue: "KeyError: u'a_lambda'."
# https://github.com/jonathanslenders/ptpython/issues/89
pass
except IOError:
# Jedi issue: "IOError: No such file or directory."
# https://github.com/jonathanslenders/ptpython/issues/71
pass
except AssertionError:
# In jedi.parser.__init__.py: 227, in remove_last_newline,
# the assertion "newline.value.endswith('\n')" can fail.
pass
except SystemError:
# In jedi.api.helpers.py: 144, in get_stack_at_position
# raise SystemError("This really shouldn't happen. There's a bug in Jedi.")
pass
except NotImplementedError:
# See: https://github.com/jonathanslenders/ptpython/issues/223
pass
except Exception:
# Supress all other Jedi exceptions.
pass
else:
for c in completions:
yield Completion(c.name_with_symbols, len(c.complete) - len(c.name_with_symbols),
display=c.name_with_symbols)