Show More
@@ -0,0 +1,73 b'' | |||||
|
1 | from IPython.core.debugger import Pdb | |||
|
2 | ||||
|
3 | from IPython.core.completer import IPCompleter | |||
|
4 | from .ptutils import IPythonPTCompleter | |||
|
5 | ||||
|
6 | from prompt_toolkit.token import Token | |||
|
7 | from prompt_toolkit.shortcuts import create_prompt_application | |||
|
8 | from prompt_toolkit.interface import CommandLineInterface | |||
|
9 | from prompt_toolkit.enums import EditingMode | |||
|
10 | ||||
|
11 | class TerminalPdb(Pdb): | |||
|
12 | def __init__(self, *args, **kwargs): | |||
|
13 | Pdb.__init__(self, *args, **kwargs) | |||
|
14 | self._ptcomp = None | |||
|
15 | self.pt_init() | |||
|
16 | ||||
|
17 | def pt_init(self): | |||
|
18 | def get_prompt_tokens(cli): | |||
|
19 | return [(Token.Prompt, self.prompt)] | |||
|
20 | ||||
|
21 | if self._ptcomp is None: | |||
|
22 | compl = IPCompleter(shell=self.shell, | |||
|
23 | namespace={}, | |||
|
24 | global_namespace={}, | |||
|
25 | use_readline=False, | |||
|
26 | parent=self.shell, | |||
|
27 | ) | |||
|
28 | self._ptcomp = IPythonPTCompleter(compl) | |||
|
29 | ||||
|
30 | self._pt_app = create_prompt_application( | |||
|
31 | editing_mode=getattr(EditingMode, self.shell.editing_mode.upper()), | |||
|
32 | history=self.shell.debugger_history, | |||
|
33 | completer= self._ptcomp, | |||
|
34 | enable_history_search=True, | |||
|
35 | mouse_support=self.shell.mouse_support, | |||
|
36 | get_prompt_tokens=get_prompt_tokens | |||
|
37 | ) | |||
|
38 | self.pt_cli = CommandLineInterface(self._pt_app, eventloop=self.shell._eventloop) | |||
|
39 | ||||
|
40 | def cmdloop(self, intro=None): | |||
|
41 | """Repeatedly issue a prompt, accept input, parse an initial prefix | |||
|
42 | off the received input, and dispatch to action methods, passing them | |||
|
43 | the remainder of the line as argument. | |||
|
44 | ||||
|
45 | override the same methods from cmd.Cmd to provide prompt toolkit replacement. | |||
|
46 | """ | |||
|
47 | if not self.use_rawinput: | |||
|
48 | raise ValueError('Sorry ipdb does not support use_rawinput=False') | |||
|
49 | ||||
|
50 | self.preloop() | |||
|
51 | ||||
|
52 | try: | |||
|
53 | if intro is not None: | |||
|
54 | self.intro = intro | |||
|
55 | if self.intro: | |||
|
56 | self.stdout.write(str(self.intro)+"\n") | |||
|
57 | stop = None | |||
|
58 | while not stop: | |||
|
59 | if self.cmdqueue: | |||
|
60 | line = self.cmdqueue.pop(0) | |||
|
61 | else: | |||
|
62 | self._ptcomp.ipy_completer.namespace = self.curframe_locals | |||
|
63 | self._ptcomp.ipy_completer.global_namespace = self.curframe.f_globals | |||
|
64 | try: | |||
|
65 | line = self.pt_cli.run(reset_current_buffer=True).text | |||
|
66 | except EOFError: | |||
|
67 | line = 'EOF' | |||
|
68 | line = self.precmd(line) | |||
|
69 | stop = self.onecmd(line) | |||
|
70 | stop = self.postcmd(stop, line) | |||
|
71 | self.postloop() | |||
|
72 | except Exception: | |||
|
73 | raise |
@@ -0,0 +1,62 b'' | |||||
|
1 | import unicodedata | |||
|
2 | from wcwidth import wcwidth | |||
|
3 | ||||
|
4 | from IPython.utils.py3compat import PY3 | |||
|
5 | ||||
|
6 | from prompt_toolkit.completion import Completer, Completion | |||
|
7 | from prompt_toolkit.layout.lexers import Lexer | |||
|
8 | from prompt_toolkit.layout.lexers import PygmentsLexer | |||
|
9 | ||||
|
10 | from pygments.lexers import Python3Lexer, BashLexer, PythonLexer | |||
|
11 | ||||
|
12 | class IPythonPTCompleter(Completer): | |||
|
13 | """Adaptor to provide IPython completions to prompt_toolkit""" | |||
|
14 | def __init__(self, ipy_completer): | |||
|
15 | self.ipy_completer = ipy_completer | |||
|
16 | ||||
|
17 | def get_completions(self, document, complete_event): | |||
|
18 | if not document.current_line.strip(): | |||
|
19 | return | |||
|
20 | ||||
|
21 | used, matches = self.ipy_completer.complete( | |||
|
22 | line_buffer=document.current_line, | |||
|
23 | cursor_pos=document.cursor_position_col | |||
|
24 | ) | |||
|
25 | start_pos = -len(used) | |||
|
26 | for m in matches: | |||
|
27 | m = unicodedata.normalize('NFC', m) | |||
|
28 | ||||
|
29 | # When the first character of the completion has a zero length, | |||
|
30 | # then it's probably a decomposed unicode character. E.g. caused by | |||
|
31 | # the "\dot" completion. Try to compose again with the previous | |||
|
32 | # character. | |||
|
33 | if wcwidth(m[0]) == 0: | |||
|
34 | if document.cursor_position + start_pos > 0: | |||
|
35 | char_before = document.text[document.cursor_position + start_pos - 1] | |||
|
36 | m = unicodedata.normalize('NFC', char_before + m) | |||
|
37 | ||||
|
38 | # Yield the modified completion instead, if this worked. | |||
|
39 | if wcwidth(m[0:1]) == 1: | |||
|
40 | yield Completion(m, start_position=start_pos - 1) | |||
|
41 | continue | |||
|
42 | ||||
|
43 | # TODO: Use Jedi to determine meta_text | |||
|
44 | # (Jedi currently has a bug that results in incorrect information.) | |||
|
45 | # meta_text = '' | |||
|
46 | # yield Completion(m, start_position=start_pos, | |||
|
47 | # display_meta=meta_text) | |||
|
48 | yield Completion(m, start_position=start_pos) | |||
|
49 | ||||
|
50 | class IPythonPTLexer(Lexer): | |||
|
51 | """ | |||
|
52 | Wrapper around PythonLexer and BashLexer. | |||
|
53 | """ | |||
|
54 | def __init__(self): | |||
|
55 | self.python_lexer = PygmentsLexer(Python3Lexer if PY3 else PythonLexer) | |||
|
56 | self.shell_lexer = PygmentsLexer(BashLexer) | |||
|
57 | ||||
|
58 | def lex_document(self, cli, document): | |||
|
59 | if document.text.startswith('!'): | |||
|
60 | return self.shell_lexer.lex_document(cli, document) | |||
|
61 | else: | |||
|
62 | return self.python_lexer.lex_document(cli, document) |
@@ -652,6 +652,9 b' class IPCompleter(Completer):' | |||||
652 | self.dict_key_matches, |
|
652 | self.dict_key_matches, | |
653 | ] |
|
653 | ] | |
654 |
|
654 | |||
|
655 | # This is set externally by InteractiveShell | |||
|
656 | self.custom_completers = None | |||
|
657 | ||||
655 | def all_completions(self, text): |
|
658 | def all_completions(self, text): | |
656 | """ |
|
659 | """ | |
657 | Wrapper around the complete method for the benefit of emacs. |
|
660 | Wrapper around the complete method for the benefit of emacs. | |
@@ -1072,6 +1075,9 b' class IPCompleter(Completer):' | |||||
1072 | return u'', [] |
|
1075 | return u'', [] | |
1073 |
|
1076 | |||
1074 | def dispatch_custom_completer(self, text): |
|
1077 | def dispatch_custom_completer(self, text): | |
|
1078 | if not self.custom_completers: | |||
|
1079 | return | |||
|
1080 | ||||
1075 | line = self.line_buffer |
|
1081 | line = self.line_buffer | |
1076 | if not line.strip(): |
|
1082 | if not line.strip(): | |
1077 | return None |
|
1083 | return None |
@@ -37,6 +37,7 b' from IPython.utils import coloransi, py3compat' | |||||
37 | from IPython.core.excolors import exception_colors |
|
37 | from IPython.core.excolors import exception_colors | |
38 | from IPython.testing.skipdoctest import skip_doctest |
|
38 | from IPython.testing.skipdoctest import skip_doctest | |
39 |
|
39 | |||
|
40 | ||||
40 | prompt = 'ipdb> ' |
|
41 | prompt = 'ipdb> ' | |
41 |
|
42 | |||
42 | #We have to check this directly from sys.argv, config struct not yet available |
|
43 | #We have to check this directly from sys.argv, config struct not yet available | |
@@ -120,12 +121,6 b' class Tracer(object):' | |||||
120 | sys.excepthook = functools.partial(BdbQuit_excepthook, |
|
121 | sys.excepthook = functools.partial(BdbQuit_excepthook, | |
121 | excepthook=sys.excepthook) |
|
122 | excepthook=sys.excepthook) | |
122 | def_colors = 'NoColor' |
|
123 | def_colors = 'NoColor' | |
123 | try: |
|
|||
124 | # Limited tab completion support |
|
|||
125 | import readline |
|
|||
126 | readline.parse_and_bind('tab: complete') |
|
|||
127 | except ImportError: |
|
|||
128 | pass |
|
|||
129 | else: |
|
124 | else: | |
130 | # In ipython, we use its custom exception handler mechanism |
|
125 | # In ipython, we use its custom exception handler mechanism | |
131 | def_colors = ip.colors |
|
126 | def_colors = ip.colors | |
@@ -245,31 +240,17 b' class Pdb(OldPdb, object):' | |||||
245 | self.parser = PyColorize.Parser() |
|
240 | self.parser = PyColorize.Parser() | |
246 |
|
241 | |||
247 | # Set the prompt - the default prompt is '(Pdb)' |
|
242 | # Set the prompt - the default prompt is '(Pdb)' | |
248 | Colors = cst.active_colors |
|
|||
249 | if color_scheme == 'NoColor': |
|
|||
250 |
|
|
243 | self.prompt = prompt | |
251 | else: |
|
|||
252 | # The colour markers are wrapped by bytes 01 and 02 so that readline |
|
|||
253 | # can calculate the width. |
|
|||
254 | self.prompt = u'\x01%s\x02%s\x01%s\x02' % (Colors.prompt, prompt, Colors.Normal) |
|
|||
255 |
|
244 | |||
256 | def set_colors(self, scheme): |
|
245 | def set_colors(self, scheme): | |
257 | """Shorthand access to the color table scheme selector method.""" |
|
246 | """Shorthand access to the color table scheme selector method.""" | |
258 | self.color_scheme_table.set_active_scheme(scheme) |
|
247 | self.color_scheme_table.set_active_scheme(scheme) | |
259 |
|
248 | |||
260 | def interaction(self, frame, traceback): |
|
249 | def interaction(self, frame, traceback): | |
261 | self.shell.set_completer_frame(frame) |
|
|||
262 | while True: |
|
|||
263 |
|
|
250 | try: | |
264 |
|
|
251 | OldPdb.interaction(self, frame, traceback) | |
265 | break |
|
|||
266 |
|
|
252 | except KeyboardInterrupt: | |
267 |
|
|
253 | sys.stdout.write('\n' + self.shell.get_exception_only()) | |
268 | break |
|
|||
269 | finally: |
|
|||
270 | # Pdb sets readline delimiters, so set them back to our own |
|
|||
271 | if self.shell.readline is not None: |
|
|||
272 | self.shell.readline.set_completer_delims(self.shell.readline_delims) |
|
|||
273 |
|
254 | |||
274 | def parseline(self, line): |
|
255 | def parseline(self, line): | |
275 | if line.startswith("!!"): |
|
256 | if line.startswith("!!"): | |
@@ -284,18 +265,15 b' class Pdb(OldPdb, object):' | |||||
284 |
|
265 | |||
285 | def new_do_up(self, arg): |
|
266 | def new_do_up(self, arg): | |
286 | OldPdb.do_up(self, arg) |
|
267 | OldPdb.do_up(self, arg) | |
287 | self.shell.set_completer_frame(self.curframe) |
|
|||
288 | do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up) |
|
268 | do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up) | |
289 |
|
269 | |||
290 | def new_do_down(self, arg): |
|
270 | def new_do_down(self, arg): | |
291 | OldPdb.do_down(self, arg) |
|
271 | OldPdb.do_down(self, arg) | |
292 | self.shell.set_completer_frame(self.curframe) |
|
|||
293 |
|
272 | |||
294 | do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down) |
|
273 | do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down) | |
295 |
|
274 | |||
296 | def new_do_frame(self, arg): |
|
275 | def new_do_frame(self, arg): | |
297 | OldPdb.do_frame(self, arg) |
|
276 | OldPdb.do_frame(self, arg) | |
298 | self.shell.set_completer_frame(self.curframe) |
|
|||
299 |
|
277 | |||
300 | def new_do_quit(self, arg): |
|
278 | def new_do_quit(self, arg): | |
301 |
|
279 | |||
@@ -312,9 +290,6 b' class Pdb(OldPdb, object):' | |||||
312 | self.msg("Restart doesn't make sense here. Using 'quit' instead.") |
|
290 | self.msg("Restart doesn't make sense here. Using 'quit' instead.") | |
313 | return self.do_quit(arg) |
|
291 | return self.do_quit(arg) | |
314 |
|
292 | |||
315 | def postloop(self): |
|
|||
316 | self.shell.set_completer_frame(None) |
|
|||
317 |
|
||||
318 | def print_stack_trace(self, context=None): |
|
293 | def print_stack_trace(self, context=None): | |
319 | if context is None: |
|
294 | if context is None: | |
320 | context = self.context |
|
295 | context = self.context |
@@ -42,6 +42,7 b' from IPython.core.autocall import ExitAutocall' | |||||
42 | from IPython.core.builtin_trap import BuiltinTrap |
|
42 | from IPython.core.builtin_trap import BuiltinTrap | |
43 | from IPython.core.events import EventManager, available_events |
|
43 | from IPython.core.events import EventManager, available_events | |
44 | from IPython.core.compilerop import CachingCompiler, check_linecache_ipython |
|
44 | from IPython.core.compilerop import CachingCompiler, check_linecache_ipython | |
|
45 | from IPython.core.debugger import Pdb | |||
45 | from IPython.core.display_trap import DisplayTrap |
|
46 | from IPython.core.display_trap import DisplayTrap | |
46 | from IPython.core.displayhook import DisplayHook |
|
47 | from IPython.core.displayhook import DisplayHook | |
47 | from IPython.core.displaypub import DisplayPublisher |
|
48 | from IPython.core.displaypub import DisplayPublisher | |
@@ -1584,6 +1585,8 b' class InteractiveShell(SingletonConfigurable):' | |||||
1584 | # Things related to exception handling and tracebacks (not debugging) |
|
1585 | # Things related to exception handling and tracebacks (not debugging) | |
1585 | #------------------------------------------------------------------------- |
|
1586 | #------------------------------------------------------------------------- | |
1586 |
|
1587 | |||
|
1588 | debugger_cls = Pdb | |||
|
1589 | ||||
1587 | def init_traceback_handlers(self, custom_exceptions): |
|
1590 | def init_traceback_handlers(self, custom_exceptions): | |
1588 | # Syntax error handler. |
|
1591 | # Syntax error handler. | |
1589 | self.SyntaxTB = ultratb.SyntaxTB(color_scheme='NoColor') |
|
1592 | self.SyntaxTB = ultratb.SyntaxTB(color_scheme='NoColor') | |
@@ -1594,7 +1597,8 b' class InteractiveShell(SingletonConfigurable):' | |||||
1594 | self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain', |
|
1597 | self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain', | |
1595 | color_scheme='NoColor', |
|
1598 | color_scheme='NoColor', | |
1596 | tb_offset = 1, |
|
1599 | tb_offset = 1, | |
1597 |
check_cache=check_linecache_ipython |
|
1600 | check_cache=check_linecache_ipython, | |
|
1601 | debugger_cls=self.debugger_cls) | |||
1598 |
|
1602 | |||
1599 | # The instance will store a pointer to the system-wide exception hook, |
|
1603 | # The instance will store a pointer to the system-wide exception hook, | |
1600 | # so that runtime code (such as magics) can access it. This is because |
|
1604 | # so that runtime code (such as magics) can access it. This is because |
@@ -809,7 +809,7 b' class VerboseTB(TBTools):' | |||||
809 |
|
809 | |||
810 | def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None, |
|
810 | def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None, | |
811 | tb_offset=0, long_header=False, include_vars=True, |
|
811 | tb_offset=0, long_header=False, include_vars=True, | |
812 | check_cache=None): |
|
812 | check_cache=None, debugger_cls = None): | |
813 | """Specify traceback offset, headers and color scheme. |
|
813 | """Specify traceback offset, headers and color scheme. | |
814 |
|
814 | |||
815 | Define how many frames to drop from the tracebacks. Calling it with |
|
815 | Define how many frames to drop from the tracebacks. Calling it with | |
@@ -830,6 +830,8 b' class VerboseTB(TBTools):' | |||||
830 | check_cache = linecache.checkcache |
|
830 | check_cache = linecache.checkcache | |
831 | self.check_cache = check_cache |
|
831 | self.check_cache = check_cache | |
832 |
|
832 | |||
|
833 | self.debugger_cls = debugger_cls or debugger.Pdb | |||
|
834 | ||||
833 | def format_records(self, records, last_unique, recursion_repeat): |
|
835 | def format_records(self, records, last_unique, recursion_repeat): | |
834 | """Format the stack frames of the traceback""" |
|
836 | """Format the stack frames of the traceback""" | |
835 | frames = [] |
|
837 | frames = [] | |
@@ -1217,7 +1219,7 b' class VerboseTB(TBTools):' | |||||
1217 |
|
1219 | |||
1218 | if force or self.call_pdb: |
|
1220 | if force or self.call_pdb: | |
1219 | if self.pdb is None: |
|
1221 | if self.pdb is None: | |
1220 |
self.pdb = |
|
1222 | self.pdb = self.debugger_cls( | |
1221 | self.color_scheme_table.active_scheme_name) |
|
1223 | self.color_scheme_table.active_scheme_name) | |
1222 | # the system displayhook may have changed, restore the original |
|
1224 | # the system displayhook may have changed, restore the original | |
1223 | # for pdb |
|
1225 | # for pdb | |
@@ -1278,7 +1280,7 b' class FormattedTB(VerboseTB, ListTB):' | |||||
1278 | def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False, |
|
1280 | def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False, | |
1279 | ostream=None, |
|
1281 | ostream=None, | |
1280 | tb_offset=0, long_header=False, include_vars=False, |
|
1282 | tb_offset=0, long_header=False, include_vars=False, | |
1281 | check_cache=None): |
|
1283 | check_cache=None, debugger_cls=None): | |
1282 |
|
1284 | |||
1283 | # NEVER change the order of this list. Put new modes at the end: |
|
1285 | # NEVER change the order of this list. Put new modes at the end: | |
1284 | self.valid_modes = ['Plain', 'Context', 'Verbose'] |
|
1286 | self.valid_modes = ['Plain', 'Context', 'Verbose'] | |
@@ -1287,7 +1289,7 b' class FormattedTB(VerboseTB, ListTB):' | |||||
1287 | VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb, |
|
1289 | VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb, | |
1288 | ostream=ostream, tb_offset=tb_offset, |
|
1290 | ostream=ostream, tb_offset=tb_offset, | |
1289 | long_header=long_header, include_vars=include_vars, |
|
1291 | long_header=long_header, include_vars=include_vars, | |
1290 | check_cache=check_cache) |
|
1292 | check_cache=check_cache, debugger_cls=debugger_cls) | |
1291 |
|
1293 | |||
1292 | # Different types of tracebacks are joined with different separators to |
|
1294 | # Different types of tracebacks are joined with different separators to | |
1293 | # form a single string. They are taken from this dict |
|
1295 | # form a single string. They are taken from this dict |
@@ -4,18 +4,15 b' from __future__ import print_function' | |||||
4 | import os |
|
4 | import os | |
5 | import sys |
|
5 | import sys | |
6 | import signal |
|
6 | import signal | |
7 | import unicodedata |
|
|||
8 | from warnings import warn |
|
7 | from warnings import warn | |
9 | from wcwidth import wcwidth |
|
|||
10 |
|
8 | |||
11 | from IPython.core.error import TryNext |
|
9 | from IPython.core.error import TryNext | |
12 | from IPython.core.interactiveshell import InteractiveShell |
|
10 | from IPython.core.interactiveshell import InteractiveShell | |
13 |
from IPython.utils.py3compat import |
|
11 | from IPython.utils.py3compat import cast_unicode_py2, input | |
14 | from IPython.utils.terminal import toggle_set_term_title, set_term_title |
|
12 | from IPython.utils.terminal import toggle_set_term_title, set_term_title | |
15 | from IPython.utils.process import abbrev_cwd |
|
13 | from IPython.utils.process import abbrev_cwd | |
16 | from traitlets import Bool, Unicode, Dict, Integer, observe |
|
14 | from traitlets import Bool, Unicode, Dict, Integer, observe | |
17 |
|
15 | |||
18 | from prompt_toolkit.completion import Completer, Completion |
|
|||
19 | from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER, EditingMode |
|
16 | from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER, EditingMode | |
20 | from prompt_toolkit.filters import HasFocus, HasSelection, Condition, ViInsertMode, EmacsInsertMode, IsDone |
|
17 | from prompt_toolkit.filters import HasFocus, HasSelection, Condition, ViInsertMode, EmacsInsertMode, IsDone | |
21 | from prompt_toolkit.history import InMemoryHistory |
|
18 | from prompt_toolkit.history import InMemoryHistory | |
@@ -23,70 +20,16 b' from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop' | |||||
23 | from prompt_toolkit.interface import CommandLineInterface |
|
20 | from prompt_toolkit.interface import CommandLineInterface | |
24 | from prompt_toolkit.key_binding.manager import KeyBindingManager |
|
21 | from prompt_toolkit.key_binding.manager import KeyBindingManager | |
25 | from prompt_toolkit.keys import Keys |
|
22 | from prompt_toolkit.keys import Keys | |
26 | from prompt_toolkit.layout.lexers import Lexer |
|
|||
27 | from prompt_toolkit.layout.lexers import PygmentsLexer |
|
|||
28 | from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor |
|
23 | from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor | |
29 | from prompt_toolkit.styles import PygmentsStyle, DynamicStyle |
|
24 | from prompt_toolkit.styles import PygmentsStyle, DynamicStyle | |
30 |
|
25 | |||
31 | from pygments.styles import get_style_by_name, get_all_styles |
|
26 | from pygments.styles import get_style_by_name, get_all_styles | |
32 | from pygments.lexers import Python3Lexer, BashLexer, PythonLexer |
|
|||
33 | from pygments.token import Token |
|
27 | from pygments.token import Token | |
34 |
|
28 | |||
|
29 | from .debugger import TerminalPdb | |||
35 | from .pt_inputhooks import get_inputhook_func |
|
30 | from .pt_inputhooks import get_inputhook_func | |
36 | from .interactiveshell import get_default_editor, TerminalMagics |
|
31 | from .interactiveshell import get_default_editor, TerminalMagics | |
37 |
|
32 | from .ptutils import IPythonPTCompleter, IPythonPTLexer | ||
38 |
|
||||
39 | class IPythonPTCompleter(Completer): |
|
|||
40 | """Adaptor to provide IPython completions to prompt_toolkit""" |
|
|||
41 | def __init__(self, ipy_completer): |
|
|||
42 | self.ipy_completer = ipy_completer |
|
|||
43 |
|
||||
44 | def get_completions(self, document, complete_event): |
|
|||
45 | if not document.current_line.strip(): |
|
|||
46 | return |
|
|||
47 |
|
||||
48 | used, matches = self.ipy_completer.complete( |
|
|||
49 | line_buffer=document.current_line, |
|
|||
50 | cursor_pos=document.cursor_position_col |
|
|||
51 | ) |
|
|||
52 | start_pos = -len(used) |
|
|||
53 | for m in matches: |
|
|||
54 | m = unicodedata.normalize('NFC', m) |
|
|||
55 |
|
||||
56 | # When the first character of the completion has a zero length, |
|
|||
57 | # then it's probably a decomposed unicode character. E.g. caused by |
|
|||
58 | # the "\dot" completion. Try to compose again with the previous |
|
|||
59 | # character. |
|
|||
60 | if wcwidth(m[0]) == 0: |
|
|||
61 | if document.cursor_position + start_pos > 0: |
|
|||
62 | char_before = document.text[document.cursor_position + start_pos - 1] |
|
|||
63 | m = unicodedata.normalize('NFC', char_before + m) |
|
|||
64 |
|
||||
65 | # Yield the modified completion instead, if this worked. |
|
|||
66 | if wcwidth(m[0:1]) == 1: |
|
|||
67 | yield Completion(m, start_position=start_pos - 1) |
|
|||
68 | continue |
|
|||
69 |
|
||||
70 | # TODO: Use Jedi to determine meta_text |
|
|||
71 | # (Jedi currently has a bug that results in incorrect information.) |
|
|||
72 | # meta_text = '' |
|
|||
73 | # yield Completion(m, start_position=start_pos, |
|
|||
74 | # display_meta=meta_text) |
|
|||
75 | yield Completion(m, start_position=start_pos) |
|
|||
76 |
|
||||
77 | class IPythonPTLexer(Lexer): |
|
|||
78 | """ |
|
|||
79 | Wrapper around PythonLexer and BashLexer. |
|
|||
80 | """ |
|
|||
81 | def __init__(self): |
|
|||
82 | self.python_lexer = PygmentsLexer(Python3Lexer if PY3 else PythonLexer) |
|
|||
83 | self.shell_lexer = PygmentsLexer(BashLexer) |
|
|||
84 |
|
||||
85 | def lex_document(self, cli, document): |
|
|||
86 | if document.text.startswith('!'): |
|
|||
87 | return self.shell_lexer.lex_document(cli, document) |
|
|||
88 | else: |
|
|||
89 | return self.python_lexer.lex_document(cli, document) |
|
|||
90 |
|
33 | |||
91 |
|
34 | |||
92 | class TerminalInteractiveShell(InteractiveShell): |
|
35 | class TerminalInteractiveShell(InteractiveShell): | |
@@ -100,6 +43,8 b' class TerminalInteractiveShell(InteractiveShell):' | |||||
100 | self._update_layout() |
|
43 | self._update_layout() | |
101 |
|
44 | |||
102 | pt_cli = None |
|
45 | pt_cli = None | |
|
46 | debugger_history = None | |||
|
47 | debugger_cls = TerminalPdb | |||
103 |
|
48 | |||
104 | autoedit_syntax = Bool(False, |
|
49 | autoedit_syntax = Bool(False, | |
105 | help="auto editing of files with syntax errors.", |
|
50 | help="auto editing of files with syntax errors.", | |
@@ -362,6 +307,8 b' class TerminalInteractiveShell(InteractiveShell):' | |||||
362 | self.init_term_title() |
|
307 | self.init_term_title() | |
363 | self.keep_running = True |
|
308 | self.keep_running = True | |
364 |
|
309 | |||
|
310 | self.debugger_history = InMemoryHistory() | |||
|
311 | ||||
365 | def ask_exit(self): |
|
312 | def ask_exit(self): | |
366 | self.keep_running = False |
|
313 | self.keep_running = False | |
367 |
|
314 |
General Comments 0
You need to be logged in to leave comments.
Login now