Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8e256bd

Browse files
jonathanslenderstakluyver
authored andcommitted
Upgrade to prompt_toolkit 2.0
1 parent 2284ccf commit 8e256bd

6 files changed

Lines changed: 154 additions & 179 deletions

File tree

IPython/terminal/debugger.py

Lines changed: 25 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,14 @@
88
from .shortcuts import suspend_to_bg, cursor_in_leading_ws
99

1010
from prompt_toolkit.enums import DEFAULT_BUFFER
11-
from prompt_toolkit.filters import (Condition, HasFocus, HasSelection,
12-
ViInsertMode, EmacsInsertMode)
13-
from prompt_toolkit.keys import Keys
14-
from prompt_toolkit.key_binding.manager import KeyBindingManager
11+
from prompt_toolkit.filters import (Condition, has_focus, has_selection,
12+
vi_insert_mode, emacs_insert_mode)
13+
from prompt_toolkit.key_binding import KeyBindings
1514
from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline
16-
from prompt_toolkit.token import Token
17-
from prompt_toolkit.shortcuts import create_prompt_application
18-
from prompt_toolkit.interface import CommandLineInterface
15+
from pygments.token import Token
16+
from prompt_toolkit.shortcuts.prompt import PromptSession
1917
from prompt_toolkit.enums import EditingMode
18+
from prompt_toolkit.formatted_text import PygmentsTokens
2019

2120

2221
class TerminalPdb(Pdb):
@@ -26,46 +25,40 @@ def __init__(self, *args, **kwargs):
2625
self.pt_init()
2726

2827
def pt_init(self):
29-
def get_prompt_tokens(cli):
28+
def get_prompt_tokens():
3029
return [(Token.Prompt, self.prompt)]
3130

32-
def patch_stdout(**kwargs):
33-
return self.pt_cli.patch_stdout_context(**kwargs)
34-
3531
if self._ptcomp is None:
3632
compl = IPCompleter(shell=self.shell,
3733
namespace={},
3834
global_namespace={},
3935
parent=self.shell,
4036
)
41-
self._ptcomp = IPythonPTCompleter(compl, patch_stdout=patch_stdout)
37+
self._ptcomp = IPythonPTCompleter(compl)
4238

43-
kbmanager = KeyBindingManager.for_prompt()
44-
supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP'))
45-
kbmanager.registry.add_binding(Keys.ControlZ, filter=supports_suspend
46-
)(suspend_to_bg)
39+
kb = KeyBindings()
40+
supports_suspend = Condition(lambda: hasattr(signal, 'SIGTSTP'))
41+
kb.add('c-z', filter=supports_suspend)(suspend_to_bg)
4742

