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