1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715
|
"""
Shortcuts for retrieving input from the user.
If you are using this library for retrieving some input from the user (as a
pure Python replacement for GNU readline), probably for 90% of the use cases,
the :func:`.prompt` function is all you need. It's the easiest shortcut which
does a lot of the underlying work like creating a
:class:`~prompt_toolkit.interface.CommandLineInterface` instance for you.
When is this not sufficient:
- When you want to have more complicated layouts (maybe with sidebars or
multiple toolbars. Or visibility of certain user interface controls
according to some conditions.)
- When you wish to have multiple input buffers. (If you would create an
editor like a Vi clone.)
- Something else that requires more customization than what is possible
with the parameters of `prompt`.
In that case, study the code in this file and build your own
`CommandLineInterface` instance. It's not too complicated.
"""
from __future__ import unicode_literals
from .buffer import Buffer, AcceptAction
from .document import Document
from .enums import DEFAULT_BUFFER, SEARCH_BUFFER, EditingMode
from .filters import IsDone, HasFocus, RendererHeightIsKnown, to_simple_filter, to_cli_filter, Condition
from .history import InMemoryHistory
from .interface import CommandLineInterface, Application, AbortAction
from .key_binding.manager import KeyBindingManager
from .key_binding.registry import Registry
from .keys import Keys
from .layout import Window, HSplit, FloatContainer, Float
from .layout.containers import ConditionalContainer
from .layout.controls import BufferControl, TokenListControl
from .layout.dimension import LayoutDimension
from .layout.lexers import PygmentsLexer
from .layout.margins import PromptMargin, ConditionalMargin
from .layout.menus import CompletionsMenu, MultiColumnCompletionsMenu
from .layout.processors import PasswordProcessor, ConditionalProcessor, AppendAutoSuggestion, HighlightSearchProcessor, HighlightSelectionProcessor, DisplayMultipleCursors
from .layout.prompt import DefaultPrompt
from .layout.screen import Char
from .layout.toolbars import ValidationToolbar, SystemToolbar, ArgToolbar, SearchToolbar
from .layout.utils import explode_tokens
from .renderer import print_tokens as renderer_print_tokens
from .styles import DEFAULT_STYLE, Style, style_from_dict
from .token import Token
from .utils import is_conemu_ansi, is_windows, DummyContext
from six import text_type, exec_, PY2
import os
import sys
import textwrap
import threading
import time
try:
from pygments.lexer import Lexer as pygments_Lexer
from pygments.style import Style as pygments_Style
except ImportError:
pygments_Lexer = None
pygments_Style = None
if is_windows():
from .terminal.win32_output import Win32Output
from .terminal.conemu_output import ConEmuOutput
else:
from .terminal.vt100_output import Vt100_Output
__all__ = (
'create_eventloop',
'create_output',
'create_prompt_layout',
'create_prompt_application',
'prompt',
'prompt_async',
'create_confirm_application',
'confirm',
'print_tokens',
)
def create_eventloop(inputhook=None, recognize_win32_paste=True):
"""
Create and return an
:class:`~prompt_toolkit.eventloop.base.EventLoop` instance for a
:class:`~prompt_toolkit.interface.CommandLineInterface`.
"""
if is_windows():
from prompt_toolkit.eventloop.win32 import Win32EventLoop as Loop
return Loop(inputhook=inputhook, recognize_paste=recognize_win32_paste)
else:
from prompt_toolkit.eventloop.posix import PosixEventLoop as Loop
return Loop(inputhook=inputhook)
def create_output(stdout=None, true_color=False, ansi_colors_only=None):
"""
Return an :class:`~prompt_toolkit.output.Output` instance for the command
line.
:param true_color: When True, use 24bit colors instead of 256 colors.
(`bool` or :class:`~prompt_toolkit.filters.SimpleFilter`.)
:param ansi_colors_only: When True, restrict to 16 ANSI colors only.
(`bool` or :class:`~prompt_toolkit.filters.SimpleFilter`.)
"""
stdout = stdout or sys.__stdout__
true_color = to_simple_filter(true_color)
if is_windows():
if is_conemu_ansi():
return ConEmuOutput(stdout)
else:
return Win32Output(stdout)
else:
term = os.environ.get('TERM', '')
if PY2:
term = term.decode('utf-8')
return Vt100_Output.from_pty(
stdout, true_color=true_color,
ansi_colors_only=ansi_colors_only, term=term)
def create_asyncio_eventloop(loop=None):
"""
Returns an asyncio :class:`~prompt_toolkit.eventloop.EventLoop` instance
for usage in a :class:`~prompt_toolkit.interface.CommandLineInterface`. It
is a wrapper around an asyncio loop.
:param loop: The asyncio eventloop (or `None` if the default asyncioloop
should be used.)
"""
# Inline import, to make sure the rest doesn't break on Python 2. (Where
# asyncio is not available.)
if is_windows():
from prompt_toolkit.eventloop.asyncio_win32 import Win32AsyncioEventLoop as AsyncioEventLoop
else:
from prompt_toolkit.eventloop.asyncio_posix import PosixAsyncioEventLoop as AsyncioEventLoop
return AsyncioEventLoop(loop)
def _split_multiline_prompt(get_prompt_tokens):
"""
Take a `get_prompt_tokens` function and return three new functions instead.
One that tells whether this prompt consists of multiple lines; one that
returns the tokens to be shown on the lines above the input; and another
one with the tokens to be shown at the first line of the input.
"""
def has_before_tokens(cli):
for token, char in get_prompt_tokens(cli):
if '\n' in char:
return True
return False
def before(cli):
result = []
found_nl = False
for token, char in reversed(explode_tokens(get_prompt_tokens(cli))):
if found_nl:
result.insert(0, (token, char))
elif char == '\n':
found_nl = True
return result
def first_input_line(cli):
result = []
for token, char in reversed(explode_tokens(get_prompt_tokens(cli))):
if char == '\n':
break
else:
result.insert(0, (token, char))
return result
return has_before_tokens, before, first_input_line
class _RPrompt(Window):
" The prompt that is displayed on the right side of the Window. "
def __init__(self, get_tokens=None):
get_tokens = get_tokens or (lambda cli: [])
super(_RPrompt, self).__init__(
TokenListControl(get_tokens, align_right=True))
def create_prompt_layout(message='', lexer=None, is_password=False,
reserve_space_for_menu=8,
get_prompt_tokens=None, get_continuation_tokens=None,
get_rprompt_tokens=None,
get_bottom_toolbar_tokens=None,
display_completions_in_columns=False,
extra_input_processors=None, multiline=False,
wrap_lines=True):
"""
Create a :class:`.Container` instance for a prompt.
:param message: Text to be used as prompt.
:param lexer: :class:`~prompt_toolkit.layout.lexers.Lexer` to be used for
the highlighting.
:param is_password: `bool` or :class:`~prompt_toolkit.filters.CLIFilter`.
When True, display input as '*'.
:param reserve_space_for_menu: Space to be reserved for the menu. When >0,
make sure that a minimal height is allocated in the terminal, in order
to display the completion menu.
:param get_prompt_tokens: An optional callable that returns the tokens to be
shown in the menu. (To be used instead of a `message`.)
:param get_continuation_tokens: An optional callable that takes a
CommandLineInterface and width as input and returns a list of (Token,
text) tuples to be used for the continuation.
:param get_bottom_toolbar_tokens: An optional callable that returns the
tokens for a toolbar at the bottom.
:param display_completions_in_columns: `bool` or
:class:`~prompt_toolkit.filters.CLIFilter`. Display the completions in
multiple columns.
:param multiline: `bool` or :class:`~prompt_toolkit.filters.CLIFilter`.
When True, prefer a layout that is more adapted for multiline input.
Text after newlines is automatically indented, and search/arg input is
shown below the input, instead of replacing the prompt.
:param wrap_lines: `bool` or :class:`~prompt_toolkit.filters.CLIFilter`.
When True (the default), automatically wrap long lines instead of
scrolling horizontally.
"""
assert isinstance(message, text_type), 'Please provide a unicode string.'
assert get_bottom_toolbar_tokens is None or callable(get_bottom_toolbar_tokens)
assert get_prompt_tokens is None or callable(get_prompt_tokens)
assert get_rprompt_tokens is None or callable(get_rprompt_tokens)
assert not (message and get_prompt_tokens)
display_completions_in_columns = to_cli_filter(display_completions_in_columns)
multiline = to_cli_filter(multiline)
if get_prompt_tokens is None:
get_prompt_tokens = lambda _: [(Token.Prompt, message)]
has_before_tokens, get_prompt_tokens_1, get_prompt_tokens_2 = \
_split_multiline_prompt(get_prompt_tokens)
# `lexer` is supposed to be a `Lexer` instance. But if a Pygments lexer
# class is given, turn it into a PygmentsLexer. (Important for
# backwards-compatibility.)
try:
if pygments_Lexer and issubclass(lexer, pygments_Lexer):
lexer = PygmentsLexer(lexer, sync_from_start=True)
except TypeError: # Happens when lexer is `None` or an instance of something else.
pass
# Create processors list.
input_processors = [
ConditionalProcessor(
# By default, only highlight search when the search
# input has the focus. (Note that this doesn't mean
# there is no search: the Vi 'n' binding for instance
# still allows to jump to the next match in
# navigation mode.)
HighlightSearchProcessor(preview_search=True),
HasFocus(SEARCH_BUFFER)),
HighlightSelectionProcessor(),
ConditionalProcessor(AppendAutoSuggestion(), HasFocus(DEFAULT_BUFFER) & ~IsDone()),
ConditionalProcessor(PasswordProcessor(), is_password),
DisplayMultipleCursors(DEFAULT_BUFFER),
]
if extra_input_processors:
input_processors.extend(extra_input_processors)
# Show the prompt before the input (using the DefaultPrompt processor.
# This also replaces it with reverse-i-search and 'arg' when required.
# (Only for single line mode.)
# (DefaultPrompt should always be at the end of the processors.)
input_processors.append(ConditionalProcessor(
DefaultPrompt(get_prompt_tokens_2), ~multiline))
# Create bottom toolbar.
if get_bottom_toolbar_tokens:
toolbars = [ConditionalContainer(
Window(TokenListControl(get_bottom_toolbar_tokens,
default_char=Char(' ', Token.Toolbar)),
height=LayoutDimension.exact(1)),
filter=~IsDone() & RendererHeightIsKnown())]
else:
toolbars = []
def get_height(cli):
# If there is an autocompletion menu to be shown, make sure that our
# layout has at least a minimal height in order to display it.
if reserve_space_for_menu and not cli.is_done:
buff = cli.current_buffer
# Reserve the space, either when there are completions, or when
# `complete_while_typing` is true and we expect completions very
# soon.
if buff.complete_while_typing() or buff.complete_state is not None:
return LayoutDimension(min=reserve_space_for_menu)
return LayoutDimension()
# Create and return Container instance.
return HSplit([
# The main input, with completion menus floating on top of it.
FloatContainer(
HSplit([
ConditionalContainer(
Window(
TokenListControl(get_prompt_tokens_1),
dont_extend_height=True),
Condition(has_before_tokens)
),
Window(
BufferControl(
input_processors=input_processors,
lexer=lexer,
# Enable preview_search, we want to have immediate feedback
# in reverse-i-search mode.
preview_search=True),
get_height=get_height,
left_margins=[
# In multiline mode, use the window margin to display
# the prompt and continuation tokens.
ConditionalMargin(
PromptMargin(get_prompt_tokens_2, get_continuation_tokens),
filter=multiline
)
],
wrap_lines=wrap_lines,
),
]),
[
# Completion menus.
Float(xcursor=True,
ycursor=True,
content=CompletionsMenu(
max_height=16,
scroll_offset=1,
extra_filter=HasFocus(DEFAULT_BUFFER) &
~display_completions_in_columns)),
Float(xcursor=True,
ycursor=True,
content=MultiColumnCompletionsMenu(
extra_filter=HasFocus(DEFAULT_BUFFER) &
display_completions_in_columns,
show_meta=True)),
# The right prompt.
Float(right=0, top=0, hide_when_covering_content=True,
content=_RPrompt(get_rprompt_tokens)),
]
),
ValidationToolbar(),
SystemToolbar(),
# In multiline mode, we use two toolbars for 'arg' and 'search'.
ConditionalContainer(ArgToolbar(), multiline),
ConditionalContainer(SearchToolbar(), multiline),
] + toolbars)
def create_prompt_application(
message='',
multiline=False,
wrap_lines=True,
is_password=False,
vi_mode=False,
editing_mode=EditingMode.EMACS,
complete_while_typing=True,
enable_history_search=False,
lexer=None,
enable_system_bindings=False,
enable_open_in_editor=False,
validator=None,
completer=None,
reserve_space_for_menu=8,
auto_suggest=None,
style=None,
history=None,
clipboard=None,
get_prompt_tokens=None,
get_continuation_tokens=None,
get_rprompt_tokens=None,
get_bottom_toolbar_tokens=None,
display_completions_in_columns=False,
get_title=None,
mouse_support=False,
extra_input_processors=None,
key_bindings_registry=None,
on_abort=AbortAction.RAISE_EXCEPTION,
on_exit=AbortAction.RAISE_EXCEPTION,
accept_action=AcceptAction.RETURN_DOCUMENT,
erase_when_done=False,
default=''):
"""
Create an :class:`~Application` instance for a prompt.
(It is meant to cover 90% of the prompt use cases, where no extreme
customization is required. For more complex input, it is required to create
a custom :class:`~Application` instance.)
:param message: Text to be shown before the prompt.
:param mulitiline: Allow multiline input. Pressing enter will insert a
newline. (This requires Meta+Enter to accept the input.)
:param wrap_lines: `bool` or :class:`~prompt_toolkit.filters.CLIFilter`.
When True (the default), automatically wrap long lines instead of
scrolling horizontally.
:param is_password: Show asterisks instead of the actual typed characters.
:param editing_mode: ``EditingMode.VI`` or ``EditingMode.EMACS``.
:param vi_mode: `bool`, if True, Identical to ``editing_mode=EditingMode.VI``.
:param complete_while_typing: `bool` or
:class:`~prompt_toolkit.filters.SimpleFilter`. Enable autocompletion
while typing.
:param enable_history_search: `bool` or
:class:`~prompt_toolkit.filters.SimpleFilter`. Enable up-arrow parting
string matching.
:param lexer: :class:`~prompt_toolkit.layout.lexers.Lexer` to be used for
the syntax highlighting.
:param validator: :class:`~prompt_toolkit.validation.Validator` instance
for input validation.
:param completer: :class:`~prompt_toolkit.completion.Completer` instance
for input completion.
:param reserve_space_for_menu: Space to be reserved for displaying the menu.
(0 means that no space needs to be reserved.)
:param auto_suggest: :class:`~prompt_toolkit.auto_suggest.AutoSuggest`
instance for input suggestions.
:param style: :class:`.Style` instance for the color scheme.
:param enable_system_bindings: `bool` or
:class:`~prompt_toolkit.filters.CLIFilter`. Pressing Meta+'!' will show
a system prompt.
:param enable_open_in_editor: `bool` or
:class:`~prompt_toolkit.filters.CLIFilter`. Pressing 'v' in Vi mode or
C-X C-E in emacs mode will open an external editor.
:param history: :class:`~prompt_toolkit.history.History` instance.
:param clipboard: :class:`~prompt_toolkit.clipboard.base.Clipboard` instance.
(e.g. :class:`~prompt_toolkit.clipboard.in_memory.InMemoryClipboard`)
:param get_bottom_toolbar_tokens: Optional callable which takes a
:class:`~prompt_toolkit.interface.CommandLineInterface` and returns a
list of tokens for the bottom toolbar.
:param display_completions_in_columns: `bool` or
:class:`~prompt_toolkit.filters.CLIFilter`. Display the completions in
multiple columns.
:param get_title: Callable that returns the title to be displayed in the
terminal.
:param mouse_support: `bool` or :class:`~prompt_toolkit.filters.CLIFilter`
to enable mouse support.
:param default: The default text to be shown in the input buffer. (This can
be edited by the user.)
"""
if key_bindings_registry is None:
key_bindings_registry = KeyBindingManager.for_prompt(
enable_system_bindings=enable_system_bindings,
enable_open_in_editor=enable_open_in_editor).registry
# Ensure backwards-compatibility, when `vi_mode` is passed.
if vi_mode:
editing_mode = EditingMode.VI
# Make sure that complete_while_typing is disabled when enable_history_search
# is enabled. (First convert to SimpleFilter, to avoid doing bitwise operations
# on bool objects.)
complete_while_typing = to_simple_filter(complete_while_typing)
enable_history_search = to_simple_filter(enable_history_search)
multiline = to_simple_filter(multiline)
complete_while_typing = complete_while_typing & ~enable_history_search
# Accept Pygments styles as well for backwards compatibility.
try:
if pygments_Style and issubclass(style, pygments_Style):
style = style_from_dict(style.styles)
except TypeError: # Happens when style is `None` or an instance of something else.
pass
# Create application
return Application(
layout=create_prompt_layout(
message=message,
lexer=lexer,
is_password=is_password,
reserve_space_for_menu=(reserve_space_for_menu if completer is not None else 0),
multiline=Condition(lambda cli: multiline()),
get_prompt_tokens=get_prompt_tokens,
get_continuation_tokens=get_continuation_tokens,
get_rprompt_tokens=get_rprompt_tokens,
get_bottom_toolbar_tokens=get_bottom_toolbar_tokens,
display_completions_in_columns=display_completions_in_columns,
extra_input_processors=extra_input_processors,
wrap_lines=wrap_lines),
buffer=Buffer(
enable_history_search=enable_history_search,
complete_while_typing=complete_while_typing,
is_multiline=multiline,
history=(history or InMemoryHistory()),
validator=validator,
completer=completer,
auto_suggest=auto_suggest,
accept_action=accept_action,
initial_document=Document(default),
),
style=style or DEFAULT_STYLE,
clipboard=clipboard,
key_bindings_registry=key_bindings_registry,
get_title=get_title,
mouse_support=mouse_support,
editing_mode=editing_mode,
erase_when_done=erase_when_done,
on_abort=on_abort,
on_exit=on_exit)
def prompt(message='', **kwargs):
"""
Get input from the user and return it.
This is a wrapper around a lot of ``prompt_toolkit`` functionality and can
be a replacement for `raw_input`. (or GNU readline.)
If you want to keep your history across several calls, create one
:class:`~prompt_toolkit.history.History` instance and pass it every time.
This function accepts many keyword arguments. Except for the following,
they are a proxy to the arguments of :func:`.create_prompt_application`.
:param patch_stdout: Replace ``sys.stdout`` by a proxy that ensures that
print statements from other threads won't destroy the prompt. (They
will be printed above the prompt instead.)
:param return_asyncio_coroutine: When True, return a asyncio coroutine. (Python >3.3)
:param true_color: When True, use 24bit colors instead of 256 colors.
:param refresh_interval: (number; in seconds) When given, refresh the UI
every so many seconds.
"""
patch_stdout = kwargs.pop('patch_stdout', False)
return_asyncio_coroutine = kwargs.pop('return_asyncio_coroutine', False)
true_color = kwargs.pop('true_color', False)
refresh_interval = kwargs.pop('refresh_interval', 0)
eventloop = kwargs.pop('eventloop', None)
application = create_prompt_application(message, **kwargs)
return run_application(application,
patch_stdout=patch_stdout,
return_asyncio_coroutine=return_asyncio_coroutine,
true_color=true_color,
refresh_interval=refresh_interval,
eventloop=eventloop)
def run_application(
application, patch_stdout=False, return_asyncio_coroutine=False,
true_color=False, refresh_interval=0, eventloop=None):
"""
Run a prompt toolkit application.
:param patch_stdout: Replace ``sys.stdout`` by a proxy that ensures that
print statements from other threads won't destroy the prompt. (They
will be printed above the prompt instead.)
:param return_asyncio_coroutine: When True, return a asyncio coroutine. (Python >3.3)
:param true_color: When True, use 24bit colors instead of 256 colors.
:param refresh_interval: (number; in seconds) When given, refresh the UI
every so many seconds.
"""
assert isinstance(application, Application)
if return_asyncio_coroutine:
eventloop = create_asyncio_eventloop()
else:
eventloop = eventloop or create_eventloop()
# Create CommandLineInterface.
cli = CommandLineInterface(
application=application,
eventloop=eventloop,
output=create_output(true_color=true_color))
# Set up refresh interval.
if refresh_interval:
done = [False]
def start_refresh_loop(cli):
def run():
while not done[0]:
time.sleep(refresh_interval)
cli.request_redraw()
t = threading.Thread(target=run)
t.daemon = True
t.start()
def stop_refresh_loop(cli):
done[0] = True
cli.on_start += start_refresh_loop
cli.on_stop += stop_refresh_loop
# Replace stdout.
patch_context = cli.patch_stdout_context() if patch_stdout else DummyContext()
# Read input and return it.
if return_asyncio_coroutine:
# Create an asyncio coroutine and call it.
exec_context = {'patch_context': patch_context, 'cli': cli,
'Document': Document}
exec_(textwrap.dedent('''
def prompt_coro():
# Inline import, because it slows down startup when asyncio is not
# needed.
import asyncio
@asyncio.coroutine
def run():
with patch_context:
result = yield from cli.run_async(reset_current_buffer=False)
if isinstance(result, Document): # Backwards-compatibility.
return result.text
return result
return run()
'''), exec_context)
return exec_context['prompt_coro']()
else:
# Note: We pass `reset_current_buffer=False`, because that way it's easy to
# give DEFAULT_BUFFER a default value, without it getting erased. We
# don't have to reset anyway, because this is the first and only time
# that this CommandLineInterface will run.
try:
with patch_context:
result = cli.run(reset_current_buffer=False)
if isinstance(result, Document): # Backwards-compatibility.
return result.text
return result
finally:
eventloop.close()
def prompt_async(message='', **kwargs):
"""
Similar to :func:`.prompt`, but return an asyncio coroutine instead.
"""
kwargs['return_asyncio_coroutine'] = True
return prompt(message, **kwargs)
def create_confirm_application(message):
"""
Create a confirmation `Application` that returns True/False.
"""
registry = Registry()
@registry.add_binding('y')
@registry.add_binding('Y')
def _(event):
event.cli.buffers[DEFAULT_BUFFER].text = 'y'
event.cli.set_return_value(True)
@registry.add_binding('n')
@registry.add_binding('N')
@registry.add_binding(Keys.ControlC)
def _(event):
event.cli.buffers[DEFAULT_BUFFER].text = 'n'
event.cli.set_return_value(False)
return create_prompt_application(message, key_bindings_registry=registry)
def confirm(message='Confirm (y or n) '):
"""
Display a confirmation prompt.
"""
assert isinstance(message, text_type)
app = create_confirm_application(message)
return run_application(app)
def print_tokens(tokens, style=None, true_color=False):
"""
Print a list of (Token, text) tuples in the given style to the output.
E.g.::
style = style_from_dict({
Token.Hello: '#ff0066',
Token.World: '#884444 italic',
})
tokens = [
(Token.Hello, 'Hello'),
(Token.World, 'World'),
]
print_tokens(tokens, style=style)
:param tokens: List of ``(Token, text)`` tuples.
:param style: :class:`.Style` instance for the color scheme.
:param true_color: When True, use 24bit colors instead of 256 colors.
"""
assert isinstance(style, Style)
output = create_output(true_color=true_color)
renderer_print_tokens(output, tokens, style)
def clear():
"""
Clear the screen.
"""
out = create_output()
out.erase_screen()
out.cursor_goto(0, 0)
out.flush()
# Deprecated alias for `prompt`.
get_input = prompt
# Deprecated alias for create_prompt_layout
create_default_layout = create_prompt_layout
# Deprecated alias for create_prompt_application
create_default_application = create_prompt_application
|