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