prompts.py
128 lines
| 4.0 KiB
| text/x-python
|
PythonLexer
Thomas Kluyver
|
r22428 | """Terminal input and output prompts.""" | ||
Thomas Kluyver
|
r22421 | from pygments.token import Token | ||
Thomas Kluyver
|
r22422 | import sys | ||
from IPython.core.displayhook import DisplayHook | ||||
Thomas Kluyver
|
r22421 | |||
Jonathan Slenders
|
r24376 | from prompt_toolkit.formatted_text import fragment_list_width, PygmentsTokens | ||
from prompt_toolkit.shortcuts import print_formatted_text | ||||
Jonathan Feinberg
|
r25385 | from prompt_toolkit.enums import EditingMode | ||
Jonathan Slenders
|
r24376 | |||
Matthias Bussonnier
|
r22471 | |||
Thomas Kluyver
|
r22421 | class Prompts(object): | ||
def __init__(self, shell): | ||||
self.shell = shell | ||||
Matthias Bussonnier
|
r24684 | def vi_mode(self): | ||
Jonathan Feinberg
|
r25385 | if (getattr(self.shell.pt_app, 'editing_mode', None) == EditingMode.VI | ||
Antony Lee
|
r24832 | and self.shell.prompt_includes_vi_mode): | ||
Jonathan Feinberg
|
r25386 | mode = str(self.shell.pt_app.app.vi_state.input_mode) | ||
if mode.startswith('InputMode.'): | ||||
mode = mode[10:13].lower() | ||||
elif mode.startswith('vi-'): | ||||
mode = mode[3:6] | ||||
return '['+mode+'] ' | ||||
Matthias Bussonnier
|
r24684 | return '' | ||
Matthias Bussonnier
|
r28537 | def current_line(self) -> int: | ||
if self.shell.pt_app is not None: | ||||
return self.shell.pt_app.default_buffer.document.cursor_position_row or 0 | ||||
return 0 | ||||
Matthias Bussonnier
|
r24684 | |||
Jonathan Slenders
|
r24376 | def in_prompt_tokens(self): | ||
Thomas Kluyver
|
r22421 | return [ | ||
Chris Hamill
|
r28535 | (Token.Prompt, self.vi_mode()), | ||
Matthias Bussonnier
|
r28537 | ( | ||
Token.Prompt, | ||||
self.shell.prompt_line_number_format.format( | ||||
line=1, rel_line=-self.current_line() | ||||
), | ||||
), | ||||
Chris Hamill
|
r28535 | (Token.Prompt, "In ["), | ||
Thomas Kluyver
|
r22421 | (Token.PromptNum, str(self.shell.execution_count)), | ||
(Token.Prompt, ']: '), | ||||
] | ||||
def _width(self): | ||||
Jonathan Slenders
|
r24376 | return fragment_list_width(self.in_prompt_tokens()) | ||
Thomas Kluyver
|
r22421 | |||
Chris Hamill
|
r28535 | def continuation_prompt_tokens(self, width=None, *, lineno=None): | ||
Thomas Kluyver
|
r22421 | if width is None: | ||
width = self._width() | ||||
Matthias Bussonnier
|
r28537 | line = lineno + 1 if lineno is not None else 0 | ||
prefix = " " * len( | ||||
self.vi_mode() | ||||
) + self.shell.prompt_line_number_format.format( | ||||
line=line, rel_line=line - self.current_line() - 1 | ||||
) | ||||
Thomas Kluyver
|
r22421 | return [ | ||
Chris Hamill
|
r28535 | ( | ||
Token.Prompt, | ||||
prefix + (" " * (width - len(prefix) - 5)) + "...: ", | ||||
), | ||||
Thomas Kluyver
|
r22421 | ] | ||
def rewrite_prompt_tokens(self): | ||||
width = self._width() | ||||
return [ | ||||
(Token.Prompt, ('-' * (width - 2)) + '> '), | ||||
] | ||||
def out_prompt_tokens(self): | ||||
return [ | ||||
(Token.OutPrompt, 'Out['), | ||||
(Token.OutPromptNum, str(self.shell.execution_count)), | ||||
(Token.OutPrompt, ']: '), | ||||
] | ||||
Thomas Kluyver
|
r22422 | |||
Thomas Kluyver
|
r22429 | class ClassicPrompts(Prompts): | ||
Jonathan Slenders
|
r24376 | def in_prompt_tokens(self): | ||
Thomas Kluyver
|
r22429 | return [ | ||
(Token.Prompt, '>>> '), | ||||
] | ||||
Jonathan Slenders
|
r24376 | def continuation_prompt_tokens(self, width=None): | ||
Thomas Kluyver
|
r22429 | return [ | ||
(Token.Prompt, '... ') | ||||
] | ||||
def rewrite_prompt_tokens(self): | ||||
return [] | ||||
def out_prompt_tokens(self): | ||||
return [] | ||||
Thomas Kluyver
|
r22422 | class RichPromptDisplayHook(DisplayHook): | ||
"""Subclass of base display hook using coloured prompt""" | ||||
def write_output_prompt(self): | ||||
sys.stdout.write(self.shell.separate_out) | ||||
Thomas Kluyver
|
r23131 | # If we're not displaying a prompt, it effectively ends with a newline, | ||
# because the output will be left-aligned. | ||||
self.prompt_end_newline = True | ||||
Thomas Kluyver
|
r22422 | if self.do_full_cache: | ||
tokens = self.shell.prompts.out_prompt_tokens() | ||||
Matthias Bussonnier
|
r28587 | prompt_txt = "".join(s for _, s in tokens) | ||
if prompt_txt and not prompt_txt.endswith("\n"): | ||||
Thomas Kluyver
|
r23131 | # Ask for a newline before multiline output | ||
self.prompt_end_newline = False | ||||
Thomas Kluyver
|
r23132 | |||
Jonathan Slenders
|
r24376 | if self.shell.pt_app: | ||
Thomas Kluyver
|
r24380 | print_formatted_text(PygmentsTokens(tokens), | ||
style=self.shell.pt_app.app.style, end='', | ||||
) | ||||
Thomas Kluyver
|
r22422 | else: | ||
Thomas Kluyver
|
r23132 | sys.stdout.write(prompt_txt) | ||
Matthias Bussonnier
|
r25164 | |||
def write_format_data(self, format_dict, md_dict=None) -> None: | ||||
Matthias Bussonnier
|
r28587 | assert self.shell is not None | ||
Matthias Bussonnier
|
r25164 | if self.shell.mime_renderers: | ||
for mime, handler in self.shell.mime_renderers.items(): | ||||
if mime in format_dict: | ||||
handler(format_dict[mime], None) | ||||
return | ||||
super().write_format_data(format_dict, md_dict) | ||||