Library for building powerful interactive command line applications in Python

Related tags

python-prompt-toolkit
Overview

Python Prompt Toolkit

Build Status AppVeyor Latest Version RTD License Codecov

https://github.com/prompt-toolkit/python-prompt-toolkit/raw/master/docs/images/logo_400px.png

prompt_toolkit is a library for building powerful interactive command line applications in Python.

Read the documentation on readthedocs.

NOTICE: prompt_toolkit 3.0

Please notice that this branch is the prompt_toolkit 3.0 branch. For most users, it should be compatible with prompt_toolkit 2.0, but it requires at least Python 3.6. On the plus side, prompt_toolkit 3.0 is completely type annotated and uses asyncio natively.

Gallery

ptpython is an interactive Python Shell, build on top of prompt_toolkit.

https://github.com/prompt-toolkit/python-prompt-toolkit/raw/master/docs/images/ptpython.png

More examples

prompt_toolkit features

prompt_toolkit could be a replacement for GNU readline, but it can be much more than that.

Some features:

  • Pure Python.
  • Syntax highlighting of the input while typing. (For instance, with a Pygments lexer.)
  • Multi-line input editing.
  • Advanced code completion.
  • Both Emacs and Vi key bindings. (Similar to readline.)
  • Even some advanced Vi functionality, like named registers and digraphs.
  • Reverse and forward incremental search.
  • Works well with Unicode double width characters. (Chinese input.)
  • Selecting text for copy/paste. (Both Emacs and Vi style.)
  • Support for bracketed paste.
  • Mouse support for cursor positioning and scrolling.
  • Auto suggestions. (Like fish shell.)
  • Multiple input buffers.
  • No global state.
  • Lightweight, the only dependencies are Pygments and wcwidth.
  • Runs on Linux, OS X, FreeBSD, OpenBSD and Windows systems.
  • And much more...

Feel free to create tickets for bugs and feature requests, and create pull requests if you have nice patches that you would like to share with others.

Installation

pip install prompt_toolkit

For Conda, do:

conda install -c https://conda.anaconda.org/conda-forge prompt_toolkit

About Windows support

prompt_toolkit is cross platform, and everything that you build on top should run fine on both Unix and Windows systems. Windows support is best on recent Windows 10 builds, for which the command line window supports vt100 escape sequences. (If not supported, we fall back to using Win32 APIs for color and cursor movements).

It's worth noting that the implementation is a "best effort of what is possible". Both Unix and Windows terminals have their limitations. But in general, the Unix experience will still be a little better.

For Windows, it's recommended to use either cmder or conemu.

Getting started

The most simple example of the library would look like this:

from prompt_toolkit import prompt

if __name__ == '__main__':
    answer = prompt('Give me some input: ')
    print('You said: %s' % answer)

For more complex examples, have a look in the examples directory. All examples are chosen to demonstrate only one thing. Also, don't be afraid to look at the source code. The implementation of the prompt function could be a good start.

Philosophy

