##// END OF EJS Templates
Merge pull request #10275 from ipython/auto-backport-of-pr-10264...
Matthias Bussonnier -
r23346:6011b494 merge
parent child Browse files
Show More
@@ -1,199 +1,201 b''
1 1 import signal
2 2 import sys
3 3
4 4 from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER
5 5 from prompt_toolkit.filters import (HasFocus, HasSelection, Condition,
6 6 ViInsertMode, EmacsInsertMode, HasCompletions)
7 7 from prompt_toolkit.filters.cli import ViMode
8 8 from prompt_toolkit.keys import Keys
9 9 from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline
10 10
11 11 from IPython.utils.decorators import undoc
12 12
13 13 @Condition
14 14 def cursor_in_leading_ws(cli):
15 15 before = cli.application.buffer.document.current_line_before_cursor
16 16 return (not before) or before.isspace()
17 17
18 18 def register_ipython_shortcuts(registry, shell):
19 19 """Set up the prompt_toolkit keyboard shortcuts for IPython"""
20 20 insert_mode = ViInsertMode() | EmacsInsertMode()
21 21
22 22 # Ctrl+J == Enter, seemingly
23 23 registry.add_binding(Keys.ControlJ,
24 24 filter=(HasFocus(DEFAULT_BUFFER)
25 25 & ~HasSelection()
26 26 & insert_mode
27 27 ))(newline_or_execute_outer(shell))
28 28
29 29 registry.add_binding(Keys.ControlBackslash)(force_exit)
30 30
31 31 registry.add_binding(Keys.ControlP,
32 32 filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER)
33 33 ))(previous_history_or_previous_completion)
34 34
35 35 registry.add_binding(Keys.ControlN,
36 36 filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER)
37 37 ))(next_history_or_next_completion)
38 38
39 39 registry.add_binding(Keys.ControlG,
40 40 filter=(HasFocus(DEFAULT_BUFFER) & HasCompletions()
41 41 ))(dismiss_completion)
42 42
43 43 registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER)
44 44 )(reset_buffer)
45 45
46 46 registry.add_binding(Keys.ControlC, filter=HasFocus(SEARCH_BUFFER)
47 47 )(reset_search_buffer)
48 48
49 49 supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP'))
50 50 registry.add_binding(Keys.ControlZ, filter=supports_suspend
51 51 )(suspend_to_bg)
52 52
53 53 # Ctrl+I == Tab
54 54 registry.add_binding(Keys.ControlI,
55 55 filter=(HasFocus(DEFAULT_BUFFER)
56 56 & ~HasSelection()
57 57 & insert_mode
58 58 & cursor_in_leading_ws
59 59 ))(indent_buffer)
60 60
61 61 registry.add_binding(Keys.ControlO,
62 62 filter=(HasFocus(DEFAULT_BUFFER)
63 63 & EmacsInsertMode()))(newline_with_copy_margin)
64 64
65 65 registry.add_binding(Keys.F2,
66 66 filter=HasFocus(DEFAULT_BUFFER)
67 67 )(open_input_in_editor)
68 68
69 69 if shell.display_completions == 'readlinelike':
70 70 registry.add_binding(Keys.ControlI,
71 71 filter=(HasFocus(DEFAULT_BUFFER)
72 72 & ~HasSelection()
73 73 & insert_mode
74 74 & ~cursor_in_leading_ws
75 75 ))(display_completions_like_readline)
76 76
77 77 if sys.platform == 'win32':
78 78 registry.add_binding(Keys.ControlV,
79 79 filter=(
80 80 HasFocus(
81 81 DEFAULT_BUFFER) & ~ViMode()
82 82 ))(win_paste)
83 83
84 84
85 85 def newline_or_execute_outer(shell):
86 86 def newline_or_execute(event):
87 87 """When the user presses return, insert a newline or execute the code."""
88 88 b = event.current_buffer
89 89 d = b.document
90 90
91 91 if b.complete_state:
92 92 cc = b.complete_state.current_completion
93 93 if cc:
94 94 b.apply_completion(cc)
95 95 else:
96 96 b.cancel_completion()
97 97 return
98 98
99 if not (d.on_last_line or d.cursor_position_row >= d.line_count
100 - d.empty_line_count_at_the_end()):
101 b.newline()
102 return
99 before_text = d.text[:d.cursor_position]
100 status, indent = shell.input_splitter.check_complete(before_text + '\n')
103 101
104 status, indent = shell.input_splitter.check_complete(d.text + '\n')
102 if not (d.on_last_line or
103 d.cursor_position_row >= d.line_count - d.empty_line_count_at_the_end()
104 ):
105 b.insert_text('\n' + (' ' * (indent or 0)))
106 return
105 107
106 108 if (status != 'incomplete') and b.accept_action.is_returnable:
107 109 b.accept_action.validate_and_handle(event.cli, b)
108 110 else:
109 111 b.insert_text('\n' + (' ' * (indent or 0)))
110 112 return newline_or_execute
111 113
112 114
113 115 def previous_history_or_previous_completion(event):
114 116 """
115 117 Control-P in vi edit mode on readline is history next, unlike default prompt toolkit.
116 118
117 119 If completer is open this still select previous completion.
118 120 """
119 121 event.current_buffer.auto_up()
120 122
121 123
122 124 def next_history_or_next_completion(event):
123 125 """
124 126 Control-N in vi edit mode on readline is history previous, unlike default prompt toolkit.
125 127
126 128 If completer is open this still select next completion.
127 129 """
128 130 event.current_buffer.auto_down()
129 131
130 132
131 133 def dismiss_completion(event):
132 134 b = event.current_buffer
133 135 if b.complete_state:
134 136 b.cancel_completion()
135 137
136 138
137 139 def reset_buffer(event):
138 140 b = event.current_buffer
139 141 if b.complete_state:
140 142 b.cancel_completion()
141 143 else:
142 144 b.reset()
143 145
144 146
145 147 def reset_search_buffer(event):
146 148 if event.current_buffer.document.text:
147 149 event.current_buffer.reset()
148 150 else:
149 151 event.cli.push_focus(DEFAULT_BUFFER)
150 152
151 153 def suspend_to_bg(event):
152 154 event.cli.suspend_to_background()
153 155
154 156 def force_exit(event):
155 157 """
156 158 Force exit (with a non-zero return value)
157 159 """
158 160 sys.exit("Quit")
159 161
160 162 def indent_buffer(event):
161 163 event.current_buffer.insert_text(' ' * 4)
162 164
163 165 def newline_with_copy_margin(event):
164 166 """
165 167 Preserve margin and cursor position when using
166 168 Control-O to insert a newline in EMACS mode
167 169 """
168 170 b = event.current_buffer
169 171 cursor_start_pos = b.document.cursor_position_col
170 172 b.newline(copy_margin=True)
171 173 b.cursor_up(count=1)
172 174 cursor_end_pos = b.document.cursor_position_col
173 175 if cursor_start_pos != cursor_end_pos:
174 176 pos_diff = cursor_start_pos - cursor_end_pos
175 177 b.cursor_right(count=pos_diff)
176 178
177 179 def open_input_in_editor(event):
178 180 event.cli.current_buffer.tempfile_suffix = ".py"
179 181 event.cli.current_buffer.open_in_editor(event.cli)
180 182
181 183
182 184 if sys.platform == 'win32':
183 185 from IPython.core.error import TryNext
184 186 from IPython.lib.clipboard import (ClipboardEmpty,
185 187 win32_clipboard_get,
186 188 tkinter_clipboard_get)
187 189
188 190 @undoc
189 191 def win_paste(event):
190 192 try:
191 193 text = win32_clipboard_get()
192 194 except TryNext:
193 195 try:
194 196 text = tkinter_clipboard_get()
195 197 except (TryNext, ClipboardEmpty):
196 198 return
197 199 except ClipboardEmpty:
198 200 return
199 201 event.current_buffer.insert_text(text.replace('\t', ' ' * 4))
General Comments 0
You need to be logged in to leave comments. Login now