4843
if self.shell.display_completions == 'readlinelike':
49-
kbmanager.registry.add_binding(Keys.ControlI,
50-
filter=(HasFocus(DEFAULT_BUFFER)
51-
& ~HasSelection()
52-
& ViInsertMode() | EmacsInsertMode()
53-
& ~cursor_in_leading_ws
54-
))(display_completions_like_readline)
55-
multicolumn = (self.shell.display_completions == 'multicolumn')
56-
57-
self._pt_app = create_prompt_application(
44+
kb.add('tab', filter=(has_focus(DEFAULT_BUFFER)
45+
& ~has_selection
46+
& vi_insert_mode | emacs_insert_mode
47+
& ~cursor_in_leading_ws
48+
))(display_completions_like_readline)
49+
50+
self.pt_app = PromptSession(
51+
message=(lambda: PygmentsTokens(get_prompt_tokens())),
5852
editing_mode=getattr(EditingMode, self.shell.editing_mode.upper()),
59-
key_bindings_registry=kbmanager.registry,
53+
key_bindings=kb,
6054
history=self.shell.debugger_history,
61-
completer= self._ptcomp,
55+
completer=self._ptcomp,
6256
enable_history_search=True,
6357
mouse_support=self.shell.mouse_support,
64-
get_prompt_tokens=get_prompt_tokens,
65-
display_completions_in_columns=multicolumn,
66-
style=self.shell.style
58+
complete_style=self.shell.pt_complete_style,
59+
style=self.shell.style,
60+
inputhook=self.shell.inputhook,
6761
)
68-
self.pt_cli = CommandLineInterface(self._pt_app, eventloop=self.shell._eventloop)
6962

7063
def cmdloop(self, intro=None):
7164
"""Repeatedly issue a prompt, accept input, parse an initial prefix
@@ -92,7 +85,7 @@ def cmdloop(self, intro=None):
9285
self._ptcomp.ipy_completer.namespace = self.curframe_locals
9386
self._ptcomp.ipy_completer.global_namespace = self.curframe.f_globals
9487
try:
95-
line = self.pt_cli.run(reset_current_buffer=True).text
88+
line = self.pt_app.prompt() # reset_current_buffer=True)
9689
except EOFError:
9790
line = 'EOF'
9891
line = self.precmd(line)

IPython/terminal/interactiveshell.py

Lines changed: 64 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@
1818
from prompt_toolkit.document import Document
1919
from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
2020
from prompt_toolkit.filters import (HasFocus, Condition, IsDone)
21+
from prompt_toolkit.formatted_text import PygmentsTokens
2122
from prompt_toolkit.history import InMemoryHistory
22-
from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout, create_output
23-
from prompt_toolkit.interface import CommandLineInterface
24-
from prompt_toolkit.key_binding.manager import KeyBindingManager
23+
from prompt_toolkit.shortcuts import PromptSession, CompleteStyle
24+
from prompt_toolkit.output.defaults import create_output
25+
from prompt_toolkit.key_binding import KeyBindings
2526
from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
26-
from prompt_toolkit.styles import PygmentsStyle, DynamicStyle
27+
from prompt_toolkit.patch_stdout import patch_stdout
28+
from prompt_toolkit.styles import DynamicStyle, merge_styles
29+
from prompt_toolkit.styles.pygments import style_from_pygments_cls, style_from_pygments_dict
2730

2831
from pygments.styles import get_style_by_name
2932
from pygments.style import Style
@@ -34,7 +37,7 @@
3437
from .pt_inputhooks import get_inputhook_name_and_func
3538
from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
3639
from .ptutils import IPythonPTCompleter, IPythonPTLexer
37-
from .shortcuts import register_ipython_shortcuts
40+
from .shortcuts import create_ipython_shortcuts
3841

3942
DISPLAY_BANNER_DEPRECATED = object()
4043

@@ -91,12 +94,11 @@ class TerminalInteractiveShell(InteractiveShell):
9194
'to reserve for the completion menu'
9295
).tag(config=True)
9396

94-
def _space_for_menu_changed(self, old, new):
95-
self._update_layout()
97+
# def _space_for_menu_changed(self, old, new):
98+
# self._update_layout()
9699

97-
pt_cli = None
100+
pt_app = None
98101
debugger_history = None
99-
_pt_app = None
100102

101103
simple_prompt = Bool(_use_simple_prompt,
102104
help="""Use `raw_input` for the REPL, without completion and prompt colors.
@@ -167,9 +169,9 @@ def refresh_style(self):
167169
def _prompts_default(self):
168170
return self.prompts_class(self)
169171

170-
@observe('prompts')
171-
def _(self, change):
172-
self._update_layout()
172+
# @observe('prompts')
173+
# def _(self, change):
174+
# self._update_layout()
173175

174176
@default('displayhook_class')
175177
def _displayhook_class_default(self):
@@ -243,10 +245,7 @@ def prompt():
243245
return
244246

245247
# Set up keyboard shortcuts
246-
kbmanager = KeyBindingManager.for_prompt(
247-
enable_open_in_editor=self.extra_open_editor_shortcuts,
248-
)
249-
register_ipython_shortcuts(kbmanager.registry, self)
248+
key_bindings = create_ipython_shortcuts(self)
250249

251250
# Pre-populate history from IPython's history database
252251
history = InMemoryHistory()
@@ -256,32 +255,26 @@ def prompt():
256255
# Ignore blank lines and consecutive duplicates
257256
cell = cell.rstrip()
258257
if cell and (cell != last_cell):
259-
history.append(cell)
258+
history.append_string(cell)
260259
last_cell = cell
261260

262261
self._style = self._make_style_from_name_or_cls(self.highlighting_style)
263262
self.style = DynamicStyle(lambda: self._style)
264263

265264
editing_mode = getattr(EditingMode, self.editing_mode.upper())
266265

267-
def patch_stdout(**kwargs):
268-
return self.pt_cli.patch_stdout_context(**kwargs)
269-
270-
self._pt_app = create_prompt_application(
266+
self.pt_app = PromptSession(
271267
editing_mode=editing_mode,
272-
key_bindings_registry=kbmanager.registry,
268+
key_bindings=key_bindings,
273269
history=history,
274-
completer=IPythonPTCompleter(shell=self,
275-
patch_stdout=patch_stdout),
276-
enable_history_search=self.enable_history_search,
270+
completer=IPythonPTCompleter(shell=self),
271+
enable_history_search = self.enable_history_search,
277272
style=self.style,
273+
include_default_pygments_style=False,
278274
mouse_support=self.mouse_support,
279-
**self._layout_options()
280-
)
281-
self._eventloop = create_eventloop(self.inputhook)
282-
self.pt_cli = CommandLineInterface(
283-
self._pt_app, eventloop=self._eventloop,
284-
output=create_output(true_color=self.true_color))
275+
enable_open_in_editor=self.extra_open_editor_shortcuts,
276+
color_depth=(ColorDepth.TRUE_COLOR if self.true_color else None),
277+
**self._extra_prompt_options())
285278

286279
def _make_style_from_name_or_cls(self, name_or_cls):
287280
"""
@@ -342,44 +335,60 @@ def _make_style_from_name_or_cls(self, name_or_cls):
342335
Token.OutPromptNum: '#ff0000 bold',
343336
}
344337
style_overrides.update(self.highlighting_style_overrides)
345-
style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
346-
style_dict=style_overrides)
338+
style = merge_styles([
339+
style_from_pygments_cls(style_cls),
340+
style_from_pygments_dict(style_overrides),
341+
])
347342

348343
return style
349344

350-
def _layout_options(self):
345+
@property
346+
def pt_complete_style(self):
347+
return {
348+
'multicolumn': CompleteStyle.MULTI_COLUMN,
349+
'column': CompleteStyle.COLUMN,
350+
'readlinelike': CompleteStyle.READLINE_LIKE,
351+
}[self.display_completions],
352+
353+
def _extra_prompt_options(self):
351354
"""
352355
Return the current layout option for the current Terminal InteractiveShell
353356
"""
357+
def get_message():
358+
return PygmentsTokens(self.prompts.in_prompt_tokens())
359+
354360
return {
361+
'complete_in_thread': False,
355362
'lexer':IPythonPTLexer(),
356363
'reserve_space_for_menu':self.space_for_menu,
357-
'get_prompt_tokens':self.prompts.in_prompt_tokens,
358-
'get_continuation_tokens':self.prompts.continuation_prompt_tokens,
359-
'multiline':True,
360-
'display_completions_in_columns': (self.display_completions == 'multicolumn'),
364+
'message': get_message,
365+
'prompt_continuation': (
366+
lambda width, lineno, is_soft_wrap:
367+
PygmentsTokens(self.prompts.continuation_prompt_tokens(width))),
368+
'multiline': True,
369+
'complete_style': self.pt_complete_style,
361370

362371
# Highlight matching brackets, but only when this setting is
363372
# enabled, and only when the DEFAULT_BUFFER has the focus.
364-
'extra_input_processors': [ConditionalProcessor(
373+
'input_processors': [ConditionalProcessor(
365374
processor=HighlightMatchingBracketProcessor(chars='[](){}'),
366375
filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
367-
Condition(lambda cli: self.highlight_matching_brackets))],
376+
Condition(lambda: self.highlight_matching_brackets))],
368377
}
369378

370-
def _update_layout(self):
371-
"""
372-
Ask for a re computation of the application layout, if for example ,
373-
some configuration options have changed.
374-
"""
375-
if self._pt_app:
376-
self._pt_app.layout = create_prompt_layout(**self._layout_options())
377-
378379
def prompt_for_code(self):
379-
with self.pt_cli.patch_stdout_context(raw=True):
380-
document = self.pt_cli.run(
381-
pre_run=self.pre_prompt, reset_current_buffer=True)
382-
return document.text
380+
if self.rl_next_input:
381+
default = self.rl_next_input
382+
self.rl_next_input = None
383+
else:
384+
default = ''
385+
386+
with patch_stdout(raw=True):
387+
text = self.pt_app.prompt(
388+
default=default,
389+
# pre_run=self.pre_prompt,# reset_current_buffer=True,
390+
**self._extra_prompt_options())
391+
return text
383392

384393
def enable_win_unicode_console(self):
385394
if sys.version_info >= (3, 6):
@@ -439,22 +448,6 @@ def ask_exit(self):
439448

440449
rl_next_input = None
441450

442-
def pre_prompt(self):
443-
if self.rl_next_input:
444-
# We can't set the buffer here, because it will be reset just after
445-
# this. Adding a callable to pre_run_callables does what we need
446-
# after the buffer is reset.
447-
s = self.rl_next_input
448-
def set_doc():
449-
self.pt_cli.application.buffer.document = Document(s)
450-
if hasattr(self.pt_cli, 'pre_run_callables'):
451-
self.pt_cli.pre_run_callables.append(set_doc)
452-
else:
453-
# Older version of prompt_toolkit; it's OK to set the document
454-
# directly here.
455-
set_doc()
456-
self.rl_next_input = None
457-
458451
def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED):
459452

460453
if display_banner is not DISPLAY_BANNER_DEPRECATED:
@@ -517,8 +510,8 @@ def auto_rewrite_input(self, cmd):
517510
return
518511

519512
tokens = self.prompts.rewrite_prompt_tokens()
520-
if self.pt_cli:
521-
self.pt_cli.print_tokens(tokens)
513+
if self.pt_app:
514+
self.pt_app.print_tokens(tokens) # XXX
522515
print(cmd)
523516
else:
524517
prompt = ''.join(s for t, s in tokens)
@@ -533,7 +526,7 @@ def switch_doctest_mode(self, mode):
533526
elif self._prompts_before:
534527
self.prompts = self._prompts_before
535528
self._prompts_before = None
536-
self._update_layout()
529+
# self._update_layout()
537530

538531

539532
InteractiveShellABC.register(TerminalInteractiveShell)

IPython/terminal/prompts.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,25 @@
55

66
from IPython.core.displayhook import DisplayHook
77

8-
from prompt_toolkit.layout.utils import token_list_width
8+
from prompt_toolkit.formatted_text import fragment_list_width, PygmentsTokens
9+
from prompt_toolkit.shortcuts import print_formatted_text
10+
911

1012
class Prompts(object):
1113
def __init__(self, shell):
1214
self.shell = shell
1315

14-
def in_prompt_tokens(self, cli=None):
16+
def in_prompt_tokens(self):
1517
return [
1618
(Token.Prompt, 'In ['),
1719
(Token.PromptNum, str(self.shell.execution_count)),
1820
(Token.Prompt, ']: '),
1921
]
2022

2123
def _width(self):
22-
return token_list_width(self.in_prompt_tokens())
24+
return fragment_list_width(self.in_prompt_tokens())
2325

24-
def continuation_prompt_tokens(self, cli=None, width=None):
26+
def continuation_prompt_tokens(self, width=None):
2527
if width is None:
2628
width = self._width()
2729
return [
@@ -42,12 +44,12 @@ def out_prompt_tokens(self):
4244
]
4345

4446
class ClassicPrompts(Prompts):
45-
def in_prompt_tokens(self, cli=None):
47+
def in_prompt_tokens(self):
4648
return [
4749
(Token.Prompt, '>>> '),
4850
]
4951

50-
def continuation_prompt_tokens(self, cli=None, width=None):
52+
def continuation_prompt_tokens(self, width=None):
5153
return [
5254
(Token.Prompt, '... ')
5355
]
@@ -73,7 +75,8 @@ def write_output_prompt(self):
7375
# Ask for a newline before multiline output
7476
self.prompt_end_newline = False
7577

76-
if self.shell.pt_cli:
77-
self.shell.pt_cli.print_tokens(tokens)
78+
if self.shell.pt_app:
79+
print_formatted_text(
80+
PygmentsTokens(tokens), style=self.shell.pt_app.app.style)
7881
else:
7982
sys.stdout.write(prompt_txt)

0 commit comments

Comments
 (0)