The source code of prompt_toolkit should be readable, concise and efficient. We prefer short functions focusing each on one task and for which the input and output types are clearly specified. We mostly prefer composition over inheritance, because inheritance can result in too much functionality in the same object. We prefer immutable objects where possible (objects don't change after initialization). Reusability is important. We absolutely refrain from having a changing global state, it should be possible to have multiple independent instances of the same code in the same process. The architecture should be layered: the lower levels operate on primitive operations and data structures giving -- when correctly combined -- all the possible flexibility; while at the higher level, there should be a simpler API, ready-to-use and sufficient for most use cases. Thinking about algorithms and efficiency is important, but avoid premature optimization.

Projects using prompt_toolkit

Special thanks to

  • Pygments: Syntax highlighter.
  • wcwidth: Determine columns needed for a wide characters.
Issues
  • prompt_toolkit 2.0  -  Will be released soon.

    prompt_toolkit 2.0 - Will be released soon.

    opened by jonathanslenders 31
  • Question: rename prompt_toolkit to prompt_toolkit2 or not?  (during a transition period).

    Question: rename prompt_toolkit to prompt_toolkit2 or not? (during a transition period).

    Hi everyone,

    I'm opening this issue to discuss whether or not we should rename prompt_toolkit to prompt_toolkit2.

    The problem that we are facing right now is that we want to release version 2.0, but it's backwards incompatible with 1.0. This would normally not be an issue, because the best practices tell you to install Python applications in a virtualenv. However, most prompt_toolkit applications are system tools, which are often installed with the system wide Python installation, and very often these are distributed through other channels like the repositories of Linux distributions. We don't want to break those.

    As I understand it, setuptools can install multiple versions of a package alongside each other. There is a __requires__ variable that is inspected by pkg_resources to make sure the right version of the package is loaded. (See, e.g.: https://stackoverflow.com/questions/13720065/what-does-requires-mean-in-python ). However, I'm not sure how well this works in practice.

    While I don't like it, if renaming this library to prompt_toolkit2 during a transition period is the only way to solve certain issues, then I'm in favor of doing it. The intend is to rename it back to prompt_toolkit when most applications are transitioned. (At that point, prompt_toolkit2 could remain an alias for prompt_toolkit.)

    I don't have much personal experience with issues like this, so all feedback is welcome.

    question 
    opened by jonathanslenders 30
  • Cannot use ansi escape codes in prompt

    Cannot use ansi escape codes in prompt

    This looks very ugly and is not what I intended at all.

    opened by LoganDark 20
  • customize amount of reserved space

    customize amount of reserved space

    Hi! It seems like using prompt-toolkit with xonsh reserves 8 lines at the bottom minimum. See https://github.com/jonathanslenders/python-prompt-toolkit/blob/9e96e1bf815b07edb5c266bf2ba9ae1d6e350746/prompt_toolkit/shortcuts.py#L232-L238 This is far too large to be usable for me. Is there any way that this could be customizable in some way? I'd really appreciate it...

    See the xonsh list for more discussion: https://groups.google.com/d/topic/xonsh/Y3L9GAcFwGM/discussion

    enhancement 
    opened by scopatz 17
  • Patched stdout does not allow ANSI escape codes

    Patched stdout does not allow ANSI escape codes

    Due to this line, ANSI escape codes are mangled and cannot be used by an application that also uses the patched stdout functionality. I was going to colorize messages from logging in my program with a formatter, but because of this it's not possible. I'm not even sure what the intent was here?

    https://github.com/jonathanslenders/python-prompt-toolkit/blame/master/prompt_toolkit/terminal/vt100_output.py#L184

    To not sound like a total downer, this module is super amazing and is really damn useful.

    bug 
    opened by trap15 17
  • Adding support for selecting text with shift + movement

    Adding support for selecting text with shift + movement

    This is a proposal for an implementation of text selection using shift + cursor movement as is customary in many GUI. This refers to issue #979.

    The implementation is based on defining a new boolean flag shift_mode in the SelectionState class. shift_mode is initialized to False by the class constructor and set to True by a call to SelectionState. enter_shift_mode() whenever a shift+movement binding is called to start selecting text in this fashion. There is an associated new shift_selection_mode filter. The advantage of proceeding this way are that

    1. the shift_mode flag is automatically destroyed when selection is exited by any means through any other bindings (because the SelectionState instance is destroyed). In that way, we are sure that the shift_mode flag will not persist to True by accident.
    2. it enables the shift-selection mode to co-exist for example with the Emacs marking mode (entered with ctrl-space). In principle, it could also co-exist with the vi-mode, but I haven't tested that as I am really not familiar with vi - so at the moment the corresponding binding definitions are only defined alongside the Emacs bindings, though they could in principle be defined with the basics bindings with some extra testing and tweaks.

    Behavior:

    • Shift + any cursor motion starts or extend the selection, accompanied by the corresponding cursor movement.
    • A cursor movement without shift will exit the selection (and moves the cursor).
    • The selection is replaced by any text that is typed (including enter, if multiline; backspace, which deletes the selection; and pasting/yanking - note: more tests might be needed here especially with regard to multiline paste).

    Cursor movements above refers to left, right, up, down, home & end (beginning & end of line), ctrl-left/right (word-by-word), ctrl-home/end (beginning/end of buffer). All missing shift- combinations of these keys have been added to keys.py (and set by default to do nothing in bindings/basic.py). Ctrl-home/end have also been added, with the corresponding commands implemented as new readline-style commands in named_commands.py. For completeness, ctrl/shift-insert keys have also been added as these are sometimes used for copy/paste. All these new key combinations are correctly converted to key-presses in input/win32.py.

    I have tested this implementation stand-alone as well as in IPython 7.6.1 (through applying the same changes to prompt_toolkit 2.0.9 - apart from removing the type hints). Everything seems to work well, without any changes required to the IPython source code itself.

    Happy to get some feedback at this stage, of what could be improved or done differently. I will continue to do more testing with multiline pasting in the meantime.

    opened by scoennz 16
  • Actually use IPython input transformer to get correct syntax

    Actually use IPython input transformer to get correct syntax

    This uses IPython input transformer to detect if the syntax is correct IPython.

    Things that are invalid IPython do not go through : 1 ! 1 do not validate; a =! ls still does. ?,??do validate; not ???. And so on and so forth.

    opened by Carreau 15
  • Integration of finalterm/iterm2 escape sequences for shell integration.

    Integration of finalterm/iterm2 escape sequences for shell integration.

    Have a look at following escape sequences: before_prompt, after_prompt, before_output, after_output:

    https://groups.google.com/forum/#!msg/iterm2-discuss/URKCBtS0228/rs5Ive4PCAAJ https://iterm2.com/shell_integration.html https://github.com/asmeurer/iterm2-tools/blob/master/iterm2_tools/shell_integration.py

    See: https://github.com/ipython/ipython/issues/8724

    enhancement 
    opened by jonathanslenders 15
  • ThreadedHistory: invoke history load callback on event loop

    ThreadedHistory: invoke history load callback on event loop

    Successor to #1159, but with a nice, compact commit history. Here is the original description:

    Fixes issue #1158, and seems to work in Xonsh as well.

    Depends on ThreadedHistory and Application being able to rendezvous on same event loop. While this may not be possible for history in general, I think it is an acceptable restriction on ThreadedHistory.

    bug 
    opened by bobhy 14
  • Multi-line insertion

    Multi-line insertion

    Added Shift-I Vi command in block selection mode to insert text at the beginning of each line of the block.

    enhancement 
    opened by davidbrochart 14
  • ScrollablePane is managing styles differently than HSplit

    ScrollablePane is managing styles differently than HSplit

    I'm trying to create a new component of a table, I'm pretty much there (thanks for the ScrollablePane!) , but I can't figure out how to manage the styles well.

    My idea is to:

    • Change the background of each row between two values class:row and class:row.alternate
    • Highlight the focused row with class:focused, till the end of the screen.

    Short version

    (the full code is below)

    When using HSplit directly like:

                ...
                children=[
                    self.table_header,
                    Window(height=1, char="─", style="class:header.separator"),
                    HSplit(self.rows),
                ],
    

    The result is:

    The same code with the only change of using ScrollablePane like:

                ...
                children=[
                    self.table_header,
                    Window(height=1, char="─", style="class:header.separator"),
                    ScrollablePane(
                        content=HSplit(self.rows),
                        display_arrows=False,
                    ),
                ],
    

    The result changes to:

    Long version

    I created a Table object that inherited from HSplit, created a _set_row_widths method that calculated the desired size of each cell based on the width of the buffer, and set it in the dimensions of the rows.

    It also guessed the header from the contents of the data for each of the cases.

    Then the data of each row was passed to _Row, a class inherited from VSplit that set the style of the focused line, created a row of Windows with a FormattedTextControl component for each row, with only the first one focusable.

    To manage the styles, I've initialized each row with either class:row or class:row.alternate, and then I use a get_style helper function to attach the class:focused style to the focused row components.

    from typing import Callable, Generic, List, Optional, TypeVar, Union
    
    from prompt_toolkit.application import get_app
    from prompt_toolkit.filters import Condition
    from prompt_toolkit.formatted_text import StyleAndTextTuples, to_formatted_text
    from prompt_toolkit.formatted_text.utils import fragment_list_to_text
    from prompt_toolkit.key_binding import KeyBindings, KeyBindingsBase, merge_key_bindings
    from prompt_toolkit.key_binding.key_processor import KeyPressEvent
    from prompt_toolkit.keys import Keys
    from prompt_toolkit.layout import ScrollablePane
    from prompt_toolkit.layout.containers import (
        Container,
        HorizontalAlign,
        HSplit,
        VerticalAlign,
        VSplit,
        Window,
    )
    from prompt_toolkit.layout.controls import FormattedTextControl
    from prompt_toolkit.layout.dimension import AnyDimension, max_layout_dimensions
    from prompt_toolkit.layout.margins import ConditionalMargin, ScrollbarMargin
    from prompt_toolkit.layout.mouse_handlers import MouseHandlers
    from prompt_toolkit.layout.screen import Screen, WritePosition
    from prompt_toolkit.mouse_events import MouseEvent, MouseEventType
    from prompt_toolkit.styles import Style
    from pydantic import BaseModel  # noqa: E0611
    
    from .key_bindings import table_bindings
    
    RowData = TypeVar("RowData")
    TableData = List[RowData]
    
    
    class Table(HSplit):
        """Define a table.
    
        Args:
            header
            data: Data to print
            handler: Called when the row is clicked, no parameters are passed to this
                callable.
        """
    
        def __init__(
            self,
            data: TableData[RowData],
            header: Optional[List[str]] = None,
            fill_width: bool = False,
            window_too_small: Optional[Container] = None,
            align: VerticalAlign = VerticalAlign.JUSTIFY,
            padding: AnyDimension = 0,
            padding_char: Optional[str] = None,
            padding_style: str = "",
            width: AnyDimension = None,
            height: AnyDimension = None,
            z_index: Optional[int] = None,
            modal: bool = False,
            key_bindings: Optional[KeyBindingsBase] = None,
            style: Union[str, Callable[[], str]] = "",
        ) -> None:
            """Initialize the widget."""
            self.fill_width = fill_width
            if header is None:
                if isinstance(data[0], list):  # If is a list of lists
                    raise ValueError("You need to specify a header for the table")
                elif isinstance(data[0], dict):  # If is a list of dictionaries
                    header = [key.title() for key in data[0].keys()]
                elif isinstance(data[0], BaseModel):  # If is a list of pydantic objects
                    header = [
                        property["title"]
                        for _, property in data[0].schema()["properties"].items()
                    ]
    
            self.data: List[RowData] = data
            self.header = header
            self.table_header = _Row(self.header, style="class:header", focusable=False)
    
            if key_bindings is None:
                key_bindings = KeyBindings()
            key_bindings = merge_key_bindings([table_bindings, key_bindings])
    
            self.rows: List[_Row] = []
            for row in self.data:
                if len(self.rows) % 2 == 0:
                    style = "class:row.alternate"
                else:
                    style = "class:row"
                self.rows.append(_Row(row, style=style))
    
            super().__init__(
                children=[
                    self.table_header,
                    Window(height=1, char="─", style="class:header.separator"),
                    ScrollablePane(
                        content=HSplit(self.rows),
                        display_arrows=False,
                    ),
                ],
                window_too_small=window_too_small,
                align=align,
                padding=padding,
                padding_char=padding_char,
                padding_style=padding_style,
                width=width,
                height=height,
                z_index=z_index,
                modal=modal,
                key_bindings=key_bindings,
                style=style,
            )
    
        def _set_row_widths(self, width: int) -> None:
            """Set the row widths.
    
            Otherwise each row will decided based on their content, breaking the table.
            """
            dimensions = []
            # Get the dimensions of each column of each row in a list of lists
            for row in [self.table_header, *self.rows]:
                dimensions.append([column.preferred_width(width) for column in row.columns])
    
            # Transpose it so we have a list of column dimensions, so we can get the max
            # per column.
            table_width_dimensions = [
                max_layout_dimensions(list(i)) for i in zip(*dimensions)
            ]
    
            # Set the max dimension to the preferred if we don't want to use the whole
            # screen
            if not self.fill_width:
                for dimension in table_width_dimensions:
                    dimension.max = dimension.preferred
    
            # Set the widths of all elements
            for row in [self.table_header, *self.rows]:
                height = row.preferred_height(width=width, max_available_height=10000)
                for column_index in range(0, len(table_width_dimensions)):
                    row.columns[column_index].width = table_width_dimensions[column_index]
                    row.columns[column_index].height = height
    
        def write_to_screen(
            self,
            screen: Screen,
            mouse_handlers: MouseHandlers,
            write_position: WritePosition,
            parent_style: str,
            erase_bg: bool,
            z_index: Optional[int],
        ) -> None:
            """
            Render the prompt to a `Screen` instance.
    
            :param screen: The :class:`~prompt_toolkit.layout.screen.Screen` class
                to which the output has to be written.
            """
            self._set_row_widths(write_position.width)
            super().write_to_screen(
                screen=screen,
                mouse_handlers=mouse_handlers,
                write_position=write_position,
                parent_style=parent_style,
                erase_bg=erase_bg,
                z_index=z_index,
            )
    
    
    class _Row(VSplit):
        """Define row.
    
        Args:
            text: text to print
        """
    
        def __init__(
            self,
            data: RowData,
            focusable: bool = True,
            window_too_small: Optional[Container] = None,
            align: HorizontalAlign = HorizontalAlign.LEFT,
            padding: AnyDimension = 3,
            padding_char: Optional[str] = " ",
            padding_style: str = "",
            width: AnyDimension = None,
            height: AnyDimension = None,
            z_index: Optional[int] = None,
            modal: bool = False,
            key_bindings: Optional[KeyBindingsBase] = None,
            style: Union[str, Callable[[], str]] = "class:row",
        ) -> None:
            """Initialize the widget."""
            # Define the row data
            self.data = data
    
            if isinstance(data, list):
                column_data = data
            elif isinstance(data, dict):
                column_data = [value for _, value in data.items()]
            elif isinstance(data, BaseModel):
                column_data = [value for _, value in data.dict().items()]
    
            # Define the row style
            def get_style() -> Union[str, Callable[[], str]]:
                if get_app().layout.has_focus(self):
                    return f"{self.style},focused"
                else:
                    return self.style
    
            self.columns: List[Window] = []
    
            for value in column_data:
                # Only allow to focus the first cell of a row
                if focusable and len(self.columns) == 0:
                    focusable = True
                else:
                    focusable = False
    
                self.columns.append(
                    Window(
                        FormattedTextControl(str(value), focusable=focusable),
                        style=get_style,  # type: ignore
                        always_hide_cursor=True,
                        dont_extend_height=True,
                        wrap_lines=True,
                    )
                )
            super().__init__(
                children=self.columns,
                window_too_small=window_too_small,
                align=align,
                padding=padding,
                padding_char=padding_char,
                padding_style=get_style, # type: ignore
                width=width,
                height=height,
                z_index=z_index,
                modal=modal,
                key_bindings=key_bindings,
                style=style,
            )
    

    If I try to use get_style in the super().__init__() call of _Row I get an RecursionError: maximum recursion depth exceeded in comparison error.

    And I have to add # type: ignore when setting the get_style in the _Row padding_style and in the Window style argument as mypy shows Argument "style" to "Window" has incompatible type "Callable[[], Union[str, Callable[[], str]]]"; expected "Union[str, Callable[[], str]]", which makes me think I'm defining the get_style function wrong :(

    And even with the HSplit case, I didn't manage to make the highlighted background color go till the end of the screen.

    I planned to create a separate package until the interface is stable, and if you like the approach, I'd do a PR with it's contents.

    Sorry for the long post and I hope you can help me :)

    opened by lyz-code 1
  • Add support for some CSI 27 modified variants of Enter

    Add support for some CSI 27 modified variants of Enter

    xterm has 3 different disambiguated key modes intended to be used by applications that wish to distinguish keyboard modifiers for certain keypresses. These emit CSI 27 escapes with a modifiers bitmask field, and may be enabled by configuration.

    We can't parse these properly, so just add support for a few common modified variants of Enter in the escape sequence list. These variants previously had no distinct encoding, so the CSI variants have been adopted by some other terms, namely foot.

    opened by RPigott 0
  • buffer.insert_text with color?

    buffer.insert_text with color?

    I'm trying to create a simple log, but I want the log to have colors.

        buffer = Buffer()  # Editable buffer.
        main_window = Window(content=BufferControl(buffer=buffer))
        status_window = Window(height=1, content=FormattedTextControl(text="Status Bar"))
        root_container = HSplit([main_window, status_window])
        layout = Layout(root_container)
        app = Application(key_bindings=kb, layout=layout, full_screen=True)
        app.run()
    

    at some point in a thread I run buffer.insert_text which works just as expected, but I can't put any color to it. If I try ansi It gets escaped in a weird way, ANSI, HTML, format_text and other similar tools won't work.

    How can I print color in a buffer?

    opened by academo 0
  • [Question] Set a custom delimiter in NestedCompletions

    [Question] Set a custom delimiter in NestedCompletions

    I am using python-prompt-toolkit for Autocompletion and its working perfectly fine for single completion .but i need to use Nested completion. consider the following example from docs:

    
    from prompt_toolkit import prompt
    from prompt_toolkit.completion import NestedCompleter
    
    
    completer = NestedCompleter.from_nested_dict(
        {
            "show": 
                {"version": None,
               
               "clock": None, 
                
                "ip": {"interface": {"brief": None}}
                },
            "exit": None,
        }
    )
    
    
    def main():
        text = prompt("Type a command: ", completer=completer)
        print("You said: %s" % text)
    
    
    if __name__ == "__main__":
        main()
    
    

    while it does work,it only works when i use space as a delimiter(i.e,keep space between words) to separate the words,like show version.however i want to use '\\' or '/'(depending on os) as delimiter,so it would be like show/ip/interface/brief(similar to how shell path completion works).i know you can do that,but i can't figure out how?.Thanks in advance

    opened by Justaus3r 0
  • Add Python 3.10 to GitHub workflow.

    Add Python 3.10 to GitHub workflow.

    null

    opened by jonathanslenders 0
  • progress dialog like tqdm

    progress dialog like tqdm

    https://github.com/prompt-toolkit/python-prompt-toolkit/blob/master/examples/dialogs/progress_dialog.py

    hello, how can update percent like tqdm? i

    example tqdm code: pbar = tqdm(totalpercent) pbar.update(1)

    i want to do this in progress dialog

    opened by aw432325 0
  • `operate-and-get-next` demo no longer works

    `operate-and-get-next` demo no longer works

    https://github.com/prompt-toolkit/python-prompt-toolkit/blob/master/examples/prompts/operate-and-get-next.py

    I remember that ctrl-o used to work in v2.0 but it no longer works in v3.0.

    opened by randy3k 1
  • NEW: check and evaluate CURSOR FORWARD command after CSI

    NEW: check and evaluate CURSOR FORWARD command after CSI

    until now, only the SELECT GRAPHIC RENDITION following a CONTROL SEQUENCE INTRODUCER was implemented in order to render an invoming ANSI ART sequence. Considering standard ANSI ART (in former times widely used in BBSes), the result after rendering the respective incoming character streams looked like this:

    01_render_ansi_art__original

    after integrating this commit (pull request) any forward cursor movements specified within the input ansi art character stream will be rendered correctly, as seen here:

    02_render_ansi_art__new

    the code for testing could look like this:

    from prompt_toolkit import print_formatted_text
    from prompt_toolkit.formatted_text import HTML, FormattedText, ANSI
    
    print = print_formatted_text
    
    print(ANSI(
    '''
    \x1b[0m
    \x1b[61C\x1b[1m▄\x1b[0m
    \x1b[19C\x1b[1;30m▄\x1b[0m\x1b[41C▄
    \x1b[19C\x1b[1;30m▄\x1b[0m\x1b[41C\x1b[1;30m▀\x1b[0m
    \x1b[19C\x1b[1;30m▀\x1b[0m\x1b[14C\x1b[1;34m▄\x1b[0;34m▄\x1b[1m \x1b[0m\x1b[24C▒
    \x1b[19C\x1b[1;30m█\x1b[0m\x1b[9C\x1b[34m▄▀▀\x1b[1m▀▀\x1b[36m▄▄\x1b[0;34m▀▄\x1b[1m          \x1b[0m  \x1b[34m▄\x1b[1m▄▀▀\x1b[0;34m▀▄\x1b[1m  \x1b[0m\x1b[3C░
    \x1b[12C\x1b[1;30m   ▄ ▄▄ ▄▄▄▄▄▄\x1b[0;34m ▄▀\x1b[1m \x1b[36m▄▀▀\x1b[46m▒▓█\x1b[40m▀\x1b[30m▄▄▄\x1b[0;34m▀▀\x1b[1;36m▄▄▄▄▄\x1b[34m▀\x1b[30m▄\x1b[0;34m▀\x1b[36m▄▄\x1b[1;46m░▒▓\x1b[40m▄\x1b[0;34m▀\x1b[1;30m▄▄▄\x1b[0m▄\x1b[1;30m ▄\x1b[0m▄\x1b[1;30m \x1b[0m▄▄\x1b[1;30m \x1b[37m▄▄\x1b[0m
    \x1b[19C\x1b[1;30m▄\x1b[0m\x1b[6C\x1b[34m█\x1b[1m \x1b[0;36m▄\x1b[1;46m░▒\x1b[0m\x1b[3C\x1b[36m▄▄\x1b[37m \x1b[34m  \x1b[36m▄\x1b[1;46m▓\x1b[40m▀▀▀\x1b[46m▓█\x1b[0m  \x1b[36m▄\x1b[1;46m░\x1b[0;36m▀▀▀\x1b[1;46m▓█\x1b[40m▀\x1b[0;34m▄\x1b[37m\x1b[4C\x1b[1;30m▄\x1b[0m
    \x1b[19C\x1b[1;30m█\x1b[0m\x1b[5C\x1b[1;34m█ \x1b[0;36m▄\x1b[1;46m░░\x1b[0;36m█▀██\x1b[1;30;46m░░\x1b[0;36m█\x1b[37m \x1b[1;36;46m░▒\x1b[0m\x1b[4C\x1b[1;36;46m▒\x1b[40m▀\x1b[0m \x1b[36m██\x1b[37m\x1b[4C\x1b[1;36m▀\x1b[34m▄▀\x1b[0m\x1b[5C\x1b[1;30m█\x1b[0m
    \x1b[19C\x1b[1;30m█\x1b[0m \x1b[34m \x1b[37m  \x1b[34m▄\x1b[1m▄▀\x1b[0m \x1b[36m▀▀\x1b[37m  \x1b[1;30;46m░░░\x1b[0;36m▀\x1b[37m \x1b[1;30;46m░░\x1b[0;36m█\x1b[1;30mRV\x1b[0;36m▄\x1b[1;30;46m░\x1b[36m░\x1b[30;40m \x1b[0;36m█\x1b[1;30;46m░\x1b[0;36m█▄\x1b[37m\x1b[4C\x1b[1;30m■\x1b[0;34m█\x1b[37m\x1b[5C\x1b[1;30m█\x1b[0m
    \x1b[10C\x1b[1m▄▄\x1b[30m \x1b[0m▄▄\x1b[1;30m \x1b[0m▄\x1b[1;30m▄\x1b[0m▄▄\x1b[1;30m▄▄▄\x1b[0;34m█\x1b[37m \x1b[1;30m▄▄\x1b[46m▓▒░\x1b[0;36m▄\x1b[1;30;46m░\x1b[0;36m▀\x1b[37m \x1b[1;34m▄\x1b[0;34m▄\x1b[37m \x1b[1;30;46m░▒▓▓\x1b[40m▄\x1b[46m░▒▓\x1b[40m▀\x1b[0m \x1b[36m█\x1b[1;30;46m░\x1b[0;36m█\x1b[1;30;46m░▒▓\x1b[40m▀ \x1b[34m■\x1b[30m▄▄▄▄ ▄▄ ▄\x1b[0m
    \x1b[23C\x1b[34m▀\x1b[1m▄\x1b[0m \x1b[1;30m▀▀\x1b[0;36m▀▀\x1b[37m \x1b[1;34m▄\x1b[0;34m▄\x1b[1m▀\x1b[33mSAC\x1b[0;34m▄\x1b[1;30m▀▀\x1b[0;34m▄▄\x1b[1;30m▀▀\x1b[34m▄▄\x1b[0;34m▄\x1b[37m \x1b[36m▀▀\x1b[1;30m▀▀\x1b[0;34m▄\x1b[1m▄▀\x1b[0m
    \x1b[19C░\x1b[4C\x1b[34m \x1b[1m▀▀\x1b[0;34m▀▀▀▀     \x1b[37m  \x1b[34m▀▀\x1b[37m  \x1b[1;34m▀▀\x1b[0m\x1b[3C\x1b[34m▀▀▀▀▀\x1b[37m\x1b[9C\x1b[1;30m█\x1b[0m
    \x1b[19C▒\x1b[41C\x1b[1;30m█\x1b[0m
    \x1b[19C\x1b[1;30m▄\x1b[0m\x1b[41C\x1b[1;30m▄\x1b[0m
    \x1b[19C▀\x1b[41C\x1b[1;30m▀\x1b[0m
    \x1b[19C\x1b[1m▀\x1b[0m\x1b[41C\x1b[1;30m▀\x1b[0m
    \x1b[0m
    '''
    ))
    
    opened by nnako 2
  • Breakpointhook breaks breakpoint() when called in an executor.

    Breakpointhook breaks breakpoint() when called in an executor.

    We have to check whether the breakpoint is called in the event loop thread or not.

    opened by jonathanslenders 0
  • Project using prompt-toolkit

    Project using prompt-toolkit

    Hi, I'm opening an issue to have a new project listed in "Projects using prompt_toolkit." Thanks!

    nlcc A natural language prompt for computational chemistry tasks:

    Demo and Twitter

    opened by whitead 0
Owner
prompt-toolkit
Tools for building command line applications in Python
prompt-toolkit
Library for building powerful interactive command line applications in Python

Python Prompt Toolkit prompt_toolkit is a library for building powerful interactive command line applications in Python. Read the documentation on rea

prompt-toolkit 7.3k Oct 23, 2021
Pythonic command line arguments parser, that will make you smile

docopt creates beautiful command-line interfaces Video introduction to docopt: PyCon UK 2012: Create *beautiful* command-line interfaces with Python N

null 7.5k Oct 25, 2021
Python Fire is a library for automatically generating command line interfaces (CLIs) from absolutely any Python object.

Python Fire Python Fire is a library for automatically generating command line interfaces (CLIs) from absolutely any Python object. Python Fire is a s

Google 20.3k Oct 24, 2021
Python library that measures the width of unicode strings rendered to a terminal

Introduction This library is mainly for CLI programs that carefully produce output for Terminals, or make pretend to be an emulator. Problem Statement

Jeff Quast 250 Oct 15, 2021
Python and tab completion, better together.

argcomplete - Bash tab completion for argparse Tab complete all the things! Argcomplete provides easy, extensible command line tab completion of argum

Andrey Kislyuk 991 Oct 22, 2021
Color text streams with a polished command line interface

colout(1) -- Color Up Arbitrary Command Output Synopsis colout [-h] [-r RESOURCE] colout [-g] [-c] [-l min,max] [-a] [-t] [-T DIR] [-P DIR] [-d COLORM

nojhan 1.1k Sep 28, 2021
Typer, build great CLIs. Easy to code. Based on Python type hints.

Typer, build great CLIs. Easy to code. Based on Python type hints. Documentation: https://typer.tiangolo.com Source Code: https://github.com/tiangolo/

Sebastián Ramírez 6.5k Oct 22, 2021
Simple cross-platform colored terminal text in Python

Colorama Makes ANSI escape character sequences (for producing colored terminal text and cursor positioning) work under MS Windows. PyPI for releases |

Jonathan Hartley 2.6k Oct 23, 2021
Python Command-line Application Tools

Clint: Python Command-line Interface Tools Clint is a module filled with a set of awesome tools for developing commandline applications. C ommand L in

Kenneth Reitz Archive 57 Oct 12, 2021
Rich is a Python library for rich text and beautiful formatting in the terminal.

Rich 中文 readme • lengua española readme • Läs på svenska Rich is a Python library for rich text and beautiful formatting in the terminal. The Rich API

Will McGugan 30.4k Oct 24, 2021
A thin, practical wrapper around terminal capabilities in Python

Blessings Coding with Blessings looks like this... from blessings import Terminal t = Terminal() print(t.bold('Hi there!')) print(t.bold_red_on_brig

Erik Rose 1.3k Oct 19, 2021
Cement is an advanced Application Framework for Python, with a primary focus on CLI

Cement Framework Cement is an advanced Application Framework for Python, with a primary focus on Command Line Interfaces (CLI). Its goal is to introdu

Data Folk Labs, LLC 1k Oct 25, 2021
sane is a command runner made simple.

sane is a command runner made simple.

Miguel M. 14 Jul 24, 2021
plotting in the terminal

bashplotlib plotting in the terminal what is it? bashplotlib is a python package and command line tool for making basic plots in the terminal. It's a

Greg Lamp 1.6k Oct 17, 2021
Python composable command line interface toolkit

$ click_ Click is a Python package for creating beautiful command line interfaces in a composable way with as little code as necessary. It's the "Comm

The Pallets Projects 11.5k Oct 24, 2021
A cross platform package to do curses-like operations, plus higher level APIs and widgets to create text UIs and ASCII art animations

ASCIIMATICS Asciimatics is a package to help people create full-screen text UIs (from interactive forms to ASCII animations) on any platform. It is li

null 2.8k Oct 23, 2021
A fast, stateless http slash commands framework for scale. Built by the Crunchy bot team.

Roid ?? A fast, stateless http slash commands framework for scale. Built by the Crunchy bot team. ?? Installation You can install roid in it's default

Harrison Burt 7 Oct 17, 2021
Command line animations based on the state of the system

shell-emotions Command line animations based on the state of the system for Linux or Windows 10 The ascii animations were created using a modified ver

Simon Malave 61 Oct 21, 2021
Textual is a TUI (Text User Interface) framework for Python using Rich as a renderer.

Textual is a TUI (Text User Interface) framework for Python using Rich as a renderer. The end goal is to be able to rapidly create rich termin

Will McGugan 5.8k Oct 17, 2021