##// END OF EJS Templates
Add prompt toolkit 3 compatibility to ipdb...
Matthias Bussonnier -
Show More
@@ -1,120 +1,126 b''
1 1 import signal
2 2 import sys
3 3
4 4 from IPython.core.debugger import Pdb
5 5
6 6 from IPython.core.completer import IPCompleter
7 7 from .ptutils import IPythonPTCompleter
8 8 from .shortcuts import suspend_to_bg, cursor_in_leading_ws
9 9
10 10 from prompt_toolkit.enums import DEFAULT_BUFFER
11 11 from prompt_toolkit.filters import (Condition, has_focus, has_selection,
12 12 vi_insert_mode, emacs_insert_mode)
13 13 from prompt_toolkit.key_binding import KeyBindings
14 14 from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline
15 15 from pygments.token import Token
16 16 from prompt_toolkit.shortcuts.prompt import PromptSession
17 17 from prompt_toolkit.enums import EditingMode
18 18 from prompt_toolkit.formatted_text import PygmentsTokens
19 19
20 from prompt_toolkit import __version__ as ptk_version
21 PTK3 = ptk_version.startswith('3.')
22
20 23
21 24 class TerminalPdb(Pdb):
22 25 """Standalone IPython debugger."""
23 26
24 27 def __init__(self, *args, **kwargs):
25 28 Pdb.__init__(self, *args, **kwargs)
26 29 self._ptcomp = None
27 30 self.pt_init()
28 31
29 32 def pt_init(self):
30 33 def get_prompt_tokens():
31 34 return [(Token.Prompt, self.prompt)]
32 35
33 36 if self._ptcomp is None:
34 37 compl = IPCompleter(shell=self.shell,
35 38 namespace={},
36 39 global_namespace={},
37 40 parent=self.shell,
38 41 )
39 42 self._ptcomp = IPythonPTCompleter(compl)
40 43
41 44 kb = KeyBindings()
42 45 supports_suspend = Condition(lambda: hasattr(signal, 'SIGTSTP'))
43 46 kb.add('c-z', filter=supports_suspend)(suspend_to_bg)
44 47
45 48 if self.shell.display_completions == 'readlinelike':
46 49 kb.add('tab', filter=(has_focus(DEFAULT_BUFFER)
47 50 & ~has_selection
48 51 & vi_insert_mode | emacs_insert_mode
49 52 & ~cursor_in_leading_ws
50 53 ))(display_completions_like_readline)
51 54
52 self.pt_app = PromptSession(
53 message=(lambda: PygmentsTokens(get_prompt_tokens())),
54 editing_mode=getattr(EditingMode, self.shell.editing_mode.upper()),
55 key_bindings=kb,
56 history=self.shell.debugger_history,
57 completer=self._ptcomp,
58 enable_history_search=True,
59 mouse_support=self.shell.mouse_support,
60 complete_style=self.shell.pt_complete_style,
61 style=self.shell.style,
62 inputhook=self.shell.inputhook,
63 color_depth=self.shell.color_depth,
55 options = dict(
56 message=(lambda: PygmentsTokens(get_prompt_tokens())),
57 editing_mode=getattr(EditingMode, self.shell.editing_mode.upper()),
58 key_bindings=kb,
59 history=self.shell.debugger_history,
60 completer=self._ptcomp,
61 enable_history_search=True,
62 mouse_support=self.shell.mouse_support,
63 complete_style=self.shell.pt_complete_style,
64 style=self.shell.style,
65 color_depth=self.shell.color_depth,
64 66 )
65 67
68 if not PTK3:
69 options['inputhook'] = self.inputhook
70 self.pt_app = PromptSession(**options)
71
66 72 def cmdloop(self, intro=None):
67 73 """Repeatedly issue a prompt, accept input, parse an initial prefix
68 74 off the received input, and dispatch to action methods, passing them
69 75 the remainder of the line as argument.
70 76
71 77 override the same methods from cmd.Cmd to provide prompt toolkit replacement.
72 78 """
73 79 if not self.use_rawinput:
74 80 raise ValueError('Sorry ipdb does not support use_rawinput=False')
75 81
76 82 self.preloop()
77 83
78 84 try:
79 85 if intro is not None:
80 86 self.intro = intro
81 87 if self.intro:
82 88 self.stdout.write(str(self.intro)+"\n")
83 89 stop = None
84 90 while not stop:
85 91 if self.cmdqueue:
86 92 line = self.cmdqueue.pop(0)
87 93 else:
88 94 self._ptcomp.ipy_completer.namespace = self.curframe_locals
89 95 self._ptcomp.ipy_completer.global_namespace = self.curframe.f_globals
90 96 try:
91 97 line = self.pt_app.prompt() # reset_current_buffer=True)
92 98 except EOFError:
93 99 line = 'EOF'
94 100 line = self.precmd(line)
95 101 stop = self.onecmd(line)
96 102 stop = self.postcmd(stop, line)
97 103 self.postloop()
98 104 except Exception:
99 105 raise
100 106
101 107
102 108 def set_trace(frame=None):
103 109 """
104 110 Start debugging from `frame`.
105 111
106 112 If frame is not specified, debugging starts from caller's frame.
107 113 """
108 114 TerminalPdb().set_trace(frame or sys._getframe().f_back)
109 115
110 116
111 117 if __name__ == '__main__':
112 118 import pdb
113 119 # IPython.core.debugger.Pdb.trace_dispatch shall not catch
114 120 # bdb.BdbQuit. When started through __main__ and an exception
115 121 # happened after hitting "c", this is needed in order to
116 122 # be able to quit the debugging session (see #9950).
117 123 old_trace_dispatch = pdb.Pdb.trace_dispatch
118 124 pdb.Pdb = TerminalPdb
119 125 pdb.Pdb.trace_dispatch = old_trace_dispatch
120 126 pdb.main()
General Comments 0
You need to be logged in to leave comments. Login now