##// END OF EJS Templates
Merge pull request #10264 from Carreau/fix-newline-indentation...
Thomas Kluyver -
r23326:2405af15 merge
parent child Browse files
Show More
@@ -1,203 +1,205 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, ViNavigationMode
7 from prompt_toolkit.filters.cli import ViMode, ViNavigationMode
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 registry.add_binding('v',
69 registry.add_binding('v',
70 filter=HasFocus(DEFAULT_BUFFER) & ViNavigationMode()
70 filter=HasFocus(DEFAULT_BUFFER) & ViNavigationMode()
71 )(open_input_in_editor)
71 )(open_input_in_editor)
72
72
73 if shell.display_completions == 'readlinelike':
73 if shell.display_completions == 'readlinelike':
74 registry.add_binding(Keys.ControlI,
74 registry.add_binding(Keys.ControlI,
75 filter=(HasFocus(DEFAULT_BUFFER)
75 filter=(HasFocus(DEFAULT_BUFFER)
76 & ~HasSelection()
76 & ~HasSelection()
77 & insert_mode
77 & insert_mode
78 & ~cursor_in_leading_ws
78 & ~cursor_in_leading_ws
79 ))(display_completions_like_readline)
79 ))(display_completions_like_readline)
80
80
81 if sys.platform == 'win32':
81 if sys.platform == 'win32':
82 registry.add_binding(Keys.ControlV,
82 registry.add_binding(Keys.ControlV,
83 filter=(
83 filter=(
84 HasFocus(
84 HasFocus(
85 DEFAULT_BUFFER) & ~ViMode()
85 DEFAULT_BUFFER) & ~ViMode()
86 ))(win_paste)
86 ))(win_paste)
87
87
88
88
89 def newline_or_execute_outer(shell):
89 def newline_or_execute_outer(shell):
90 def newline_or_execute(event):
90 def newline_or_execute(event):
91 """When the user presses return, insert a newline or execute the code."""
91 """When the user presses return, insert a newline or execute the code."""
92 b = event.current_buffer
92 b = event.current_buffer
93 d = b.document
93 d = b.document
94
94
95 if b.complete_state:
95 if b.complete_state:
96 cc = b.complete_state.current_completion
96 cc = b.complete_state.current_completion
97 if cc:
97 if cc:
98 b.apply_completion(cc)
98 b.apply_completion(cc)
99 else:
99 else:
100 b.cancel_completion()
100 b.cancel_completion()
101 return
101 return
102
102
103 if not (d.on_last_line or d.cursor_position_row >= d.line_count
103 before_text = d.text[:d.cursor_position]
104 - d.empty_line_count_at_the_end()):
104 status, indent = shell.input_splitter.check_complete(before_text + '\n')
105 b.newline()
106 return
107
105
108 status, indent = shell.input_splitter.check_complete(d.text + '\n')
106 if not (d.on_last_line or
107 d.cursor_position_row >= d.line_count - d.empty_line_count_at_the_end()
108 ):
109 b.insert_text('\n' + (' ' * (indent or 0)))
110 return
109
111
110 if (status != 'incomplete') and b.accept_action.is_returnable:
112 if (status != 'incomplete') and b.accept_action.is_returnable:
111 b.accept_action.validate_and_handle(event.cli, b)
113 b.accept_action.validate_and_handle(event.cli, b)
112 else:
114 else:
113 b.insert_text('\n' + (' ' * (indent or 0)))
115 b.insert_text('\n' + (' ' * (indent or 0)))
114 return newline_or_execute
116 return newline_or_execute
115
117
116
118
117 def previous_history_or_previous_completion(event):
119 def previous_history_or_previous_completion(event):
118 """
120 """
119 Control-P in vi edit mode on readline is history next, unlike default prompt toolkit.
121 Control-P in vi edit mode on readline is history next, unlike default prompt toolkit.
120
122
121 If completer is open this still select previous completion.
123 If completer is open this still select previous completion.
122 """
124 """
123 event.current_buffer.auto_up()
125 event.current_buffer.auto_up()
124
126
125
127
126 def next_history_or_next_completion(event):
128 def next_history_or_next_completion(event):
127 """
129 """
128 Control-N in vi edit mode on readline is history previous, unlike default prompt toolkit.
130 Control-N in vi edit mode on readline is history previous, unlike default prompt toolkit.
129
131
130 If completer is open this still select next completion.
132 If completer is open this still select next completion.
131 """
133 """
132 event.current_buffer.auto_down()
134 event.current_buffer.auto_down()
133
135
134
136
135 def dismiss_completion(event):
137 def dismiss_completion(event):
136 b = event.current_buffer
138 b = event.current_buffer
137 if b.complete_state:
139 if b.complete_state:
138 b.cancel_completion()
140 b.cancel_completion()
139
141
140
142
141 def reset_buffer(event):
143 def reset_buffer(event):
142 b = event.current_buffer
144 b = event.current_buffer
143 if b.complete_state:
145 if b.complete_state:
144 b.cancel_completion()
146 b.cancel_completion()
145 else:
147 else:
146 b.reset()
148 b.reset()
147
149
148
150
149 def reset_search_buffer(event):
151 def reset_search_buffer(event):
150 if event.current_buffer.document.text:
152 if event.current_buffer.document.text:
151 event.current_buffer.reset()
153 event.current_buffer.reset()
152 else:
154 else:
153 event.cli.push_focus(DEFAULT_BUFFER)
155 event.cli.push_focus(DEFAULT_BUFFER)
154
156
155 def suspend_to_bg(event):
157 def suspend_to_bg(event):
156 event.cli.suspend_to_background()
158 event.cli.suspend_to_background()
157
159
158 def force_exit(event):
160 def force_exit(event):
159 """
161 """
160 Force exit (with a non-zero return value)
162 Force exit (with a non-zero return value)
161 """
163 """
162 sys.exit("Quit")
164 sys.exit("Quit")
163
165
164 def indent_buffer(event):
166 def indent_buffer(event):
165 event.current_buffer.insert_text(' ' * 4)
167 event.current_buffer.insert_text(' ' * 4)
166
168
167 def newline_with_copy_margin(event):
169 def newline_with_copy_margin(event):
168 """
170 """
169 Preserve margin and cursor position when using
171 Preserve margin and cursor position when using
170 Control-O to insert a newline in EMACS mode
172 Control-O to insert a newline in EMACS mode
171 """
173 """
172 b = event.current_buffer
174 b = event.current_buffer
173 cursor_start_pos = b.document.cursor_position_col
175 cursor_start_pos = b.document.cursor_position_col
174 b.newline(copy_margin=True)
176 b.newline(copy_margin=True)
175 b.cursor_up(count=1)
177 b.cursor_up(count=1)
176 cursor_end_pos = b.document.cursor_position_col
178 cursor_end_pos = b.document.cursor_position_col
177 if cursor_start_pos != cursor_end_pos:
179 if cursor_start_pos != cursor_end_pos:
178 pos_diff = cursor_start_pos - cursor_end_pos
180 pos_diff = cursor_start_pos - cursor_end_pos
179 b.cursor_right(count=pos_diff)
181 b.cursor_right(count=pos_diff)
180
182
181 def open_input_in_editor(event):
183 def open_input_in_editor(event):
182 event.cli.current_buffer.tempfile_suffix = ".py"
184 event.cli.current_buffer.tempfile_suffix = ".py"
183 event.cli.current_buffer.open_in_editor(event.cli)
185 event.cli.current_buffer.open_in_editor(event.cli)
184
186
185
187
186 if sys.platform == 'win32':
188 if sys.platform == 'win32':
187 from IPython.core.error import TryNext
189 from IPython.core.error import TryNext
188 from IPython.lib.clipboard import (ClipboardEmpty,
190 from IPython.lib.clipboard import (ClipboardEmpty,
189 win32_clipboard_get,
191 win32_clipboard_get,
190 tkinter_clipboard_get)
192 tkinter_clipboard_get)
191
193
192 @undoc
194 @undoc
193 def win_paste(event):
195 def win_paste(event):
194 try:
196 try:
195 text = win32_clipboard_get()
197 text = win32_clipboard_get()
196 except TryNext:
198 except TryNext:
197 try:
199 try:
198 text = tkinter_clipboard_get()
200 text = tkinter_clipboard_get()
199 except (TryNext, ClipboardEmpty):
201 except (TryNext, ClipboardEmpty):
200 return
202 return
201 except ClipboardEmpty:
203 except ClipboardEmpty:
202 return
204 return
203 event.current_buffer.insert_text(text.replace('\t', ' ' * 4))
205 event.current_buffer.insert_text(text.replace('\t', ' ' * 4))
General Comments 0
You need to be logged in to leave comments. Login now