##// END OF EJS Templates
Merge pull request #10761 from ipython/auto-backport-of-pr-10760...
Merge pull request #10761 from ipython/auto-backport-of-pr-10760 Backport PR #10760 on branch 5.x

File last commit:

r23276:046284bd
r23870:827649b4 merge
Show More
ptutils.py
115 lines | 4.1 KiB | text/x-python | PythonLexer
Min RK
Make IPythonPTCompleter(shell) backward-compatible...
r22768 """prompt-toolkit utilities
Everything in this module is a private API,
not to be used outside IPython.
"""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
Thomas Kluyver
Integrate completion into debugger
r22388 import unicodedata
from wcwidth import wcwidth
from IPython.utils.py3compat import PY3
Min RK
explicit TypeError when IPCompleter passed to PTCompleter
r22767 from IPython.core.completer import IPCompleter
Thomas Kluyver
Integrate completion into debugger
r22388 from prompt_toolkit.completion import Completer, Completion
from prompt_toolkit.layout.lexers import Lexer
from prompt_toolkit.layout.lexers import PygmentsLexer
Jonathan Slenders
Use correct Pygments lexers for different %%magics.
r22512 import pygments.lexers as pygments_lexers
Thomas Kluyver
Integrate completion into debugger
r22388
class IPythonPTCompleter(Completer):
"""Adaptor to provide IPython completions to prompt_toolkit"""
Min RK
Backport PR #10223: Fix error tab completing in the debugger...
r23276 def __init__(self, ipy_completer=None, shell=None, patch_stdout=None):
Min RK
Make IPythonPTCompleter(shell) backward-compatible...
r22768 if shell is None and ipy_completer is None:
raise TypeError("Please pass shell=an InteractiveShell instance.")
self._ipy_completer = ipy_completer
Min RK
give PTCompleter InteractiveShell, not Completer...
r22765 self.shell = shell
Min RK
Backport PR #10223: Fix error tab completing in the debugger...
r23276 if patch_stdout is None:
raise TypeError("Please pass patch_stdout")
self.patch_stdout = patch_stdout
Min RK
explicit TypeError when IPCompleter passed to PTCompleter
r22767
Min RK
give PTCompleter InteractiveShell, not Completer...
r22765 @property
def ipy_completer(self):
Min RK
Make IPythonPTCompleter(shell) backward-compatible...
r22768 if self._ipy_completer:
return self._ipy_completer
else:
return self.shell.Completer
Thomas Kluyver
Integrate completion into debugger
r22388
def get_completions(self, document, complete_event):
if not document.current_line.strip():
return
Min RK
Backport PR #10153: Use prompt_toolkit's patch_stdout_context when finding completions...
r23246 # Some bits of our completion system may print stuff (e.g. if a module
# is imported). This context manager ensures that doesn't interfere with
# the prompt.
Min RK
Backport PR #10223: Fix error tab completing in the debugger...
r23276 with self.patch_stdout():
Min RK
Backport PR #10153: Use prompt_toolkit's patch_stdout_context when finding completions...
r23246 used, matches = self.ipy_completer.complete(
line_buffer=document.current_line,
cursor_pos=document.cursor_position_col
)
Thomas Kluyver
Integrate completion into debugger
r22388 start_pos = -len(used)
for m in matches:
Thomas Kluyver
Protect against completion machinery returning an empty string...
r22445 if not m:
# Guard against completion machinery giving us an empty string.
continue
Thomas Kluyver
Integrate completion into debugger
r22388 m = unicodedata.normalize('NFC', m)
# When the first character of the completion has a zero length,
# then it's probably a decomposed unicode character. E.g. caused by
# the "\dot" completion. Try to compose again with the previous
# character.
if wcwidth(m[0]) == 0:
if document.cursor_position + start_pos > 0:
char_before = document.text[document.cursor_position + start_pos - 1]
m = unicodedata.normalize('NFC', char_before + m)
# Yield the modified completion instead, if this worked.
if wcwidth(m[0:1]) == 1:
yield Completion(m, start_position=start_pos - 1)
continue
# TODO: Use Jedi to determine meta_text
# (Jedi currently has a bug that results in incorrect information.)
# meta_text = ''
# yield Completion(m, start_position=start_pos,
# display_meta=meta_text)
yield Completion(m, start_position=start_pos)
class IPythonPTLexer(Lexer):
"""
Wrapper around PythonLexer and BashLexer.
"""
def __init__(self):
Jonathan Slenders
Use correct Pygments lexers for different %%magics.
r22512 l = pygments_lexers
self.python_lexer = PygmentsLexer(l.Python3Lexer if PY3 else l.PythonLexer)
self.shell_lexer = PygmentsLexer(l.BashLexer)
self.magic_lexers = {
'HTML': PygmentsLexer(l.HtmlLexer),
'html': PygmentsLexer(l.HtmlLexer),
'javascript': PygmentsLexer(l.JavascriptLexer),
'js': PygmentsLexer(l.JavascriptLexer),
'perl': PygmentsLexer(l.PerlLexer),
'ruby': PygmentsLexer(l.RubyLexer),
'latex': PygmentsLexer(l.TexLexer),
}
Thomas Kluyver
Integrate completion into debugger
r22388
def lex_document(self, cli, document):
Jonathan Slenders
Use correct Pygments lexers for different %%magics.
r22512 text = document.text.lstrip()
lexer = self.python_lexer
if text.startswith('!') or text.startswith('%%bash'):
lexer = self.shell_lexer
elif text.startswith('%%'):
for magic, l in self.magic_lexers.items():
if text.startswith('%%' + magic):
lexer = l
break
return lexer.lex_document(cli, document)