##// END OF EJS Templates
preserve margins when using Ctrl-O for newline...
Gil Forsyth -
Show More
@@ -1,167 +1,185 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
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.ControlP,
30 30 filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER)
31 31 ))(previous_history_or_previous_completion)
32 32
33 33 registry.add_binding(Keys.ControlN,
34 34 filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER)
35 35 ))(next_history_or_next_completion)
36 36
37 37 registry.add_binding(Keys.ControlG,
38 38 filter=(HasFocus(DEFAULT_BUFFER) & HasCompletions()
39 39 ))(dismiss_completion)
40 40
41 41 registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER)
42 42 )(reset_buffer)
43 43
44 44 registry.add_binding(Keys.ControlC, filter=HasFocus(SEARCH_BUFFER)
45 45 )(reset_search_buffer)
46 46
47 47 supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP'))
48 48 registry.add_binding(Keys.ControlZ, filter=supports_suspend
49 49 )(suspend_to_bg)
50 50
51 51 # Ctrl+I == Tab
52 52 registry.add_binding(Keys.ControlI,
53 53 filter=(HasFocus(DEFAULT_BUFFER)
54 54 & ~HasSelection()
55 55 & insert_mode
56 56 & cursor_in_leading_ws
57 57 ))(indent_buffer)
58 58
59 registry.add_binding(Keys.ControlO,
60 filter=(HasFocus(DEFAULT_BUFFER)
61 & insert_mode))(newline_with_copy_margin)
62
59 63 if shell.display_completions == 'readlinelike':
60 64 registry.add_binding(Keys.ControlI,
61 65 filter=(HasFocus(DEFAULT_BUFFER)
62 66 & ~HasSelection()
63 67 & insert_mode
64 68 & ~cursor_in_leading_ws
65 69 ))(display_completions_like_readline)
66 70
67 71 if sys.platform == 'win32':
68 72 registry.add_binding(Keys.ControlV,
69 73 filter=(
70 74 HasFocus(
71 75 DEFAULT_BUFFER) & ~ViMode()
72 76 ))(win_paste)
73 77
74 78
75 79 def newline_or_execute_outer(shell):
76 80 def newline_or_execute(event):
77 81 """When the user presses return, insert a newline or execute the code."""
78 82 b = event.current_buffer
79 83 d = b.document
80 84
81 85 if b.complete_state:
82 86 cc = b.complete_state.current_completion
83 87 if cc:
84 88 b.apply_completion(cc)
85 89 else:
86 90 b.cancel_completion()
87 91 return
88 92
89 93 if not (d.on_last_line or d.cursor_position_row >= d.line_count
90 94 - d.empty_line_count_at_the_end()):
91 95 b.newline()
92 96 return
93 97
94 98 status, indent = shell.input_splitter.check_complete(d.text + '\n')
95 99
96 100 if (status != 'incomplete') and b.accept_action.is_returnable:
97 101 b.accept_action.validate_and_handle(event.cli, b)
98 102 else:
99 103 b.insert_text('\n' + (' ' * (indent or 0)))
100 104 return newline_or_execute
101 105
102 106
103 107 def previous_history_or_previous_completion(event):
104 108 """
105 109 Control-P in vi edit mode on readline is history next, unlike default prompt toolkit.
106 110
107 111 If completer is open this still select previous completion.
108 112 """
109 113 event.current_buffer.auto_up()
110 114
111 115
112 116 def next_history_or_next_completion(event):
113 117 """
114 118 Control-N in vi edit mode on readline is history previous, unlike default prompt toolkit.
115 119
116 120 If completer is open this still select next completion.
117 121 """
118 122 event.current_buffer.auto_down()
119 123
120 124
121 125 def dismiss_completion(event):
122 126 b = event.current_buffer
123 127 if b.complete_state:
124 128 b.cancel_completion()
125 129
126 130
127 131 def reset_buffer(event):
128 132 b = event.current_buffer
129 133 if b.complete_state:
130 134 b.cancel_completion()
131 135 else:
132 136 b.reset()
133 137
134 138
135 139 def reset_search_buffer(event):
136 140 if event.current_buffer.document.text:
137 141 event.current_buffer.reset()
138 142 else:
139 143 event.cli.push_focus(DEFAULT_BUFFER)
140 144
141 145 def suspend_to_bg(event):
142 146 event.cli.suspend_to_background()
143 147
144 148 def indent_buffer(event):
145 149 event.current_buffer.insert_text(' ' * 4)
146 150
151 def newline_with_copy_margin(event):
152 """
153 Preserve margin and cursor position when using
154 Control-O to insert a newline in EMACS mode
155 """
156 b = event.current_buffer
157 cursor_start_pos = b.document.cursor_position_col
158 b.newline(copy_margin=True)
159 b.cursor_up(count=1)
160 cursor_end_pos = b.document.cursor_position_col
161 if cursor_start_pos != cursor_end_pos:
162 pos_diff = cursor_start_pos - cursor_end_pos
163 b.cursor_right(count=pos_diff)
164
147 165
148 166
149 167
150 168 if sys.platform == 'win32':
151 169 from IPython.core.error import TryNext
152 170 from IPython.lib.clipboard import (ClipboardEmpty,
153 171 win32_clipboard_get,
154 172 tkinter_clipboard_get)
155 173
156 174 @undoc
157 175 def win_paste(event):
158 176 try:
159 177 text = win32_clipboard_get()
160 178 except TryNext:
161 179 try:
162 180 text = tkinter_clipboard_get()
163 181 except (TryNext, ClipboardEmpty):
164 182 return
165 183 except ClipboardEmpty:
166 184 return
167 185 event.current_buffer.insert_text(text.replace('\t', ' ' * 4))
General Comments 0
You need to be logged in to leave comments. Login now