##// END OF EJS Templates
forgotten import
Matthias Bussonnier -
Show More
@@ -1,371 +1,372 b''
1 """
1 """
2 Module to define and register Terminal IPython shortcuts with
2 Module to define and register Terminal IPython shortcuts with
3 :mod:`prompt_toolkit`
3 :mod:`prompt_toolkit`
4 """
4 """
5
5
6 # Copyright (c) IPython Development Team.
6 # Copyright (c) IPython Development Team.
7 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
8
8
9 import warnings
9 import warnings
10 import signal
10 import signal
11 import sys
11 import sys
12 import re
12 from typing import Callable
13 from typing import Callable
13
14
14
15
15 from prompt_toolkit.application.current import get_app
16 from prompt_toolkit.application.current import get_app
16 from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER
17 from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER
17 from prompt_toolkit.filters import (has_focus, has_selection, Condition,
18 from prompt_toolkit.filters import (has_focus, has_selection, Condition,
18 vi_insert_mode, emacs_insert_mode, has_completions, vi_mode)
19 vi_insert_mode, emacs_insert_mode, has_completions, vi_mode)
19 from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline
20 from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline
20 from prompt_toolkit.key_binding import KeyBindings
21 from prompt_toolkit.key_binding import KeyBindings
21 from prompt_toolkit.key_binding.bindings import named_commands as nc
22 from prompt_toolkit.key_binding.bindings import named_commands as nc
22 from prompt_toolkit.key_binding.vi_state import InputMode, ViState
23 from prompt_toolkit.key_binding.vi_state import InputMode, ViState
23
24
24 from IPython.utils.decorators import undoc
25 from IPython.utils.decorators import undoc
25
26
26 @undoc
27 @undoc
27 @Condition
28 @Condition
28 def cursor_in_leading_ws():
29 def cursor_in_leading_ws():
29 before = get_app().current_buffer.document.current_line_before_cursor
30 before = get_app().current_buffer.document.current_line_before_cursor
30 return (not before) or before.isspace()
31 return (not before) or before.isspace()
31
32
32
33
33 def create_ipython_shortcuts(shell):
34 def create_ipython_shortcuts(shell):
34 """Set up the prompt_toolkit keyboard shortcuts for IPython"""
35 """Set up the prompt_toolkit keyboard shortcuts for IPython"""
35
36
36 kb = KeyBindings()
37 kb = KeyBindings()
37 insert_mode = vi_insert_mode | emacs_insert_mode
38 insert_mode = vi_insert_mode | emacs_insert_mode
38
39
39 if getattr(shell, 'handle_return', None):
40 if getattr(shell, 'handle_return', None):
40 return_handler = shell.handle_return(shell)
41 return_handler = shell.handle_return(shell)
41 else:
42 else:
42 return_handler = newline_or_execute_outer(shell)
43 return_handler = newline_or_execute_outer(shell)
43
44
44 kb.add('enter', filter=(has_focus(DEFAULT_BUFFER)
45 kb.add('enter', filter=(has_focus(DEFAULT_BUFFER)
45 & ~has_selection
46 & ~has_selection
46 & insert_mode
47 & insert_mode
47 ))(return_handler)
48 ))(return_handler)
48
49
49 def reformat_and_execute(event):
50 def reformat_and_execute(event):
50 reformat_text_before_cursor(event.current_buffer, event.current_buffer.document, shell)
51 reformat_text_before_cursor(event.current_buffer, event.current_buffer.document, shell)
51 event.current_buffer.validate_and_handle()
52 event.current_buffer.validate_and_handle()
52
53
53 kb.add('escape', 'enter', filter=(has_focus(DEFAULT_BUFFER)
54 kb.add('escape', 'enter', filter=(has_focus(DEFAULT_BUFFER)
54 & ~has_selection
55 & ~has_selection
55 & insert_mode
56 & insert_mode
56 ))(reformat_and_execute)
57 ))(reformat_and_execute)
57
58
58 kb.add('c-\\')(force_exit)
59 kb.add('c-\\')(force_exit)
59
60
60 kb.add('c-p', filter=(vi_insert_mode & has_focus(DEFAULT_BUFFER))
61 kb.add('c-p', filter=(vi_insert_mode & has_focus(DEFAULT_BUFFER))
61 )(previous_history_or_previous_completion)
62 )(previous_history_or_previous_completion)
62
63
63 kb.add('c-n', filter=(vi_insert_mode & has_focus(DEFAULT_BUFFER))
64 kb.add('c-n', filter=(vi_insert_mode & has_focus(DEFAULT_BUFFER))
64 )(next_history_or_next_completion)
65 )(next_history_or_next_completion)
65
66
66 kb.add('c-g', filter=(has_focus(DEFAULT_BUFFER) & has_completions)
67 kb.add('c-g', filter=(has_focus(DEFAULT_BUFFER) & has_completions)
67 )(dismiss_completion)
68 )(dismiss_completion)
68
69
69 kb.add('c-c', filter=has_focus(DEFAULT_BUFFER))(reset_buffer)
70 kb.add('c-c', filter=has_focus(DEFAULT_BUFFER))(reset_buffer)
70
71
71 kb.add('c-c', filter=has_focus(SEARCH_BUFFER))(reset_search_buffer)
72 kb.add('c-c', filter=has_focus(SEARCH_BUFFER))(reset_search_buffer)
72
73
73 supports_suspend = Condition(lambda: hasattr(signal, 'SIGTSTP'))
74 supports_suspend = Condition(lambda: hasattr(signal, 'SIGTSTP'))
74 kb.add('c-z', filter=supports_suspend)(suspend_to_bg)
75 kb.add('c-z', filter=supports_suspend)(suspend_to_bg)
75
76
76 # Ctrl+I == Tab
77 # Ctrl+I == Tab
77 kb.add('tab', filter=(has_focus(DEFAULT_BUFFER)
78 kb.add('tab', filter=(has_focus(DEFAULT_BUFFER)
78 & ~has_selection
79 & ~has_selection
79 & insert_mode
80 & insert_mode
80 & cursor_in_leading_ws
81 & cursor_in_leading_ws
81 ))(indent_buffer)
82 ))(indent_buffer)
82 kb.add('c-o', filter=(has_focus(DEFAULT_BUFFER) & emacs_insert_mode)
83 kb.add('c-o', filter=(has_focus(DEFAULT_BUFFER) & emacs_insert_mode)
83 )(newline_autoindent_outer(shell.input_transformer_manager))
84 )(newline_autoindent_outer(shell.input_transformer_manager))
84
85
85 kb.add('f2', filter=has_focus(DEFAULT_BUFFER))(open_input_in_editor)
86 kb.add('f2', filter=has_focus(DEFAULT_BUFFER))(open_input_in_editor)
86
87
87 if shell.display_completions == 'readlinelike':
88 if shell.display_completions == 'readlinelike':
88 kb.add('c-i', filter=(has_focus(DEFAULT_BUFFER)
89 kb.add('c-i', filter=(has_focus(DEFAULT_BUFFER)
89 & ~has_selection
90 & ~has_selection
90 & insert_mode
91 & insert_mode
91 & ~cursor_in_leading_ws
92 & ~cursor_in_leading_ws
92 ))(display_completions_like_readline)
93 ))(display_completions_like_readline)
93
94
94 if sys.platform == "win32":
95 if sys.platform == "win32":
95 kb.add("c-v", filter=(has_focus(DEFAULT_BUFFER) & ~vi_mode))(win_paste)
96 kb.add("c-v", filter=(has_focus(DEFAULT_BUFFER) & ~vi_mode))(win_paste)
96
97
97 @Condition
98 @Condition
98 def ebivim():
99 def ebivim():
99 return shell.emacs_bindings_in_vi_insert_mode
100 return shell.emacs_bindings_in_vi_insert_mode
100
101
101 focused_insert = has_focus(DEFAULT_BUFFER) & vi_insert_mode
102 focused_insert = has_focus(DEFAULT_BUFFER) & vi_insert_mode
102
103
103 # Needed for to accept autosuggestions in vi insert mode
104 # Needed for to accept autosuggestions in vi insert mode
104 @kb.add("c-e", filter=focused_insert & ebivim)
105 @kb.add("c-e", filter=focused_insert & ebivim)
105 def _(event):
106 def _(event):
106 b = event.current_buffer
107 b = event.current_buffer
107 suggestion = b.suggestion
108 suggestion = b.suggestion
108 if suggestion:
109 if suggestion:
109 b.insert_text(suggestion.text)
110 b.insert_text(suggestion.text)
110 else:
111 else:
111 nc.end_of_line(event)
112 nc.end_of_line(event)
112
113
113 @kb.add("c-f", filter=focused_insert & ebivim)
114 @kb.add("c-f", filter=focused_insert & ebivim)
114 def _(event):
115 def _(event):
115 b = event.current_buffer
116 b = event.current_buffer
116 suggestion = b.suggestion
117 suggestion = b.suggestion
117 if suggestion:
118 if suggestion:
118 b.insert_text(suggestion.text)
119 b.insert_text(suggestion.text)
119 else:
120 else:
120 nc.forward_char(event)
121 nc.forward_char(event)
121
122
122 @kb.add("escape", "f", filter=focused_insert & ebivim)
123 @kb.add("escape", "f", filter=focused_insert & ebivim)
123 def _(event):
124 def _(event):
124 b = event.current_buffer
125 b = event.current_buffer
125 suggestion = b.suggestion
126 suggestion = b.suggestion
126 if suggestion:
127 if suggestion:
127 t = re.split(r"(\S+\s+)", suggestion.text)
128 t = re.split(r"(\S+\s+)", suggestion.text)
128 b.insert_text(next((x for x in t if x), ""))
129 b.insert_text(next((x for x in t if x), ""))
129 else:
130 else:
130 nc.forward_word(event)
131 nc.forward_word(event)
131
132
132 # Simple Control keybindings
133 # Simple Control keybindings
133 key_cmd_dict = {
134 key_cmd_dict = {
134 "c-a": nc.beginning_of_line,
135 "c-a": nc.beginning_of_line,
135 "c-b": nc.backward_char,
136 "c-b": nc.backward_char,
136 "c-k": nc.kill_line,
137 "c-k": nc.kill_line,
137 "c-w": nc.backward_kill_word,
138 "c-w": nc.backward_kill_word,
138 "c-y": nc.yank,
139 "c-y": nc.yank,
139 "c-_": nc.undo,
140 "c-_": nc.undo,
140 }
141 }
141
142
142 for key, cmd in key_cmd_dict.items():
143 for key, cmd in key_cmd_dict.items():
143 kb.add(key, filter=focused_insert & ebivim)(cmd)
144 kb.add(key, filter=focused_insert & ebivim)(cmd)
144
145
145 # Alt and Combo Control keybindings
146 # Alt and Combo Control keybindings
146 keys_cmd_dict = {
147 keys_cmd_dict = {
147 # Control Combos
148 # Control Combos
148 ("c-x", "c-e"): nc.edit_and_execute,
149 ("c-x", "c-e"): nc.edit_and_execute,
149 ("c-x", "e"): nc.edit_and_execute,
150 ("c-x", "e"): nc.edit_and_execute,
150 # Alt
151 # Alt
151 ("escape", "b"): nc.backward_word,
152 ("escape", "b"): nc.backward_word,
152 ("escape", "c"): nc.capitalize_word,
153 ("escape", "c"): nc.capitalize_word,
153 ("escape", "d"): nc.kill_word,
154 ("escape", "d"): nc.kill_word,
154 ("escape", "h"): nc.backward_kill_word,
155 ("escape", "h"): nc.backward_kill_word,
155 ("escape", "l"): nc.downcase_word,
156 ("escape", "l"): nc.downcase_word,
156 ("escape", "u"): nc.uppercase_word,
157 ("escape", "u"): nc.uppercase_word,
157 ("escape", "y"): nc.yank_pop,
158 ("escape", "y"): nc.yank_pop,
158 ("escape", "."): nc.yank_last_arg,
159 ("escape", "."): nc.yank_last_arg,
159 }
160 }
160
161
161 for keys, cmd in keys_cmd_dict.items():
162 for keys, cmd in keys_cmd_dict.items():
162 kb.add(*keys, filter=focused_insert & ebivim)(cmd)
163 kb.add(*keys, filter=focused_insert & ebivim)(cmd)
163
164
164 def get_input_mode(self):
165 def get_input_mode(self):
165 if sys.version_info[0] == 3:
166 if sys.version_info[0] == 3:
166 app = get_app()
167 app = get_app()
167 app.ttimeoutlen = shell.ttimeoutlen
168 app.ttimeoutlen = shell.ttimeoutlen
168 app.timeoutlen = shell.timeoutlen
169 app.timeoutlen = shell.timeoutlen
169
170
170 return self._input_mode
171 return self._input_mode
171
172
172 def set_input_mode(self, mode):
173 def set_input_mode(self, mode):
173 shape = {InputMode.NAVIGATION: 2, InputMode.REPLACE: 4}.get(mode, 6)
174 shape = {InputMode.NAVIGATION: 2, InputMode.REPLACE: 4}.get(mode, 6)
174 cursor = "\x1b[{} q".format(shape)
175 cursor = "\x1b[{} q".format(shape)
175
176
176 if hasattr(sys.stdout, "_cli"):
177 if hasattr(sys.stdout, "_cli"):
177 write = sys.stdout._cli.output.write_raw
178 write = sys.stdout._cli.output.write_raw
178 else:
179 else:
179 write = sys.stdout.write
180 write = sys.stdout.write
180
181
181 write(cursor)
182 write(cursor)
182 sys.stdout.flush()
183 sys.stdout.flush()
183
184
184 self._input_mode = mode
185 self._input_mode = mode
185
186
186 if shell.editing_mode == "vi" and shell.modal_cursor:
187 if shell.editing_mode == "vi" and shell.modal_cursor:
187 ViState._input_mode = InputMode.INSERT
188 ViState._input_mode = InputMode.INSERT
188 ViState.input_mode = property(get_input_mode, set_input_mode)
189 ViState.input_mode = property(get_input_mode, set_input_mode)
189
190
190 return kb
191 return kb
191
192
192
193
193 def reformat_text_before_cursor(buffer, document, shell):
194 def reformat_text_before_cursor(buffer, document, shell):
194 text = buffer.delete_before_cursor(len(document.text[:document.cursor_position]))
195 text = buffer.delete_before_cursor(len(document.text[:document.cursor_position]))
195 try:
196 try:
196 formatted_text = shell.reformat_handler(text)
197 formatted_text = shell.reformat_handler(text)
197 buffer.insert_text(formatted_text)
198 buffer.insert_text(formatted_text)
198 except Exception as e:
199 except Exception as e:
199 buffer.insert_text(text)
200 buffer.insert_text(text)
200
201
201
202
202 def newline_or_execute_outer(shell):
203 def newline_or_execute_outer(shell):
203
204
204 def newline_or_execute(event):
205 def newline_or_execute(event):
205 """When the user presses return, insert a newline or execute the code."""
206 """When the user presses return, insert a newline or execute the code."""
206 b = event.current_buffer
207 b = event.current_buffer
207 d = b.document
208 d = b.document
208
209
209 if b.complete_state:
210 if b.complete_state:
210 cc = b.complete_state.current_completion
211 cc = b.complete_state.current_completion
211 if cc:
212 if cc:
212 b.apply_completion(cc)
213 b.apply_completion(cc)
213 else:
214 else:
214 b.cancel_completion()
215 b.cancel_completion()
215 return
216 return
216
217
217 # If there's only one line, treat it as if the cursor is at the end.
218 # If there's only one line, treat it as if the cursor is at the end.
218 # See https://github.com/ipython/ipython/issues/10425
219 # See https://github.com/ipython/ipython/issues/10425
219 if d.line_count == 1:
220 if d.line_count == 1:
220 check_text = d.text
221 check_text = d.text
221 else:
222 else:
222 check_text = d.text[:d.cursor_position]
223 check_text = d.text[:d.cursor_position]
223 status, indent = shell.check_complete(check_text)
224 status, indent = shell.check_complete(check_text)
224
225
225 # if all we have after the cursor is whitespace: reformat current text
226 # if all we have after the cursor is whitespace: reformat current text
226 # before cursor
227 # before cursor
227 after_cursor = d.text[d.cursor_position:]
228 after_cursor = d.text[d.cursor_position:]
228 reformatted = False
229 reformatted = False
229 if not after_cursor.strip():
230 if not after_cursor.strip():
230 reformat_text_before_cursor(b, d, shell)
231 reformat_text_before_cursor(b, d, shell)
231 reformatted = True
232 reformatted = True
232 if not (d.on_last_line or
233 if not (d.on_last_line or
233 d.cursor_position_row >= d.line_count - d.empty_line_count_at_the_end()
234 d.cursor_position_row >= d.line_count - d.empty_line_count_at_the_end()
234 ):
235 ):
235 if shell.autoindent:
236 if shell.autoindent:
236 b.insert_text('\n' + indent)
237 b.insert_text('\n' + indent)
237 else:
238 else:
238 b.insert_text('\n')
239 b.insert_text('\n')
239 return
240 return
240
241
241 if (status != 'incomplete') and b.accept_handler:
242 if (status != 'incomplete') and b.accept_handler:
242 if not reformatted:
243 if not reformatted:
243 reformat_text_before_cursor(b, d, shell)
244 reformat_text_before_cursor(b, d, shell)
244 b.validate_and_handle()
245 b.validate_and_handle()
245 else:
246 else:
246 if shell.autoindent:
247 if shell.autoindent:
247 b.insert_text('\n' + indent)
248 b.insert_text('\n' + indent)
248 else:
249 else:
249 b.insert_text('\n')
250 b.insert_text('\n')
250 return newline_or_execute
251 return newline_or_execute
251
252
252
253
253 def previous_history_or_previous_completion(event):
254 def previous_history_or_previous_completion(event):
254 """
255 """
255 Control-P in vi edit mode on readline is history next, unlike default prompt toolkit.
256 Control-P in vi edit mode on readline is history next, unlike default prompt toolkit.
256
257
257 If completer is open this still select previous completion.
258 If completer is open this still select previous completion.
258 """
259 """
259 event.current_buffer.auto_up()
260 event.current_buffer.auto_up()
260
261
261
262
262 def next_history_or_next_completion(event):
263 def next_history_or_next_completion(event):
263 """
264 """
264 Control-N in vi edit mode on readline is history previous, unlike default prompt toolkit.
265 Control-N in vi edit mode on readline is history previous, unlike default prompt toolkit.
265
266
266 If completer is open this still select next completion.
267 If completer is open this still select next completion.
267 """
268 """
268 event.current_buffer.auto_down()
269 event.current_buffer.auto_down()
269
270
270
271
271 def dismiss_completion(event):
272 def dismiss_completion(event):
272 b = event.current_buffer
273 b = event.current_buffer
273 if b.complete_state:
274 if b.complete_state:
274 b.cancel_completion()
275 b.cancel_completion()
275
276
276
277
277 def reset_buffer(event):
278 def reset_buffer(event):
278 b = event.current_buffer
279 b = event.current_buffer
279 if b.complete_state:
280 if b.complete_state:
280 b.cancel_completion()
281 b.cancel_completion()
281 else:
282 else:
282 b.reset()
283 b.reset()
283
284
284
285
285 def reset_search_buffer(event):
286 def reset_search_buffer(event):
286 if event.current_buffer.document.text:
287 if event.current_buffer.document.text:
287 event.current_buffer.reset()
288 event.current_buffer.reset()
288 else:
289 else:
289 event.app.layout.focus(DEFAULT_BUFFER)
290 event.app.layout.focus(DEFAULT_BUFFER)
290
291
291 def suspend_to_bg(event):
292 def suspend_to_bg(event):
292 event.app.suspend_to_background()
293 event.app.suspend_to_background()
293
294
294 def force_exit(event):
295 def force_exit(event):
295 """
296 """
296 Force exit (with a non-zero return value)
297 Force exit (with a non-zero return value)
297 """
298 """
298 sys.exit("Quit")
299 sys.exit("Quit")
299
300
300 def indent_buffer(event):
301 def indent_buffer(event):
301 event.current_buffer.insert_text(' ' * 4)
302 event.current_buffer.insert_text(' ' * 4)
302
303
303 @undoc
304 @undoc
304 def newline_with_copy_margin(event):
305 def newline_with_copy_margin(event):
305 """
306 """
306 DEPRECATED since IPython 6.0
307 DEPRECATED since IPython 6.0
307
308
308 See :any:`newline_autoindent_outer` for a replacement.
309 See :any:`newline_autoindent_outer` for a replacement.
309
310
310 Preserve margin and cursor position when using
311 Preserve margin and cursor position when using
311 Control-O to insert a newline in EMACS mode
312 Control-O to insert a newline in EMACS mode
312 """
313 """
313 warnings.warn("`newline_with_copy_margin(event)` is deprecated since IPython 6.0. "
314 warnings.warn("`newline_with_copy_margin(event)` is deprecated since IPython 6.0. "
314 "see `newline_autoindent_outer(shell)(event)` for a replacement.",
315 "see `newline_autoindent_outer(shell)(event)` for a replacement.",
315 DeprecationWarning, stacklevel=2)
316 DeprecationWarning, stacklevel=2)
316
317
317 b = event.current_buffer
318 b = event.current_buffer
318 cursor_start_pos = b.document.cursor_position_col
319 cursor_start_pos = b.document.cursor_position_col
319 b.newline(copy_margin=True)
320 b.newline(copy_margin=True)
320 b.cursor_up(count=1)
321 b.cursor_up(count=1)
321 cursor_end_pos = b.document.cursor_position_col
322 cursor_end_pos = b.document.cursor_position_col
322 if cursor_start_pos != cursor_end_pos:
323 if cursor_start_pos != cursor_end_pos:
323 pos_diff = cursor_start_pos - cursor_end_pos
324 pos_diff = cursor_start_pos - cursor_end_pos
324 b.cursor_right(count=pos_diff)
325 b.cursor_right(count=pos_diff)
325
326
326 def newline_autoindent_outer(inputsplitter) -> Callable[..., None]:
327 def newline_autoindent_outer(inputsplitter) -> Callable[..., None]:
327 """
328 """
328 Return a function suitable for inserting a indented newline after the cursor.
329 Return a function suitable for inserting a indented newline after the cursor.
329
330
330 Fancier version of deprecated ``newline_with_copy_margin`` which should
331 Fancier version of deprecated ``newline_with_copy_margin`` which should
331 compute the correct indentation of the inserted line. That is to say, indent
332 compute the correct indentation of the inserted line. That is to say, indent
332 by 4 extra space after a function definition, class definition, context
333 by 4 extra space after a function definition, class definition, context
333 manager... And dedent by 4 space after ``pass``, ``return``, ``raise ...``.
334 manager... And dedent by 4 space after ``pass``, ``return``, ``raise ...``.
334 """
335 """
335
336
336 def newline_autoindent(event):
337 def newline_autoindent(event):
337 """insert a newline after the cursor indented appropriately."""
338 """insert a newline after the cursor indented appropriately."""
338 b = event.current_buffer
339 b = event.current_buffer
339 d = b.document
340 d = b.document
340
341
341 if b.complete_state:
342 if b.complete_state:
342 b.cancel_completion()
343 b.cancel_completion()
343 text = d.text[:d.cursor_position] + '\n'
344 text = d.text[:d.cursor_position] + '\n'
344 _, indent = inputsplitter.check_complete(text)
345 _, indent = inputsplitter.check_complete(text)
345 b.insert_text('\n' + (' ' * (indent or 0)), move_cursor=False)
346 b.insert_text('\n' + (' ' * (indent or 0)), move_cursor=False)
346
347
347 return newline_autoindent
348 return newline_autoindent
348
349
349
350
350 def open_input_in_editor(event):
351 def open_input_in_editor(event):
351 event.app.current_buffer.open_in_editor()
352 event.app.current_buffer.open_in_editor()
352
353
353
354
354 if sys.platform == 'win32':
355 if sys.platform == 'win32':
355 from IPython.core.error import TryNext
356 from IPython.core.error import TryNext
356 from IPython.lib.clipboard import (ClipboardEmpty,
357 from IPython.lib.clipboard import (ClipboardEmpty,
357 win32_clipboard_get,
358 win32_clipboard_get,
358 tkinter_clipboard_get)
359 tkinter_clipboard_get)
359
360
360 @undoc
361 @undoc
361 def win_paste(event):
362 def win_paste(event):
362 try:
363 try:
363 text = win32_clipboard_get()
364 text = win32_clipboard_get()
364 except TryNext:
365 except TryNext:
365 try:
366 try:
366 text = tkinter_clipboard_get()
367 text = tkinter_clipboard_get()
367 except (TryNext, ClipboardEmpty):
368 except (TryNext, ClipboardEmpty):
368 return
369 return
369 except ClipboardEmpty:
370 except ClipboardEmpty:
370 return
371 return
371 event.current_buffer.insert_text(text.replace("\t", " " * 4))
372 event.current_buffer.insert_text(text.replace("\t", " " * 4))
General Comments 0
You need to be logged in to leave comments. Login now