##// END OF EJS Templates
Remove readline mention, fit IPython typo.
Matthias Bussonnier -
Show More
@@ -1,589 +1,589 b''
1 """IPython terminal interface using prompt_toolkit in place of readline"""
1 """IPython terminal interface using prompt_toolkit"""
2 from __future__ import print_function
2 from __future__ import print_function
3
3
4 import os
4 import os
5 import sys
5 import sys
6 import signal
6 import signal
7 from warnings import warn
7 from warnings import warn
8
8
9 from IPython.core.error import TryNext
9 from IPython.core.error import TryNext
10 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
10 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
11 from IPython.utils.py3compat import PY3, cast_unicode_py2, input
11 from IPython.utils.py3compat import PY3, cast_unicode_py2, input
12 from IPython.utils.terminal import toggle_set_term_title, set_term_title
12 from IPython.utils.terminal import toggle_set_term_title, set_term_title
13 from IPython.utils.process import abbrev_cwd
13 from IPython.utils.process import abbrev_cwd
14 from traitlets import Bool, Unicode, Dict, Integer, observe, Instance, Type, default, Enum
14 from traitlets import Bool, Unicode, Dict, Integer, observe, Instance, Type, default, Enum
15
15
16 from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER, EditingMode
16 from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER, EditingMode
17 from prompt_toolkit.filters import (HasFocus, HasSelection, Condition,
17 from prompt_toolkit.filters import (HasFocus, HasSelection, Condition,
18 ViInsertMode, EmacsInsertMode, IsDone, HasCompletions)
18 ViInsertMode, EmacsInsertMode, IsDone, HasCompletions)
19 from prompt_toolkit.filters.cli import ViMode
19 from prompt_toolkit.filters.cli import ViMode
20 from prompt_toolkit.history import InMemoryHistory
20 from prompt_toolkit.history import InMemoryHistory
21 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout
21 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout
22 from prompt_toolkit.interface import CommandLineInterface
22 from prompt_toolkit.interface import CommandLineInterface
23 from prompt_toolkit.key_binding.manager import KeyBindingManager
23 from prompt_toolkit.key_binding.manager import KeyBindingManager
24 from prompt_toolkit.keys import Keys
24 from prompt_toolkit.keys import Keys
25 from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
25 from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
26 from prompt_toolkit.styles import PygmentsStyle, DynamicStyle
26 from prompt_toolkit.styles import PygmentsStyle, DynamicStyle
27 from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline
27 from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline
28
28
29 from pygments.styles import get_style_by_name, get_all_styles
29 from pygments.styles import get_style_by_name, get_all_styles
30 from pygments.token import Token
30 from pygments.token import Token
31
31
32 from .debugger import TerminalPdb, Pdb
32 from .debugger import TerminalPdb, Pdb
33 from .magics import TerminalMagics
33 from .magics import TerminalMagics
34 from .pt_inputhooks import get_inputhook_func
34 from .pt_inputhooks import get_inputhook_func
35 from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
35 from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
36 from .ptutils import IPythonPTCompleter, IPythonPTLexer
36 from .ptutils import IPythonPTCompleter, IPythonPTLexer
37
37
38
38
39 def get_default_editor():
39 def get_default_editor():
40 try:
40 try:
41 ed = os.environ['EDITOR']
41 ed = os.environ['EDITOR']
42 if not PY3:
42 if not PY3:
43 ed = ed.decode()
43 ed = ed.decode()
44 return ed
44 return ed
45 except KeyError:
45 except KeyError:
46 pass
46 pass
47 except UnicodeError:
47 except UnicodeError:
48 warn("$EDITOR environment variable is not pure ASCII. Using platform "
48 warn("$EDITOR environment variable is not pure ASCII. Using platform "
49 "default editor.")
49 "default editor.")
50
50
51 if os.name == 'posix':
51 if os.name == 'posix':
52 return 'vi' # the only one guaranteed to be there!
52 return 'vi' # the only one guaranteed to be there!
53 else:
53 else:
54 return 'notepad' # same in Windows!
54 return 'notepad' # same in Windows!
55
55
56
56
57 if sys.stdin and sys.stdout and sys.stderr:
57 if sys.stdin and sys.stdout and sys.stderr:
58 _is_tty = (sys.stdin.isatty()) and (sys.stdout.isatty()) and (sys.stderr.isatty())
58 _is_tty = (sys.stdin.isatty()) and (sys.stdout.isatty()) and (sys.stderr.isatty())
59 else:
59 else:
60 _is_tty = False
60 _is_tty = False
61
61
62
62
63 _use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)
63 _use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)
64
64
65 class TerminalInteractiveShell(InteractiveShell):
65 class TerminalInteractiveShell(InteractiveShell):
66 colors_force = True
66 colors_force = True
67
67
68 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
68 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
69 'to reserve for the completion menu'
69 'to reserve for the completion menu'
70 ).tag(config=True)
70 ).tag(config=True)
71
71
72 def _space_for_menu_changed(self, old, new):
72 def _space_for_menu_changed(self, old, new):
73 self._update_layout()
73 self._update_layout()
74
74
75 pt_cli = None
75 pt_cli = None
76 debugger_history = None
76 debugger_history = None
77
77
78 simple_prompt = Bool(_use_simple_prompt,
78 simple_prompt = Bool(_use_simple_prompt,
79 help="""Use `raw_input` for the REPL, without completion, multiline input, and prompt colors.
79 help="""Use `raw_input` for the REPL, without completion, multiline input, and prompt colors.
80
80
81 Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are:
81 Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are:
82 IPython own testing machinery, and emacs inferior-shell integration through elpy.
82 IPython own testing machinery, and emacs inferior-shell integration through elpy.
83
83
84 This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT`
84 This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT`
85 environment variable is set, or the current terminal is not a tty.
85 environment variable is set, or the current terminal is not a tty.
86
86
87 """
87 """
88 ).tag(config=True)
88 ).tag(config=True)
89
89
90 @property
90 @property
91 def debugger_cls(self):
91 def debugger_cls(self):
92 return Pdb if self.simple_prompt else TerminalPdb
92 return Pdb if self.simple_prompt else TerminalPdb
93
93
94 autoedit_syntax = Bool(False,
94 autoedit_syntax = Bool(False,
95 help="auto editing of files with syntax errors.",
95 help="auto editing of files with syntax errors.",
96 ).tag(config=True)
96 ).tag(config=True)
97
97
98
98
99 confirm_exit = Bool(True,
99 confirm_exit = Bool(True,
100 help="""
100 help="""
101 Set to confirm when you try to exit IPython with an EOF (Control-D
101 Set to confirm when you try to exit IPython with an EOF (Control-D
102 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
102 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
103 you can force a direct exit without any confirmation.""",
103 you can force a direct exit without any confirmation.""",
104 ).tag(config=True)
104 ).tag(config=True)
105
105
106 editing_mode = Unicode('emacs',
106 editing_mode = Unicode('emacs',
107 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
107 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
108 ).tag(config=True)
108 ).tag(config=True)
109
109
110 mouse_support = Bool(False,
110 mouse_support = Bool(False,
111 help="Enable mouse support in the prompt"
111 help="Enable mouse support in the prompt"
112 ).tag(config=True)
112 ).tag(config=True)
113
113
114 highlighting_style = Unicode('default',
114 highlighting_style = Unicode('default',
115 help="The name of a Pygments style to use for syntax highlighting: \n %s" % ', '.join(get_all_styles())
115 help="The name of a Pygments style to use for syntax highlighting: \n %s" % ', '.join(get_all_styles())
116 ).tag(config=True)
116 ).tag(config=True)
117
117
118
118
119 @observe('highlighting_style')
119 @observe('highlighting_style')
120 def _highlighting_style_changed(self, change):
120 def _highlighting_style_changed(self, change):
121 self._style = self._make_style_from_name(self.highlighting_style)
121 self._style = self._make_style_from_name(self.highlighting_style)
122
122
123 highlighting_style_overrides = Dict(
123 highlighting_style_overrides = Dict(
124 help="Override highlighting format for specific tokens"
124 help="Override highlighting format for specific tokens"
125 ).tag(config=True)
125 ).tag(config=True)
126
126
127 editor = Unicode(get_default_editor(),
127 editor = Unicode(get_default_editor(),
128 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
128 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
129 ).tag(config=True)
129 ).tag(config=True)
130
130
131 prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True)
131 prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True)
132
132
133 prompts = Instance(Prompts)
133 prompts = Instance(Prompts)
134
134
135 @default('prompts')
135 @default('prompts')
136 def _prompts_default(self):
136 def _prompts_default(self):
137 return self.prompts_class(self)
137 return self.prompts_class(self)
138
138
139 @observe('prompts')
139 @observe('prompts')
140 def _(self, change):
140 def _(self, change):
141 self._update_layout()
141 self._update_layout()
142
142
143 @default('displayhook_class')
143 @default('displayhook_class')
144 def _displayhook_class_default(self):
144 def _displayhook_class_default(self):
145 return RichPromptDisplayHook
145 return RichPromptDisplayHook
146
146
147 term_title = Bool(True,
147 term_title = Bool(True,
148 help="Automatically set the terminal title"
148 help="Automatically set the terminal title"
149 ).tag(config=True)
149 ).tag(config=True)
150
150
151 display_completions_in_columns = Bool(None,
151 display_completions_in_columns = Bool(None,
152 help="Display a multi column completion menu.", allow_none=True
152 help="Display a multi column completion menu.", allow_none=True
153 ).tag(config=True)
153 ).tag(config=True)
154
154
155 @observe('display_completions_in_columns')
155 @observe('display_completions_in_columns')
156 def _display_completions_in_columns_changed(self, new):
156 def _display_completions_in_columns_changed(self, new):
157 raise DeprecationWarning("The `display_completions_in_columns` Boolean has been replaced by the enum `display_completions`"
157 raise DeprecationWarning("The `display_completions_in_columns` Boolean has been replaced by the enum `display_completions`"
158 "with the following acceptable value: 'column', 'multicolumn','readlinelike'. ")
158 "with the following acceptable value: 'column', 'multicolumn','readlinelike'. ")
159
159
160 display_completions = Enum(('column', 'multicolumn','readlinelike'), default_value='multicolumn').tag(config=True)
160 display_completions = Enum(('column', 'multicolumn','readlinelike'), default_value='multicolumn').tag(config=True)
161
161
162 highlight_matching_brackets = Bool(True,
162 highlight_matching_brackets = Bool(True,
163 help="Highlight matching brackets .",
163 help="Highlight matching brackets .",
164 ).tag(config=True)
164 ).tag(config=True)
165
165
166 @observe('term_title')
166 @observe('term_title')
167 def init_term_title(self, change=None):
167 def init_term_title(self, change=None):
168 # Enable or disable the terminal title.
168 # Enable or disable the terminal title.
169 if self.term_title:
169 if self.term_title:
170 toggle_set_term_title(True)
170 toggle_set_term_title(True)
171 set_term_title('IPython: ' + abbrev_cwd())
171 set_term_title('IPython: ' + abbrev_cwd())
172 else:
172 else:
173 toggle_set_term_title(False)
173 toggle_set_term_title(False)
174
174
175 def init_display_formatter(self):
175 def init_display_formatter(self):
176 super(TerminalInteractiveShell, self).init_display_formatter()
176 super(TerminalInteractiveShell, self).init_display_formatter()
177 # terminal only supports plain text
177 # terminal only supports plain text
178 self.display_formatter.active_types = ['text/plain']
178 self.display_formatter.active_types = ['text/plain']
179
179
180 def init_prompt_toolkit_cli(self):
180 def init_prompt_toolkit_cli(self):
181 self._app = None
181 self._app = None
182 if self.simple_prompt:
182 if self.simple_prompt:
183 # Fall back to plain non-interactive output for tests.
183 # Fall back to plain non-interactive output for tests.
184 # This is very limited, and only accepts a single line.
184 # This is very limited, and only accepts a single line.
185 def prompt():
185 def prompt():
186 return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
186 return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
187 self.prompt_for_code = prompt
187 self.prompt_for_code = prompt
188 return
188 return
189
189
190 kbmanager = KeyBindingManager.for_prompt()
190 kbmanager = KeyBindingManager.for_prompt()
191 insert_mode = ViInsertMode() | EmacsInsertMode()
191 insert_mode = ViInsertMode() | EmacsInsertMode()
192 # Ctrl+J == Enter, seemingly
192 # Ctrl+J == Enter, seemingly
193 @kbmanager.registry.add_binding(Keys.ControlJ,
193 @kbmanager.registry.add_binding(Keys.ControlJ,
194 filter=(HasFocus(DEFAULT_BUFFER)
194 filter=(HasFocus(DEFAULT_BUFFER)
195 & ~HasSelection()
195 & ~HasSelection()
196 & insert_mode
196 & insert_mode
197 ))
197 ))
198 def _(event):
198 def _(event):
199 b = event.current_buffer
199 b = event.current_buffer
200 d = b.document
200 d = b.document
201
201
202 if b.complete_state:
202 if b.complete_state:
203 cc = b.complete_state.current_completion
203 cc = b.complete_state.current_completion
204 if cc:
204 if cc:
205 b.apply_completion(cc)
205 b.apply_completion(cc)
206 else:
206 else:
207 b.cancel_completion()
207 b.cancel_completion()
208 return
208 return
209
209
210 if not (d.on_last_line or d.cursor_position_row >= d.line_count
210 if not (d.on_last_line or d.cursor_position_row >= d.line_count
211 - d.empty_line_count_at_the_end()):
211 - d.empty_line_count_at_the_end()):
212 b.newline()
212 b.newline()
213 return
213 return
214
214
215 status, indent = self.input_splitter.check_complete(d.text + '\n')
215 status, indent = self.input_splitter.check_complete(d.text + '\n')
216
216
217 if (status != 'incomplete') and b.accept_action.is_returnable:
217 if (status != 'incomplete') and b.accept_action.is_returnable:
218 b.accept_action.validate_and_handle(event.cli, b)
218 b.accept_action.validate_and_handle(event.cli, b)
219 else:
219 else:
220 b.insert_text('\n' + (' ' * (indent or 0)))
220 b.insert_text('\n' + (' ' * (indent or 0)))
221
221
222 @kbmanager.registry.add_binding(Keys.ControlP, filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER)))
222 @kbmanager.registry.add_binding(Keys.ControlP, filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER)))
223 def _previous_history_or_previous_completion(event):
223 def _previous_history_or_previous_completion(event):
224 """
224 """
225 Control-P in vi edit mode on readline is history next, unlike default prompt toolkit.
225 Control-P in vi edit mode on readline is history next, unlike default prompt toolkit.
226
226
227 If completer is open this still select previous completion.
227 If completer is open this still select previous completion.
228 """
228 """
229 event.current_buffer.auto_up()
229 event.current_buffer.auto_up()
230
230
231 @kbmanager.registry.add_binding(Keys.ControlN, filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER)))
231 @kbmanager.registry.add_binding(Keys.ControlN, filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER)))
232 def _next_history_or_next_completion(event):
232 def _next_history_or_next_completion(event):
233 """
233 """
234 Control-N in vi edit mode on readline is history previous, unlike default prompt toolkit.
234 Control-N in vi edit mode on readline is history previous, unlike default prompt toolkit.
235
235
236 If completer is open this still select next completion.
236 If completer is open this still select next completion.
237 """
237 """
238 event.current_buffer.auto_down()
238 event.current_buffer.auto_down()
239
239
240 @kbmanager.registry.add_binding(Keys.ControlG, filter=(
240 @kbmanager.registry.add_binding(Keys.ControlG, filter=(
241 HasFocus(DEFAULT_BUFFER) & HasCompletions()
241 HasFocus(DEFAULT_BUFFER) & HasCompletions()
242 ))
242 ))
243 def _dismiss_completion(event):
243 def _dismiss_completion(event):
244 b = event.current_buffer
244 b = event.current_buffer
245 if b.complete_state:
245 if b.complete_state:
246 b.cancel_completion()
246 b.cancel_completion()
247
247
248 @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER))
248 @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER))
249 def _reset_buffer(event):
249 def _reset_buffer(event):
250 b = event.current_buffer
250 b = event.current_buffer
251 if b.complete_state:
251 if b.complete_state:
252 b.cancel_completion()
252 b.cancel_completion()
253 else:
253 else:
254 b.reset()
254 b.reset()
255
255
256 @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(SEARCH_BUFFER))
256 @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(SEARCH_BUFFER))
257 def _reset_search_buffer(event):
257 def _reset_search_buffer(event):
258 if event.current_buffer.document.text:
258 if event.current_buffer.document.text:
259 event.current_buffer.reset()
259 event.current_buffer.reset()
260 else:
260 else:
261 event.cli.push_focus(DEFAULT_BUFFER)
261 event.cli.push_focus(DEFAULT_BUFFER)
262
262
263 supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP'))
263 supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP'))
264
264
265 @kbmanager.registry.add_binding(Keys.ControlZ, filter=supports_suspend)
265 @kbmanager.registry.add_binding(Keys.ControlZ, filter=supports_suspend)
266 def _suspend_to_bg(event):
266 def _suspend_to_bg(event):
267 event.cli.suspend_to_background()
267 event.cli.suspend_to_background()
268
268
269 @Condition
269 @Condition
270 def cursor_in_leading_ws(cli):
270 def cursor_in_leading_ws(cli):
271 before = cli.application.buffer.document.current_line_before_cursor
271 before = cli.application.buffer.document.current_line_before_cursor
272 return (not before) or before.isspace()
272 return (not before) or before.isspace()
273
273
274 # Ctrl+I == Tab
274 # Ctrl+I == Tab
275 @kbmanager.registry.add_binding(Keys.ControlI,
275 @kbmanager.registry.add_binding(Keys.ControlI,
276 filter=(HasFocus(DEFAULT_BUFFER)
276 filter=(HasFocus(DEFAULT_BUFFER)
277 & ~HasSelection()
277 & ~HasSelection()
278 & insert_mode
278 & insert_mode
279 & cursor_in_leading_ws
279 & cursor_in_leading_ws
280 ))
280 ))
281 def _indent_buffer(event):
281 def _indent_buffer(event):
282 event.current_buffer.insert_text(' ' * 4)
282 event.current_buffer.insert_text(' ' * 4)
283
283
284
284
285 if self.display_completions == 'readlinelike':
285 if self.display_completions == 'readlinelike':
286 @kbmanager.registry.add_binding(Keys.ControlI,
286 @kbmanager.registry.add_binding(Keys.ControlI,
287 filter=(HasFocus(DEFAULT_BUFFER)
287 filter=(HasFocus(DEFAULT_BUFFER)
288 & ~HasSelection()
288 & ~HasSelection()
289 & insert_mode
289 & insert_mode
290 & ~cursor_in_leading_ws
290 & ~cursor_in_leading_ws
291 ))
291 ))
292 def _disaply_compl(ev):
292 def _disaply_compl(ev):
293 display_completions_like_readline(ev)
293 display_completions_like_readline(ev)
294
294
295
295
296 if sys.platform == 'win32':
296 if sys.platform == 'win32':
297 from IPython.lib.clipboard import (ClipboardEmpty,
297 from IPython.lib.clipboard import (ClipboardEmpty,
298 win32_clipboard_get, tkinter_clipboard_get)
298 win32_clipboard_get, tkinter_clipboard_get)
299 @kbmanager.registry.add_binding(Keys.ControlV,
299 @kbmanager.registry.add_binding(Keys.ControlV,
300 filter=(HasFocus(DEFAULT_BUFFER) & ~ViMode()))
300 filter=(HasFocus(DEFAULT_BUFFER) & ~ViMode()))
301 def _paste(event):
301 def _paste(event):
302 try:
302 try:
303 text = win32_clipboard_get()
303 text = win32_clipboard_get()
304 except TryNext:
304 except TryNext:
305 try:
305 try:
306 text = tkinter_clipboard_get()
306 text = tkinter_clipboard_get()
307 except (TryNext, ClipboardEmpty):
307 except (TryNext, ClipboardEmpty):
308 return
308 return
309 except ClipboardEmpty:
309 except ClipboardEmpty:
310 return
310 return
311 event.current_buffer.insert_text(text.replace('\t', ' ' * 4))
311 event.current_buffer.insert_text(text.replace('\t', ' ' * 4))
312
312
313 # Pre-populate history from IPython's history database
313 # Pre-populate history from IPython's history database
314 history = InMemoryHistory()
314 history = InMemoryHistory()
315 last_cell = u""
315 last_cell = u""
316 for __, ___, cell in self.history_manager.get_tail(self.history_load_length,
316 for __, ___, cell in self.history_manager.get_tail(self.history_load_length,
317 include_latest=True):
317 include_latest=True):
318 # Ignore blank lines and consecutive duplicates
318 # Ignore blank lines and consecutive duplicates
319 cell = cell.rstrip()
319 cell = cell.rstrip()
320 if cell and (cell != last_cell):
320 if cell and (cell != last_cell):
321 history.append(cell)
321 history.append(cell)
322
322
323 self._style = self._make_style_from_name(self.highlighting_style)
323 self._style = self._make_style_from_name(self.highlighting_style)
324 style = DynamicStyle(lambda: self._style)
324 style = DynamicStyle(lambda: self._style)
325
325
326 editing_mode = getattr(EditingMode, self.editing_mode.upper())
326 editing_mode = getattr(EditingMode, self.editing_mode.upper())
327
327
328 self._app = create_prompt_application(
328 self._app = create_prompt_application(
329 editing_mode=editing_mode,
329 editing_mode=editing_mode,
330 key_bindings_registry=kbmanager.registry,
330 key_bindings_registry=kbmanager.registry,
331 history=history,
331 history=history,
332 completer=IPythonPTCompleter(self.Completer),
332 completer=IPythonPTCompleter(self.Completer),
333 enable_history_search=True,
333 enable_history_search=True,
334 style=style,
334 style=style,
335 mouse_support=self.mouse_support,
335 mouse_support=self.mouse_support,
336 **self._layout_options()
336 **self._layout_options()
337 )
337 )
338 self._eventloop = create_eventloop(self.inputhook)
338 self._eventloop = create_eventloop(self.inputhook)
339 self.pt_cli = CommandLineInterface(self._app, eventloop=self._eventloop)
339 self.pt_cli = CommandLineInterface(self._app, eventloop=self._eventloop)
340
340
341 def _make_style_from_name(self, name):
341 def _make_style_from_name(self, name):
342 """
342 """
343 Small wrapper that make an IPython compatible style from a style name
343 Small wrapper that make an IPython compatible style from a style name
344
344
345 We need that to add style for prompt ... etc.
345 We need that to add style for prompt ... etc.
346 """
346 """
347 style_cls = get_style_by_name(name)
347 style_cls = get_style_by_name(name)
348 style_overrides = {
348 style_overrides = {
349 Token.Prompt: '#009900',
349 Token.Prompt: '#009900',
350 Token.PromptNum: '#00ff00 bold',
350 Token.PromptNum: '#00ff00 bold',
351 Token.OutPrompt: '#990000',
351 Token.OutPrompt: '#990000',
352 Token.OutPromptNum: '#ff0000 bold',
352 Token.OutPromptNum: '#ff0000 bold',
353 }
353 }
354 if name == 'default':
354 if name == 'default':
355 style_cls = get_style_by_name('default')
355 style_cls = get_style_by_name('default')
356 # The default theme needs to be visible on both a dark background
356 # The default theme needs to be visible on both a dark background
357 # and a light background, because we can't tell what the terminal
357 # and a light background, because we can't tell what the terminal
358 # looks like. These tweaks to the default theme help with that.
358 # looks like. These tweaks to the default theme help with that.
359 style_overrides.update({
359 style_overrides.update({
360 Token.Number: '#007700',
360 Token.Number: '#007700',
361 Token.Operator: 'noinherit',
361 Token.Operator: 'noinherit',
362 Token.String: '#BB6622',
362 Token.String: '#BB6622',
363 Token.Name.Function: '#2080D0',
363 Token.Name.Function: '#2080D0',
364 Token.Name.Class: 'bold #2080D0',
364 Token.Name.Class: 'bold #2080D0',
365 Token.Name.Namespace: 'bold #2080D0',
365 Token.Name.Namespace: 'bold #2080D0',
366 })
366 })
367 style_overrides.update(self.highlighting_style_overrides)
367 style_overrides.update(self.highlighting_style_overrides)
368 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
368 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
369 style_dict=style_overrides)
369 style_dict=style_overrides)
370
370
371 return style
371 return style
372
372
373 def _layout_options(self):
373 def _layout_options(self):
374 """
374 """
375 Return the current layout option for the current Terminal InteractiveShell
375 Return the current layout option for the current Terminal InteractiveShell
376 """
376 """
377 return {
377 return {
378 'lexer':IPythonPTLexer(),
378 'lexer':IPythonPTLexer(),
379 'reserve_space_for_menu':self.space_for_menu,
379 'reserve_space_for_menu':self.space_for_menu,
380 'get_prompt_tokens':self.prompts.in_prompt_tokens,
380 'get_prompt_tokens':self.prompts.in_prompt_tokens,
381 'get_continuation_tokens':self.prompts.continuation_prompt_tokens,
381 'get_continuation_tokens':self.prompts.continuation_prompt_tokens,
382 'multiline':True,
382 'multiline':True,
383 'display_completions_in_columns': (self.display_completions == 'multicolumn'),
383 'display_completions_in_columns': (self.display_completions == 'multicolumn'),
384
384
385 # Highlight matching brackets, but only when this setting is
385 # Highlight matching brackets, but only when this setting is
386 # enabled, and only when the DEFAULT_BUFFER has the focus.
386 # enabled, and only when the DEFAULT_BUFFER has the focus.
387 'extra_input_processors': [ConditionalProcessor(
387 'extra_input_processors': [ConditionalProcessor(
388 processor=HighlightMatchingBracketProcessor(chars='[](){}'),
388 processor=HighlightMatchingBracketProcessor(chars='[](){}'),
389 filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
389 filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
390 Condition(lambda cli: self.highlight_matching_brackets))],
390 Condition(lambda cli: self.highlight_matching_brackets))],
391 }
391 }
392
392
393 def _update_layout(self):
393 def _update_layout(self):
394 """
394 """
395 Ask for a re computation of the application layout, if for example ,
395 Ask for a re computation of the application layout, if for example ,
396 some configuration options have changed.
396 some configuration options have changed.
397 """
397 """
398 if getattr(self, '._app', None):
398 if getattr(self, '._app', None):
399 self._app.layout = create_prompt_layout(**self._layout_options())
399 self._app.layout = create_prompt_layout(**self._layout_options())
400
400
401 def prompt_for_code(self):
401 def prompt_for_code(self):
402 document = self.pt_cli.run(
402 document = self.pt_cli.run(
403 pre_run=self.pre_prompt, reset_current_buffer=True)
403 pre_run=self.pre_prompt, reset_current_buffer=True)
404 return document.text
404 return document.text
405
405
406 def init_io(self):
406 def init_io(self):
407 if sys.platform not in {'win32', 'cli'}:
407 if sys.platform not in {'win32', 'cli'}:
408 return
408 return
409
409
410 import win_unicode_console
410 import win_unicode_console
411 import colorama
411 import colorama
412
412
413 win_unicode_console.enable()
413 win_unicode_console.enable()
414 colorama.init()
414 colorama.init()
415
415
416 # For some reason we make these wrappers around stdout/stderr.
416 # For some reason we make these wrappers around stdout/stderr.
417 # For now, we need to reset them so all output gets coloured.
417 # For now, we need to reset them so all output gets coloured.
418 # https://github.com/ipython/ipython/issues/8669
418 # https://github.com/ipython/ipython/issues/8669
419 from IPython.utils import io
419 from IPython.utils import io
420 io.stdout = io.IOStream(sys.stdout)
420 io.stdout = io.IOStream(sys.stdout)
421 io.stderr = io.IOStream(sys.stderr)
421 io.stderr = io.IOStream(sys.stderr)
422
422
423 def init_magics(self):
423 def init_magics(self):
424 super(TerminalInteractiveShell, self).init_magics()
424 super(TerminalInteractiveShell, self).init_magics()
425 self.register_magics(TerminalMagics)
425 self.register_magics(TerminalMagics)
426
426
427 def init_alias(self):
427 def init_alias(self):
428 # The parent class defines aliases that can be safely used with any
428 # The parent class defines aliases that can be safely used with any
429 # frontend.
429 # frontend.
430 super(TerminalInteractiveShell, self).init_alias()
430 super(TerminalInteractiveShell, self).init_alias()
431
431
432 # Now define aliases that only make sense on the terminal, because they
432 # Now define aliases that only make sense on the terminal, because they
433 # need direct access to the console in a way that we can't emulate in
433 # need direct access to the console in a way that we can't emulate in
434 # GUI or web frontend
434 # GUI or web frontend
435 if os.name == 'posix':
435 if os.name == 'posix':
436 for cmd in ['clear', 'more', 'less', 'man']:
436 for cmd in ['clear', 'more', 'less', 'man']:
437 self.alias_manager.soft_define_alias(cmd, cmd)
437 self.alias_manager.soft_define_alias(cmd, cmd)
438
438
439
439
440 def __init__(self, *args, **kwargs):
440 def __init__(self, *args, **kwargs):
441 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
441 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
442 self.init_prompt_toolkit_cli()
442 self.init_prompt_toolkit_cli()
443 self.init_term_title()
443 self.init_term_title()
444 self.keep_running = True
444 self.keep_running = True
445
445
446 self.debugger_history = InMemoryHistory()
446 self.debugger_history = InMemoryHistory()
447
447
448 def ask_exit(self):
448 def ask_exit(self):
449 self.keep_running = False
449 self.keep_running = False
450
450
451 rl_next_input = None
451 rl_next_input = None
452
452
453 def pre_prompt(self):
453 def pre_prompt(self):
454 if self.rl_next_input:
454 if self.rl_next_input:
455 self.pt_cli.application.buffer.text = cast_unicode_py2(self.rl_next_input)
455 self.pt_cli.application.buffer.text = cast_unicode_py2(self.rl_next_input)
456 self.rl_next_input = None
456 self.rl_next_input = None
457
457
458 def interact(self):
458 def interact(self):
459 while self.keep_running:
459 while self.keep_running:
460 print(self.separate_in, end='')
460 print(self.separate_in, end='')
461
461
462 try:
462 try:
463 code = self.prompt_for_code()
463 code = self.prompt_for_code()
464 except EOFError:
464 except EOFError:
465 if (not self.confirm_exit) \
465 if (not self.confirm_exit) \
466 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
466 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
467 self.ask_exit()
467 self.ask_exit()
468
468
469 else:
469 else:
470 if code:
470 if code:
471 self.run_cell(code, store_history=True)
471 self.run_cell(code, store_history=True)
472 if self.autoedit_syntax and self.SyntaxTB.last_syntax_error:
472 if self.autoedit_syntax and self.SyntaxTB.last_syntax_error:
473 self.edit_syntax_error()
473 self.edit_syntax_error()
474
474
475 def mainloop(self):
475 def mainloop(self):
476 # An extra layer of protection in case someone mashing Ctrl-C breaks
476 # An extra layer of protection in case someone mashing Ctrl-C breaks
477 # out of our internal code.
477 # out of our internal code.
478 while True:
478 while True:
479 try:
479 try:
480 self.interact()
480 self.interact()
481 break
481 break
482 except KeyboardInterrupt:
482 except KeyboardInterrupt:
483 print("\nKeyboardInterrupt escaped interact()\n")
483 print("\nKeyboardInterrupt escaped interact()\n")
484
484
485 if hasattr(self, '_eventloop'):
485 if hasattr(self, '_eventloop'):
486 self._eventloop.close()
486 self._eventloop.close()
487
487
488 _inputhook = None
488 _inputhook = None
489 def inputhook(self, context):
489 def inputhook(self, context):
490 if self._inputhook is not None:
490 if self._inputhook is not None:
491 self._inputhook(context)
491 self._inputhook(context)
492
492
493 def enable_gui(self, gui=None):
493 def enable_gui(self, gui=None):
494 if gui:
494 if gui:
495 self._inputhook = get_inputhook_func(gui)
495 self._inputhook = get_inputhook_func(gui)
496 else:
496 else:
497 self._inputhook = None
497 self._inputhook = None
498
498
499 # Methods to support auto-editing of SyntaxErrors:
499 # Methods to support auto-editing of SyntaxErrors:
500
500
501 def edit_syntax_error(self):
501 def edit_syntax_error(self):
502 """The bottom half of the syntax error handler called in the main loop.
502 """The bottom half of the syntax error handler called in the main loop.
503
503
504 Loop until syntax error is fixed or user cancels.
504 Loop until syntax error is fixed or user cancels.
505 """
505 """
506
506
507 while self.SyntaxTB.last_syntax_error:
507 while self.SyntaxTB.last_syntax_error:
508 # copy and clear last_syntax_error
508 # copy and clear last_syntax_error
509 err = self.SyntaxTB.clear_err_state()
509 err = self.SyntaxTB.clear_err_state()
510 if not self._should_recompile(err):
510 if not self._should_recompile(err):
511 return
511 return
512 try:
512 try:
513 # may set last_syntax_error again if a SyntaxError is raised
513 # may set last_syntax_error again if a SyntaxError is raised
514 self.safe_execfile(err.filename, self.user_ns)
514 self.safe_execfile(err.filename, self.user_ns)
515 except:
515 except:
516 self.showtraceback()
516 self.showtraceback()
517 else:
517 else:
518 try:
518 try:
519 with open(err.filename) as f:
519 with open(err.filename) as f:
520 # This should be inside a display_trap block and I
520 # This should be inside a display_trap block and I
521 # think it is.
521 # think it is.
522 sys.displayhook(f.read())
522 sys.displayhook(f.read())
523 except:
523 except:
524 self.showtraceback()
524 self.showtraceback()
525
525
526 def _should_recompile(self, e):
526 def _should_recompile(self, e):
527 """Utility routine for edit_syntax_error"""
527 """Utility routine for edit_syntax_error"""
528
528
529 if e.filename in ('<ipython console>', '<input>', '<string>',
529 if e.filename in ('<ipython console>', '<input>', '<string>',
530 '<console>', '<BackgroundJob compilation>',
530 '<console>', '<BackgroundJob compilation>',
531 None):
531 None):
532 return False
532 return False
533 try:
533 try:
534 if (self.autoedit_syntax and
534 if (self.autoedit_syntax and
535 not self.ask_yes_no(
535 not self.ask_yes_no(
536 'Return to editor to correct syntax error? '
536 'Return to editor to correct syntax error? '
537 '[Y/n] ', 'y')):
537 '[Y/n] ', 'y')):
538 return False
538 return False
539 except EOFError:
539 except EOFError:
540 return False
540 return False
541
541
542 def int0(x):
542 def int0(x):
543 try:
543 try:
544 return int(x)
544 return int(x)
545 except TypeError:
545 except TypeError:
546 return 0
546 return 0
547
547
548 # always pass integer line and offset values to editor hook
548 # always pass integer line and offset values to editor hook
549 try:
549 try:
550 self.hooks.fix_error_editor(e.filename,
550 self.hooks.fix_error_editor(e.filename,
551 int0(e.lineno), int0(e.offset),
551 int0(e.lineno), int0(e.offset),
552 e.msg)
552 e.msg)
553 except TryNext:
553 except TryNext:
554 warn('Could not open editor')
554 warn('Could not open editor')
555 return False
555 return False
556 return True
556 return True
557
557
558 # Run !system commands directly, not through pipes, so terminal programs
558 # Run !system commands directly, not through pipes, so terminal programs
559 # work correctly.
559 # work correctly.
560 system = InteractiveShell.system_raw
560 system = InteractiveShell.system_raw
561
561
562 def auto_rewrite_input(self, cmd):
562 def auto_rewrite_input(self, cmd):
563 """Overridden from the parent class to use fancy rewriting prompt"""
563 """Overridden from the parent class to use fancy rewriting prompt"""
564 if not self.show_rewritten_input:
564 if not self.show_rewritten_input:
565 return
565 return
566
566
567 tokens = self.prompts.rewrite_prompt_tokens()
567 tokens = self.prompts.rewrite_prompt_tokens()
568 if self.pt_cli:
568 if self.pt_cli:
569 self.pt_cli.print_tokens(tokens)
569 self.pt_cli.print_tokens(tokens)
570 print(cmd)
570 print(cmd)
571 else:
571 else:
572 prompt = ''.join(s for t, s in tokens)
572 prompt = ''.join(s for t, s in tokens)
573 print(prompt, cmd, sep='')
573 print(prompt, cmd, sep='')
574
574
575 _prompts_before = None
575 _prompts_before = None
576 def switch_doctest_mode(self, mode):
576 def switch_doctest_mode(self, mode):
577 """Switch prompts to classic for %doctest_mode"""
577 """Switch prompts to classic for %doctest_mode"""
578 if mode:
578 if mode:
579 self._prompts_before = self.prompts
579 self._prompts_before = self.prompts
580 self.prompts = ClassicPrompts(self)
580 self.prompts = ClassicPrompts(self)
581 elif self._prompts_before:
581 elif self._prompts_before:
582 self.prompts = self._prompts_before
582 self.prompts = self._prompts_before
583 self._prompts_before = None
583 self._prompts_before = None
584
584
585
585
586 InteractiveShellABC.register(TerminalInteractiveShell)
586 InteractiveShellABC.register(TerminalInteractiveShell)
587
587
588 if __name__ == '__main__':
588 if __name__ == '__main__':
589 TerminalInteractiveShell.instance().interact()
589 TerminalInteractiveShell.instance().interact()
@@ -1,137 +1,137 b''
1 ============
1 ============
2 5.x Series
2 5.x Series
3 ============
3 ============
4
4
5 IPython 5.0
5 IPython 5.0
6 ===========
6 ===========
7
7
8 Released June, 2016
8 Released June, 2016
9
9
10 IPython 5.0 now uses `prompt-toolkit` for the command line interface, thus
10 IPython 5.0 now uses `prompt-toolkit` for the command line interface, thus
11 allowing real multi-line editing and syntactic coloration as you type.
11 allowing real multi-line editing and syntactic coloration as you type.
12
12
13
13
14 When using IPython as a subprocess, like for emacs inferior-shell, IPython can
14 When using IPython as a subprocess, like for emacs inferior-shell, IPython can
15 be started with --simple-prompt flag, which will bypass the prompt_toolkit
15 be started with --simple-prompt flag, which will bypass the prompt_toolkit
16 input layer. In this mode completion, prompt color and many other features are
16 input layer. In this mode completion, prompt color and many other features are
17 disabled.
17 disabled.
18
18
19 Backwards incompatible changes
19 Backwards incompatible changes
20 ------------------------------
20 ------------------------------
21
21
22
22
23 The `install_ext magic` function which was deprecated since 4.0 have now been deleted.
23 The `install_ext magic` function which was deprecated since 4.0 have now been deleted.
24 You can still distribute and install extension as packages on PyPI.
24 You can still distribute and install extension as packages on PyPI.
25
25
26 Update IPython event triggering to ensure callback registration and
26 Update IPython event triggering to ensure callback registration and
27 unregistration only affects the set of callbacks the *next* time that event is
27 unregistration only affects the set of callbacks the *next* time that event is
28 triggered. See :ghissue:`9447` and :ghpull:`9453`.
28 triggered. See :ghissue:`9447` and :ghpull:`9453`.
29
29
30 This is a change to the existing semantics, wherein one callback registering a
30 This is a change to the existing semantics, wherein one callback registering a
31 second callback when triggered for an event would previously be invoked for
31 second callback when triggered for an event would previously be invoked for
32 that same event.
32 that same event.
33
33
34 Integration with pydb has been removed since pydb development has been stopped
34 Integration with pydb has been removed since pydb development has been stopped
35 since 2012, and pydb is not installable from PyPI
35 since 2012, and pydb is not installable from PyPI
36
36
37
37
38
38
39 Replacement of readline in TerminalInteractiveShell and PDB
39 Replacement of readline in TerminalInteractiveShell and PDB
40 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
40 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
41
41
42 IPython 5.0 now uses ``prompt_toolkit``. The
42 IPython 5.0 now uses ``prompt_toolkit``. The
43 ``IPtyhon.terminal.interactiveshell.TerminalInteractiveShell`` now uses
43 ``IPython.terminal.interactiveshell.TerminalInteractiveShell`` now uses
44 ``prompt_toolkit``. It is an almost complete rewrite, so many settings have
44 ``prompt_toolkit``. It is an almost complete rewrite, so many settings have
45 thus changed or disappeared. The class keep the same name to avoid breaking
45 thus changed or disappeared. The class keep the same name to avoid breaking
46 user configuration for the options which names is unchanged.
46 user configuration for the options which names is unchanged.
47
47
48 The usage of ``prompt_toolkit`` is accompanied by a complete removal of all
48 The usage of ``prompt_toolkit`` is accompanied by a complete removal of all
49 code, using ``readline``. A particular effect of not using `readline` anymore
49 code, using ``readline``. A particular effect of not using `readline` anymore
50 is that `.inputrc` settings are note effective anymore. Options having similar
50 is that `.inputrc` settings are note effective anymore. Options having similar
51 effects have likely been replaced by a configuration option on IPython itself
51 effects have likely been replaced by a configuration option on IPython itself
52 (e.g: vi input mode).
52 (e.g: vi input mode).
53
53
54 The `PromptManager` class have been removed, and the prompt machinery simplified.
54 The `PromptManager` class have been removed, and the prompt machinery simplified.
55 See `TerminalInteractiveShell.prompts` configurable for how to setup your prompts.
55 See `TerminalInteractiveShell.prompts` configurable for how to setup your prompts.
56
56
57 .. note::
57 .. note::
58
58
59 During developement and beta cycle, ``TerminalInteractiveShell`` was
59 During developement and beta cycle, ``TerminalInteractiveShell`` was
60 temporarly moved to ``IPtyhon.terminal.ptshell``.
60 temporarly moved to ``IPtyhon.terminal.ptshell``.
61
61
62
62
63 Most of the above remarks also affect `IPython.core.debugger.Pdb`, the `%debug`
63 Most of the above remarks also affect `IPython.core.debugger.Pdb`, the `%debug`
64 and `%pdb` magic which do not use readline anymore either.
64 and `%pdb` magic which do not use readline anymore either.
65
65
66
66
67
67
68
68
69 Provisional Changes
69 Provisional Changes
70 -------------------
70 -------------------
71
71
72 Provisional changes are in experimental functionality that may, or may not make
72 Provisional changes are in experimental functionality that may, or may not make
73 it to future version of IPython, and which API may change without warnings.
73 it to future version of IPython, and which API may change without warnings.
74 Activating these feature and using these API is at your own risk, and may have
74 Activating these feature and using these API is at your own risk, and may have
75 security implication for your system, especially if used with the Jupyter notebook,
75 security implication for your system, especially if used with the Jupyter notebook,
76
76
77 When running via the Jupyter notebook interfaces, or other compatible client,
77 When running via the Jupyter notebook interfaces, or other compatible client,
78 you can enable rich documentation experimental functionality:
78 you can enable rich documentation experimental functionality:
79
79
80 When the ``docrepr`` package is installed setting the boolean flag
80 When the ``docrepr`` package is installed setting the boolean flag
81 ``InteractiveShell.sphinxify_docstring`` to ``True``, will process the various
81 ``InteractiveShell.sphinxify_docstring`` to ``True``, will process the various
82 object through sphinx before displaying them (see the ``docrepr`` package
82 object through sphinx before displaying them (see the ``docrepr`` package
83 documentation for more information.
83 documentation for more information.
84
84
85 You need to also enable the IPython pager display rich HTML representation
85 You need to also enable the IPython pager display rich HTML representation
86 using the ``InteractiveShell.enable_html_pager`` boolean configuration option.
86 using the ``InteractiveShell.enable_html_pager`` boolean configuration option.
87 As usual you can set these configuration options globally in your configuration
87 As usual you can set these configuration options globally in your configuration
88 files, alternatively you can turn them on dynamically using the following
88 files, alternatively you can turn them on dynamically using the following
89 snippet:
89 snippet:
90
90
91 .. code-block:: python
91 .. code-block:: python
92
92
93 ip = get_ipython()
93 ip = get_ipython()
94 ip.sphinxify_docstring = True
94 ip.sphinxify_docstring = True
95 ip.enable_html_pager = True
95 ip.enable_html_pager = True
96
96
97 You can test the effect of various combinations of the above configuration in
97 You can test the effect of various combinations of the above configuration in
98 the Jupyter notebook, with things example like :
98 the Jupyter notebook, with things example like :
99
99
100 .. code-block:: python
100 .. code-block:: python
101
101
102 import numpy as np
102 import numpy as np
103 np.histogram?
103 np.histogram?
104
104
105 This is part of an effort to make Documentation in Python richer and provide in
105 This is part of an effort to make Documentation in Python richer and provide in
106 the long term if possible dynamic examples that can contain math, images,
106 the long term if possible dynamic examples that can contain math, images,
107 widgets... As stated above this is nightly experimental feature with a lot of
107 widgets... As stated above this is nightly experimental feature with a lot of
108 (fun) problem to solve. We would be happy to get your feedback and expertise on
108 (fun) problem to solve. We would be happy to get your feedback and expertise on
109 it.
109 it.
110
110
111
111
112 Known Issues:
112 Known Issues:
113 -------------
113 -------------
114
114
115 - ``<Esc>`` Key does not dismiss the completer and does not clear the current
115 - ``<Esc>`` Key does not dismiss the completer and does not clear the current
116 buffer. This is an on purpose modification due to current technical
116 buffer. This is an on purpose modification due to current technical
117 limitation. Cf :ghpull:`9572`. Escape the control character which is used
117 limitation. Cf :ghpull:`9572`. Escape the control character which is used
118 for other shortcut, and there is no practical way to distinguish. Use Ctr-G
118 for other shortcut, and there is no practical way to distinguish. Use Ctr-G
119 or Ctrl-C as an alternative.
119 or Ctrl-C as an alternative.
120
120
121 - Cannot use ``Shift-Enter`` and ``Ctrl-Enter`` to submit code in terminal. cf
121 - Cannot use ``Shift-Enter`` and ``Ctrl-Enter`` to submit code in terminal. cf
122 :ghissue:`9587` and :ghissue:`9401`. In terminal there is no practical way to
122 :ghissue:`9587` and :ghissue:`9401`. In terminal there is no practical way to
123 distinguish these key sequences from a normal new line return.
123 distinguish these key sequences from a normal new line return.
124
124
125 - Dialog completion pop up even with a single completion. Cf :ghissue:`9540`. This
125 - Dialog completion pop up even with a single completion. Cf :ghissue:`9540`. This
126 would automatically be resolved with the next minor revision of
126 would automatically be resolved with the next minor revision of
127 ``prompt_toolkit``
127 ``prompt_toolkit``
128
128
129 - ``PageUp`` and ``pageDown`` do not move through completion menu.
129 - ``PageUp`` and ``pageDown`` do not move through completion menu.
130
130
131 - Custom prompt cannot make use of custom invisible escape sequences. This
131 - Custom prompt cannot make use of custom invisible escape sequences. This
132 will be automatically resolved with next version of Prompt Toolkit
132 will be automatically resolved with next version of Prompt Toolkit
133
133
134 - Color styles might not adapt to terminal emulator themes. This will need new
134 - Color styles might not adapt to terminal emulator themes. This will need new
135 version of Pygments to be released, and can be mitigated with custom themes.
135 version of Pygments to be released, and can be mitigated with custom themes.
136
136
137
137
General Comments 0
You need to be logged in to leave comments. Login now