##// END OF EJS Templates
Remove redundant setting of tempfile_suffix....
foobarbyte -
Show More
@@ -1,274 +1,273 b''
1 1 """
2 2 Module to define and register Terminal IPython shortcuts with
3 3 :mod:`prompt_toolkit`
4 4 """
5 5
6 6 # Copyright (c) IPython Development Team.
7 7 # Distributed under the terms of the Modified BSD License.
8 8
9 9 import warnings
10 10 import signal
11 11 import sys
12 12 from typing import Callable
13 13
14 14
15 15 from prompt_toolkit.application.current import get_app
16 16 from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER
17 17 from prompt_toolkit.filters import (has_focus, has_selection, Condition,
18 18 vi_insert_mode, emacs_insert_mode, has_completions, vi_mode)
19 19 from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline
20 20 from prompt_toolkit.key_binding import KeyBindings
21 21
22 22 from IPython.utils.decorators import undoc
23 23
24 24 @undoc
25 25 @Condition
26 26 def cursor_in_leading_ws():
27 27 before = get_app().current_buffer.document.current_line_before_cursor
28 28 return (not before) or before.isspace()
29 29
30 30
31 31 def create_ipython_shortcuts(shell):
32 32 """Set up the prompt_toolkit keyboard shortcuts for IPython"""
33 33
34 34 kb = KeyBindings()
35 35 insert_mode = vi_insert_mode | emacs_insert_mode
36 36
37 37 if getattr(shell, 'handle_return', None):
38 38 return_handler = shell.handle_return(shell)
39 39 else:
40 40 return_handler = newline_or_execute_outer(shell)
41 41
42 42 kb.add('enter', filter=(has_focus(DEFAULT_BUFFER)
43 43 & ~has_selection
44 44 & insert_mode
45 45 ))(return_handler)
46 46
47 47 def reformat_and_execute(event):
48 48 reformat_text_before_cursor(event.current_buffer, event.current_buffer.document, shell)
49 49 event.current_buffer.validate_and_handle()
50 50
51 51 kb.add('escape', 'enter', filter=(has_focus(DEFAULT_BUFFER)
52 52 & ~has_selection
53 53 & insert_mode
54 54 ))(reformat_and_execute)
55 55
56 56 kb.add('c-\\')(force_exit)
57 57
58 58 kb.add('c-p', filter=(vi_insert_mode & has_focus(DEFAULT_BUFFER))
59 59 )(previous_history_or_previous_completion)
60 60
61 61 kb.add('c-n', filter=(vi_insert_mode & has_focus(DEFAULT_BUFFER))
62 62 )(next_history_or_next_completion)
63 63
64 64 kb.add('c-g', filter=(has_focus(DEFAULT_BUFFER) & has_completions)
65 65 )(dismiss_completion)
66 66
67 67 kb.add('c-c', filter=has_focus(DEFAULT_BUFFER))(reset_buffer)
68 68
69 69 kb.add('c-c', filter=has_focus(SEARCH_BUFFER))(reset_search_buffer)
70 70
71 71 supports_suspend = Condition(lambda: hasattr(signal, 'SIGTSTP'))
72 72 kb.add('c-z', filter=supports_suspend)(suspend_to_bg)
73 73
74 74 # Ctrl+I == Tab
75 75 kb.add('tab', filter=(has_focus(DEFAULT_BUFFER)
76 76 & ~has_selection
77 77 & insert_mode
78 78 & cursor_in_leading_ws
79 79 ))(indent_buffer)
80 80 kb.add('c-o', filter=(has_focus(DEFAULT_BUFFER) & emacs_insert_mode)
81 81 )(newline_autoindent_outer(shell.input_transformer_manager))
82 82
83 83 kb.add('f2', filter=has_focus(DEFAULT_BUFFER))(open_input_in_editor)
84 84
85 85 if shell.display_completions == 'readlinelike':
86 86 kb.add('c-i', filter=(has_focus(DEFAULT_BUFFER)
87 87 & ~has_selection
88 88 & insert_mode
89 89 & ~cursor_in_leading_ws
90 90 ))(display_completions_like_readline)
91 91
92 92 if sys.platform == 'win32':
93 93 kb.add('c-v', filter=(has_focus(DEFAULT_BUFFER) & ~vi_mode))(win_paste)
94 94
95 95 return kb
96 96
97 97
98 98 def reformat_text_before_cursor(buffer, document, shell):
99 99 text = buffer.delete_before_cursor(len(document.text[:document.cursor_position]))
100 100 try:
101 101 formatted_text = shell.reformat_handler(text)
102 102 buffer.insert_text(formatted_text)
103 103 except Exception as e:
104 104 buffer.insert_text(text)
105 105
106 106
107 107 def newline_or_execute_outer(shell):
108 108
109 109 def newline_or_execute(event):
110 110 """When the user presses return, insert a newline or execute the code."""
111 111 b = event.current_buffer
112 112 d = b.document
113 113
114 114 if b.complete_state:
115 115 cc = b.complete_state.current_completion
116 116 if cc:
117 117 b.apply_completion(cc)
118 118 else:
119 119 b.cancel_completion()
120 120 return
121 121
122 122 # If there's only one line, treat it as if the cursor is at the end.
123 123 # See https://github.com/ipython/ipython/issues/10425
124 124 if d.line_count == 1:
125 125 check_text = d.text
126 126 else:
127 127 check_text = d.text[:d.cursor_position]
128 128 status, indent = shell.check_complete(check_text)
129 129
130 130 # if all we have after the cursor is whitespace: reformat current text
131 131 # before cursor
132 132 after_cursor = d.text[d.cursor_position:]
133 133 if not after_cursor.strip():
134 134 reformat_text_before_cursor(b, d, shell)
135 135 if not (d.on_last_line or
136 136 d.cursor_position_row >= d.line_count - d.empty_line_count_at_the_end()
137 137 ):
138 138 if shell.autoindent:
139 139 b.insert_text('\n' + indent)
140 140 else:
141 141 b.insert_text('\n')
142 142 return
143 143
144 144 if (status != 'incomplete') and b.accept_handler:
145 145 reformat_text_before_cursor(b, d, shell)
146 146 b.validate_and_handle()
147 147 else:
148 148 if shell.autoindent:
149 149 b.insert_text('\n' + indent)
150 150 else:
151 151 b.insert_text('\n')
152 152 return newline_or_execute
153 153
154 154
155 155 def previous_history_or_previous_completion(event):
156 156 """
157 157 Control-P in vi edit mode on readline is history next, unlike default prompt toolkit.
158 158
159 159 If completer is open this still select previous completion.
160 160 """
161 161 event.current_buffer.auto_up()
162 162
163 163
164 164 def next_history_or_next_completion(event):
165 165 """
166 166 Control-N in vi edit mode on readline is history previous, unlike default prompt toolkit.
167 167
168 168 If completer is open this still select next completion.
169 169 """
170 170 event.current_buffer.auto_down()
171 171
172 172
173 173 def dismiss_completion(event):
174 174 b = event.current_buffer
175 175 if b.complete_state:
176 176 b.cancel_completion()
177 177
178 178
179 179 def reset_buffer(event):
180 180 b = event.current_buffer
181 181 if b.complete_state:
182 182 b.cancel_completion()
183 183 else:
184 184 b.reset()
185 185
186 186
187 187 def reset_search_buffer(event):
188 188 if event.current_buffer.document.text:
189 189 event.current_buffer.reset()
190 190 else:
191 191 event.app.layout.focus(DEFAULT_BUFFER)
192 192
193 193 def suspend_to_bg(event):
194 194 event.app.suspend_to_background()
195 195
196 196 def force_exit(event):
197 197 """
198 198 Force exit (with a non-zero return value)
199 199 """
200 200 sys.exit("Quit")
201 201
202 202 def indent_buffer(event):
203 203 event.current_buffer.insert_text(' ' * 4)
204 204
205 205 @undoc
206 206 def newline_with_copy_margin(event):
207 207 """
208 208 DEPRECATED since IPython 6.0
209 209
210 210 See :any:`newline_autoindent_outer` for a replacement.
211 211
212 212 Preserve margin and cursor position when using
213 213 Control-O to insert a newline in EMACS mode
214 214 """
215 215 warnings.warn("`newline_with_copy_margin(event)` is deprecated since IPython 6.0. "
216 216 "see `newline_autoindent_outer(shell)(event)` for a replacement.",
217 217 DeprecationWarning, stacklevel=2)
218 218
219 219 b = event.current_buffer
220 220 cursor_start_pos = b.document.cursor_position_col
221 221 b.newline(copy_margin=True)
222 222 b.cursor_up(count=1)
223 223 cursor_end_pos = b.document.cursor_position_col
224 224 if cursor_start_pos != cursor_end_pos:
225 225 pos_diff = cursor_start_pos - cursor_end_pos
226 226 b.cursor_right(count=pos_diff)
227 227
228 228 def newline_autoindent_outer(inputsplitter) -> Callable[..., None]:
229 229 """
230 230 Return a function suitable for inserting a indented newline after the cursor.
231 231
232 232 Fancier version of deprecated ``newline_with_copy_margin`` which should
233 233 compute the correct indentation of the inserted line. That is to say, indent
234 234 by 4 extra space after a function definition, class definition, context
235 235 manager... And dedent by 4 space after ``pass``, ``return``, ``raise ...``.
236 236 """
237 237
238 238 def newline_autoindent(event):
239 239 """insert a newline after the cursor indented appropriately."""
240 240 b = event.current_buffer
241 241 d = b.document
242 242
243 243 if b.complete_state:
244 244 b.cancel_completion()
245 245 text = d.text[:d.cursor_position] + '\n'
246 246 _, indent = inputsplitter.check_complete(text)
247 247 b.insert_text('\n' + (' ' * (indent or 0)), move_cursor=False)
248 248
249 249 return newline_autoindent
250 250
251 251
252 252 def open_input_in_editor(event):
253 event.app.current_buffer.tempfile_suffix = ".py"
254 253 event.app.current_buffer.open_in_editor()
255 254
256 255
257 256 if sys.platform == 'win32':
258 257 from IPython.core.error import TryNext
259 258 from IPython.lib.clipboard import (ClipboardEmpty,
260 259 win32_clipboard_get,
261 260 tkinter_clipboard_get)
262 261
263 262 @undoc
264 263 def win_paste(event):
265 264 try:
266 265 text = win32_clipboard_get()
267 266 except TryNext:
268 267 try:
269 268 text = tkinter_clipboard_get()
270 269 except (TryNext, ClipboardEmpty):
271 270 return
272 271 except ClipboardEmpty:
273 272 return
274 273 event.current_buffer.insert_text(text.replace('\t', ' ' * 4))
General Comments 0
You need to be logged in to leave comments. Login now