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