Esempio n. 1
0
def main():
    # vytvoření aplikace s textovým uživatelským rozhraním
    application = Application(layout=layout,
                              key_bindings=key_bindings,
                              full_screen=True)

    # spuštění aplikace
    application.run()
Esempio n. 2
0
def cli():
    app = Application(full_screen=True,
                      layout=LAYOUT,
                      style=patched_style(),
                      color_depth=ColorDepth.TRUE_COLOR,
                      key_bindings=KG)
    app.editing_mode = EditingMode.VI
    app.run()
    shortcuts.clear_title()
Esempio n. 3
0
def prompt(text: Union[str, FormattedText],
           title: str = '',
           actions: List[Action] = [],
           **kwargs: Any) -> None:
    """A simple and extensible prompt helper routine

    :param text: Text to be printed before the prompt, it can be formatted text
    :type  text: str or FormattedText
    :param title: Title to be shown in a bottom bar
    :type  title: str
    :param actions: A list of Actions as defined in `Action`.
    :type  actions: [Action]
    :param kwargs: kwargs to prompt_toolkit application class
    """
    assert (isinstance(actions, list))
    assert (type(title) == str)

    kb = KeyBindings()

    for action in actions:
        kb.add(action.key)(action.action)

    print_formatted_text(FormattedText(text))

    root_container = HSplit([
        Window(wrap_lines=True,
               height=1,
               align=WindowAlign.LEFT,
               always_hide_cursor=True,
               style='bg:ansiblack fg:ansiwhite',
               content=FormattedTextControl(
                   focusable=False,
                   text=HTML(' '.join(
                       "{a.name}<yellow>[{a.key}]</yellow>".format(a=a)
                       for a in actions))))
    ] + ([
        Window(height=1,
               align=WindowAlign.LEFT,
               always_hide_cursor=True,
               style='bold fg:ansipurple bg:ansiwhite',
               content=FormattedTextControl(focusable=False, text=title))
    ] if title else []))

    app = Application(layout=Layout(root_container), key_bindings=kb, **kwargs)
    app.run()
Esempio n. 4
0
def loop(cmd, history_file):
    buf = create_buffer(cmd, history_file)
    key_bindings = KeyBindings()
    bind_keys(buf, key_bindings)
    layout = create_layout(
        buffer=buf,
        multiline=True,
        lexer=SqlLexer,
        extra_input_processors=[
            ConditionalProcessor(
                processor=HighlightMatchingBracketProcessor(chars='[](){}'),
                filter=HasFocus(DEFAULT_BUFFER) & ~IsDone())
        ],
        get_bottom_toolbar_tokens=lambda: get_toolbar_tokens(cmd),
        get_prompt_tokens=lambda: [('class:prompt', 'cr> ')])
    output = get_default_output()
    app = Application(layout=layout,
                      style=style_from_pygments_cls(CrateStyle),
                      key_bindings=merge_key_bindings(
                          [key_bindings,
                           load_open_in_editor_bindings()]),
                      editing_mode=_get_editing_mode(),
                      output=output)
    cmd.get_num_columns = lambda: output.get_size().columns

    while True:
        try:
            text = app.run()
            if text:
                cmd.process(text)
            buf.reset()
        except ProgrammingError as e:
            if '401' in e.message:
                username = cmd.username
                password = cmd.password
                cmd.username = input('Username: '******'Bye!')
            return
Esempio n. 5
0
class CLI:
    def __init__(self, command, refresh_interval=2):
        self.setup_layout()
        self._command = command
        self._app = Application(layout=self._layout,
                                key_bindings=self.generate_keybindings(),
                                full_screen=False,
                                erase_when_done=True,
                                before_render=self.refresh,
                                min_redraw_interval=refresh_interval)

    def setup_layout(self):
        self._text_area = TextArea(
            text=f'Loading...\nPress control-c to quit.', read_only=True)
        self._frame = Frame(self._text_area)
        self._layout = Layout(container=self._frame)

    def generate_keybindings(self):
        kb = KeyBindings()
        kb.add('c-c')(self._exit_keybinding_listener)
        return kb

    def _exit_keybinding_listener(self, event):
        event.app.exit()

    def refresh(self, event):
        output = subprocess.check_output(self._command,
                                         shell=True,
                                         encoding=sys.stdout.encoding).strip()
        try:
            datum = int(output)
        except ValueError:
            raise ValueError('Command output needs to be a number')

        self._text_area.text = (f'Last run: {datetime.now()}\n\n'
                                f'{datum}\n\n'
                                f'Press control-c to quit.')

    def run(self):
        self._app.run()
Esempio n. 6
0
class PyTicker(object):
    def __init__(self, pyticker_db: PyTickerDBOperations):
        self._application = None
        self._pyticker_layout = PyTickerLayout(pyticker_db)
        self._watchlist_view = WatchListView()
        self._positions_view = PositionsView()
        self._pyticker_db = pyticker_db

    def init_application(self):
        layout = self._pyticker_layout.get_layout()
        self._application = Application(layout=layout,
                                        full_screen=True,
                                        key_bindings=bindings)

    def _invalidate(self):
        watchlist_stock_symbols, position_stock_symbols = self._pyticker_db.get_stock_symobls_to_fetch_quotes(
        )
        yahoo_client = YahooHttpClient(watchlist_stock_symbols,
                                       position_stock_symbols,
                                       self._pyticker_db)
        watchlist_text, position_text = yahoo_client.get_stock_quotes()
        WATCHLIST_STOCKS_TEXT.text = watchlist_text
        POSITION_STOCKS_TEXT.text = position_text
        self._application.invalidate()

    def run(self):
        watchlist_stock_symbols, position_stock_symbols = self._pyticker_db.get_stock_symobls_to_fetch_quotes(
        )
        yahoo_client = YahooHttpClient(watchlist_stock_symbols,
                                       position_stock_symbols,
                                       self._pyticker_db)
        watchlist_text, position_text = yahoo_client.get_stock_quotes()
        WATCHLIST_STOCKS_TEXT.text = watchlist_text
        POSITION_STOCKS_TEXT.text = position_text
        threading.Thread(target=lambda: every(1, self._invalidate),
                         daemon=True).start()
        self._application.run()
Esempio n. 7
0
    def run(self):
        root_container = self.get_container()
        kb = self.get_key_bindings()

        layout = Layout(root_container)
        style = Style([
            ('cursor-line', 'fg:ansiwhite bg:#003366'),
            ('cursor-line', 'fg:#CCCCCC bg:#003366'),
        ])

        app = Application(
            layout=layout,
            full_screen=True,
            key_bindings=kb,
            editing_mode=EditingMode.VI,
            mouse_support=True,
            style=style,
        )
        self.state.app = app
        self.state.layout = layout
        app.state = self.state

        app.run()
        self.state.print()
Esempio n. 8
0
def select_menu(items, display_format=None, max_height=10):
    """ Presents a list of options and allows the user to select one.

    This presents a static list of options and prompts the user to select one.
    This is similar to a completion menu but is different in that it does not
    allow a user to type and the returned value is always a member of the list.

    :type items: list
    :param list: The list of items to be selected from. If this list contains
    elements that are not strings the display_format option must be specified.

    :type display_format: Callable[[Any], str]
    :param display_format: A callable that takes a single element from the
    items list as input and returns a string used to represent the item in the
    menu.

    :type max_height: int
    :param max_height: The max number of items to show in the list at a time.

    :returns: The selected element from the items list.
    """
    app_bindings = KeyBindings()

    @app_bindings.add('c-c')
    def exit_app(event):
        event.app.exit(exception=KeyboardInterrupt, style='class:aborting')

    min_height = min(max_height, len(items))
    menu_window = Window(
        SelectionMenuControl(items, display_format=display_format),
        always_hide_cursor=False,
        height=Dimension(min=min_height, max=min_height),
        scroll_offsets=ScrollOffsets(),
        right_margins=[ScrollbarMargin()],
    )

    # Using a FloatContainer was the only way I was able to succesfully
    # limit the height and width of the window.
    content = FloatContainer(
        Window(height=Dimension(min=min_height, max=min_height)),
        [Float(menu_window, top=0, left=0)])
    app = Application(
        layout=Layout(content),
        key_bindings=app_bindings,
        erase_when_done=True,
    )
    return app.run()
Esempio n. 9
0
    def run(self):
        answer = None
        while True:
            try:
                widget = self._questions_iter.send(answer)
            except StopIteration:
                break

            layout = Layout(widget)
            app = Application(
                layout,
                full_screen=False,
                key_bindings=self._key_bindings,
                style=self._style,
            )
            c = widget.main_control()
            if c is not None:
                app.layout.focus(c)
            widget._handler = self._make_handler(app)

            try:
                answer = app.run()
            except Cancel:
                break
Esempio n. 10
0
def main():
    # vytvoření aplikace s textovým uživatelským rozhraním
    application = Application(full_screen=True)

    # spuštění aplikace
    application.run()
Esempio n. 11
0
class PtDebugCli:
    """ Command line interface using prompt_toolkit. """
    def __init__(self, debugger):
        self._filename = None
        self.sources = {}
        self.debugger = debugger
        self.debugger.events.on_stop += self.on_stop
        self.current_address_margin = CurrentAddressMargin()
        kb = KeyBindings()
        self.locals_processor = DisplayVariablesProcessor()

        self.source_buffer = Buffer(multiline=True)
        self.bar_buffer = Buffer(multiline=True)
        self.register_buffer = Buffer(multiline=True)
        self.logs_buffer = Buffer(multiline=True)

        @kb.add(Keys.F10, eager=True)
        def quit_(event):
            event.app.exit()

        @kb.add(Keys.F8)
        def clear_breakpoint_(event):
            if self.has_source():
                filename, row = self.get_current_location()
                self.debugger.clear_breakpoint(filename, row)

        @kb.add(Keys.F7)
        def set_breakpoint_(event):
            if self.has_source():
                filename, row = self.get_current_location()
                self.debugger.set_breakpoint(filename, row)

        @kb.add(Keys.F6)
        def step_(event):
            self.debugger.step()

        @kb.add(Keys.F5)
        def run_(event):
            self.debugger.run()

        @kb.add(Keys.F4)
        def stop_(event):
            self.debugger.stop()

        @kb.add(Keys.PageUp)
        def scroll_up_(event):
            self.source_buffer.cursor_up(count=15)

        @kb.add(Keys.PageDown)
        def scroll_down_(event):
            self.source_buffer.cursor_down(count=15)

        src_lexer = PygmentsLexer(CLexer)

        source_code_window = Window(
            content=BufferControl(
                buffer=self.source_buffer,
                lexer=src_lexer,
                input_processors=[self.locals_processor],
            ),
            left_margins=[self.current_address_margin,
                          NumberedMargin()],
            right_margins=[ScrollbarMargin(display_arrows=True)],
            cursorline=True,
        )

        register_window = Window(
            content=BufferControl(buffer=self.register_buffer), width=20)

        title_text = "Welcome to the ppci debugger version {} running in prompt_toolkit {}".format(
            ppci_version, ptk_version)

        help_text = ("F4=stop F5=run F6=step F7=set breakpoint" +
                     " F8=clear breakpoint F10=exit")

        # Application layout:
        body = HSplit([
            Window(content=FormattedTextControl(text=title_text), height=1),
            VSplit([
                HSplit([
                    Frame(
                        body=source_code_window,
                        title="source-code",
                    ),
                    Window(
                        content=BufferControl(buffer=self.logs_buffer),
                        height=2,
                    ),
                ]),
                Frame(body=register_window, title="registers"),
            ]),
            Window(
                content=FormattedTextControl(self.get_status_tokens),
                height=1,
            ),
            Window(content=FormattedTextControl(help_text), height=1),
        ])
        layout = Layout(body)

        style = style_from_pygments_cls(get_style_by_name("vim"))

        log_handler = MyHandler(self.logs_buffer)
        fmt = logging.Formatter(fmt=logformat)
        log_handler.setFormatter(fmt)
        log_handler.setLevel(logging.DEBUG)
        logging.getLogger().setLevel(logging.DEBUG)
        logging.getLogger().addHandler(log_handler)

        self._event_loop = get_event_loop()

        self.application = Application(layout=layout,
                                       style=style,
                                       key_bindings=kb,
                                       full_screen=True)

    def cmdloop(self):
        self.application.run()

    def get_status_tokens(self):
        tokens = []
        tokens.append(
            ("class:status", "STATUS={} ".format(self.debugger.status)))
        tokens.append(
            ("class:status", "PC={:08X} ".format(self.debugger.get_pc())))
        if self.debugger.has_symbols:
            loc = self.debugger.find_pc()
            if loc:
                filename, row = loc
                tokens.append(
                    ("class:status", "LOCATION={}:{}".format(filename, row)))
        return tokens

    def on_stop(self):
        """ Handle stopped event. """
        def callback():
            self.display_registers()
            self.highlight_source()
            self.evaluate_locals()
            self.application.invalidate()

        self._event_loop.call_soon_threadsafe(callback)

    def evaluate_locals(self):
        # Locals:
        localz = self.debugger.local_vars()
        self.locals_processor.variables.clear()
        for name, var in localz.items():
            value = self.debugger.eval_variable(var)
            var_text = "{} = {}".format(name, value)
            self.locals_processor.variables[var.loc.row] = var_text

    def has_source(self):
        return self._filename is not None

    def get_current_location(self):
        assert self.has_source()
        row = self.source_buffer.document.cursor_position_row + 1
        return self._filename, row

    def highlight_source(self):
        if self.debugger.has_symbols:
            loc = self.debugger.find_pc()
            if loc:
                filename, row = loc
                self.source_buffer.text = self.get_file_source(filename)
                self._filename = filename
                self.source_buffer.cursor_position = 3
                self.current_address_margin.current_line = row
            else:
                self.current_address_margin.current_line = None

    def display_registers(self):
        """ Update register buffer """
        registers = self.debugger.get_registers()
        register_values = self.debugger.get_register_values(registers)
        lines = ["Register values:"]
        if register_values:
            for register, value in register_values.items():
                size = register.bitsize // 4
                lines.append("{:>5.5s} : 0x{:0{sz}X}".format(str(register),
                                                             value,
                                                             sz=size))
        self.register_buffer.text = "\n".join(lines)

    def get_file_source(self, filename):
        if filename not in self.sources:
            with open(filename, "r") as f:
                source = f.read()
            self.sources[filename] = source
        return self.sources[filename]
Esempio n. 12
0
class LinkTable:
    def __init__(self, filepath):
        self.db = Database(filepath)
        cursor = FormattedTextControl(focusable=True,
                                      text=[("", CURSOR)],
                                      show_cursor=False)
        sep = Window(width=len(SEPARATOR), char=SEPARATOR, style="class:line")

        self.ids = Column("ID")
        self.names = Column("Name")
        self.sources = Column("Source")
        self.tags = Column("Tags")
        self.urls = Column("URL")

        table_header = VSplit([
            Label(text="", width=len(CURSOR)),
            sep,
            Label(self.ids.title, width=self.ids.width, style="bold"),
            sep,
            Label(self.names.title, width=self.names.width, style="bold"),
            sep,
            Label(self.tags.title, width=self.tags.width, style="bold"),
            sep,
            Label(self.sources.title, width=self.sources.width, style="bold"),
            sep,
            Label(self.urls.title, width=self.urls.width, style="bold"),
        ])
        self.selection = Window(cursor,
                                width=len(CURSOR),
                                style="class:selector")
        table_body = VSplit([
            self.selection,
            sep,
            Window(self.ids.col, width=self.ids.width),
            sep,
            Window(self.names.col, width=self.names.width),
            sep,
            Window(self.tags.col, width=self.tags.width),
            sep,
            Window(self.sources.col, width=self.sources.width),
            sep,
            Window(self.urls.col, width=self.urls.width),
        ])

        self.prompt = TextArea(
            multiline=False,
            focusable=True,
            accept_handler=self._do_search,
            get_line_prefix=self._get_prompt,
        )

        table = HSplit([table_header, table_body])
        layout = HSplit([table, self.prompt])

        kb = KeyBindings()

        @kb.add("c-c", eager=True)
        @kb.add("q", filter=has_focus(self.selection))
        def close(event):
            event.app.exit()

        @kb.add("s", filter=has_focus(self.selection))
        def start_search(event):
            event.app.layout.focus(self.prompt)

        @kb.add("o", filter=has_focus(self.selection))
        @kb.add(Keys.Enter, filter=has_focus(self.selection))
        def open_link(event):
            cursor = self.selection.content.text
            idx = len(cursor)

            selected = self.ids.col.text[idx - 1]
            link_id = int(selected[1])

            Link.open(self.db, link_id)

        @kb.add(Keys.Down, filter=has_focus(self.selection))
        def next_item(event):
            cursor = self.selection.content.text
            idx = len(cursor)
            max_idx = len(self.ids.col.text)

            if idx + 1 > max_idx:
                return

            cursor.insert(0, ("", "\n"))

        @kb.add(Keys.Up, filter=has_focus(self.selection))
        def prev_item(event):
            cursor = self.selection.content.text
            idx = len(cursor)

            if idx == 1:
                return

            cursor.pop(0)

        self.app = Application(layout=Layout(layout), key_bindings=kb)

    def run(self):
        self._do_search()
        self.app.run()

    def _do_search(self, inpt: Buffer = None):
        self.selection.content.text = [("", CURSOR)]
        self.ids.clear()
        self.names.clear()
        self.tags.clear()
        self.sources.clear()
        self.urls.clear()

        name = None
        tags = None

        if inpt is not None and len(inpt.text) > 0:
            terms = inpt.text.split(" ")

            tags = [t.replace("#", "") for t in terms if t.startswith("#")]
            name = " ".join(n for n in terms if not n.startswith("#"))

        links = Link.search(self.db,
                            name=name,
                            top=10,
                            tags=tags,
                            sort="visits")

        for idx, link in enumerate(links):

            newline = "\n" if idx < len(links) - 1 else ""

            self.ids.col.text.append(("", f"{link.id}{newline}"))
            self.names.col.text.append(("", f"{link.name}{newline}"))
            self.urls.col.text.append(("", f"{link.url_expanded}{newline}"))

            tags = ", ".join(f"#{t.name}" for t in link.tags)
            self.tags.col.text.append(("", f"{tags}{newline}"))

            source = "" if not link.source else link.source.name
            self.sources.col.text.append(("", f"{source}{newline}"))

        self.app.layout.focus(self.selection)

    def _get_prompt(self, line_no, other):

        if has_focus(self.prompt)():
            return "Search: "

        return "[s]earch | [o]pen | [q]uit"
Esempio n. 13
0
class MultiPane:
    def __init__(
        self,
        entries,
        preview_callback=None,
        input_callback=None,
        input_completions=None,
    ):
        if not entries or len(entries) == 0:
            raise RuntimeError("Entries cannot be empty.")
        self.entries = entries
        self.input_callback = input_callback
        self.preview_callback = preview_callback

        self.ansi_escape_8bit = re.compile(
            r"(?:\x1B[@-Z\\-_]|[\x80-\x9A\x9C-\x9F]|(?:\x1B\[|\x9B)[0-?]*[ -/]*[@-~])"
        )
        self.current_lineno = 1
        self.max_entry_width = min(
            max(
                map(
                    lambda x: len(x) + 1, self.ansi_escape_8bit.sub("", entries).split("\n")
                )
            ),
            48,
        )

        entries_text = ANSI(self.entries)
        entries_formatted_text = to_formatted_text(entries_text)
        entries_plain_text = fragment_list_to_text(entries_formatted_text)
        self.entries_control = FormattedBufferControl(
            buffer=Buffer(
                document=Document(entries_plain_text, 0),
                name="entries",
                on_cursor_position_changed=self.update_entries,
                read_only=True,
            ),
            focusable=True,
            formatted_text=entries_formatted_text,
            include_default_input_processors=False,
            input_processors=[FormatTextProcessor(), HighlightSelectionProcessor()],
        )

        if self.preview_callback:
            self.preview_text = ANSI(self.preview_callback(self.current_lineno))
            formatted_text = to_formatted_text(self.preview_text)
            plain_text = fragment_list_to_text(formatted_text)
            self.preview_control = FormattedBufferControl(
                buffer=Buffer(
                    document=Document(plain_text, 0),
                    name="preview",
                    on_cursor_position_changed=self.update_preview,
                    read_only=True,
                ),
                focusable=True,
                formatted_text=formatted_text,
                include_default_input_processors=False,
                input_processors=[FormatTextProcessor(), HighlightSelectionProcessor()],
            )
            # Alternative (not scrollable):
            # self.preview_control = FormattedTextControl(
            #     focusable=True,
            #     show_cursor=True,
            #     text=ANSI(self.preview_callback(self.current_lineno)),
            # )
            entries_container = VSplit(
                [
                    Window(
                        content=self.entries_control,
                        width=self.max_entry_width,
                        wrap_lines=True,
                    ),
                    Window(width=3, char=" | "),
                    Window(content=self.preview_control, wrap_lines=True),
                ]
            )
        else:
            entries_container = Window(
                content=self.entries_control,
                width=self.max_entry_width,
                wrap_lines=True,
            )
        if self.input_callback:
            self.search_field = SearchToolbar()
            self.input_field = TextArea(
                accept_handler=self.input_accept,
                completer=FuzzyWordCompleter(list(input_completions)),
                complete_while_typing=True,
                height=1,
                multiline=False,
                prompt="> ",
                search_field=self.search_field,
                wrap_lines=False,
            )
            self.root_container = FloatContainer(
                content=HSplit(
                    [entries_container, Window(height=1, char="-"), self.input_field,]
                ),
                floats=[
                    Float(
                        content=CompletionsMenu(max_height=16, scroll_offset=1),
                        xcursor=True,
                        ycursor=True,
                    )
                ],
            )

        else:
            self.root_container = entries_container
        self.layout = Layout(self.root_container)

        self.app = Application(full_screen=True, key_bindings=kb, layout=self.layout)

    def input_accept(self, buffer):
        self.input_callback(self.input_field.text)

    def get_lineno(self, text, pos):
        text = self.ansi_escape_8bit.sub("", text)
        lineno = 1
        for i, c in enumerate(text):
            if (c == ord(b"\n") or c == "\n") and i != pos:
                lineno += 1
            if i == pos:
                break
            i += 1
        return lineno

    def update_preview(self, buffer):
        self.update_entries(self.entries_control.buffer)

    def update_entries(self, buffer, force=False):
        new_lineno = self.get_lineno(self.entries, buffer.cursor_position)
        if force or self.current_lineno != new_lineno:
            self.current_lineno = new_lineno

            text = ANSI(self.preview_callback(self.current_lineno))
            formatted_text = to_formatted_text(text)
            plain_text = fragment_list_to_text(formatted_text)
            self.preview_control.buffer.set_document(
                Document(plain_text, 0), bypass_readonly=True
            )
            self.preview_control.formatted_lines = self.preview_control.parse_formatted_text(
                formatted_text
            )

    def replace_entries(self, entries):
        self.current_lineno = 1
        self.entries_control.buffer.set_document(
            Document(entries, 0), bypass_readonly=True
        )
        self.update_entries(self.entries_control.buffer, True)

    def run(self):
        self.app.run()
Esempio n. 14
0
class App:
    toolbar_style = Style([("bgcolor", "reverse"), ("color", "reverse")])
    error_text = ""
    output_text = ""
    script = ""

    def __init__(self, inpipe):
        self.inpipe = inpipe
        self.tempfile = tempfile.NamedTemporaryFile(mode="w", delete=True)
        self.initialize_nodes()

        root = VSplit(
            [
                # Input buffer and status line
                HSplit(
                    [
                        self.first_line,
                        Window(
                            content=BufferControl(
                                buffer=self.input_buffer,
                                # This lexer is disabled for now because
                                # I don't want to mess with colourschemes
                                # lexer=PygmentsLexer(PythonLexer),
                            )
                        ),
                        self.error_output,
                    ],
                    width=Dimension(),
                ),
                Window(width=1, char="|"),
                # Output display area
                Window(ignore_content_width=True, content=self.output, wrap_lines=True),
            ],
            width=Dimension(),
        )

        layout = Layout(root)

        self.app = Application(layout=layout, key_bindings=kb, full_screen=True)

    def initialize_nodes(self):
        self.first_line = FormattedTextToolbar(
            self.get_first_line_text(), style="#ffffff bg:#444444"
        )
        self.input_buffer = Buffer(on_text_changed=self.on_change)
        self.output = FormattedTextControl(text=self.get_output_text)
        self.error_output = FormattedTextToolbar(
            self.get_error_text, style="#ffffff bg:#444444"
        )

    def on_change(self, b):

        self.tempfile.seek(0)
        self.tempfile.truncate()
        self.tempfile.write("inpipe = {}\n{}".format(self.inpipe, b.text))
        self.tempfile.flush()
        self.execute(self.tempfile.name)

    def execute(self, script):
        try:
            proc = subprocess.run(["python", script], capture_output=True, timeout=5)
            self.write(proc.stderr, True)
            self.write(proc.stdout)
        except subprocess.TimeoutExpired:
            self.tempfile.truncate(0)
            self.write(b"Run time exceeded 5s and was killed", True)

    def write(self, msg, error=False):
        msg = msg.decode("utf-8")
        if error:
            self.error_text = str(msg)
        else:
            self.output_text = str(msg)

    def get_first_line_text(self):
        full_text = str(self.inpipe)

        if len(full_text) > 28:
            full_text = full_text[:25] + "..."

        return f"inpipe = {full_text}"

    def get_error_text(self):
        return self.error_text

    def get_output_text(self):
        return self.output_text

    def start(self):
        with patch_stdout(self.app):
            self.app.run()

        return self.tempfile
Esempio n. 15
0
from prompt_toolkit import Application
from prompt_toolkit.buffer import Buffer
from prompt_toolkit.layout.containers import VSplit, Window
from prompt_toolkit.layout.controls import BufferControl, FormattedTextControl
from prompt_toolkit.layout.layout import Layout

buffer1 = Buffer()  # Editable buffer.

root_container = VSplit([
    # One window that holds the BufferControl with the default buffer on
    # the left.
    Window(content=BufferControl(buffer=buffer1)),

    # A vertical line in the middle. We explicitly specify the width, to
    # make sure that the layout engine will not try to divide the whole
    # width by three for all these windows. The window will simply fill its
    # content by repeating this character.
    Window(width=1, char='|'),

    # Display the text 'Hello world' on the right.
    Window(content=FormattedTextControl(text='Hello world')),
])

layout = Layout(root_container)

app = Application(layout=layout, full_screen=True)
app.run()  # You won't be able to Exit this app
Esempio n. 16
0
class VoltronUI:
    """
	Class that manages all UI elements
	"""
    def __init__(self, buffer_queue):
        self.buffer = Buffer()
        self.modules = {}
        self.module_prompt_callback = None
        self.prompt_ident = None
        self.prompt_ident_skip = []

        key_bindings = KeyBindings()

        default_text = """
Welcome to VoltronBot!
Type ? for available commands.
Control-C or type 'quit' to exit
"""
        lexer = PygmentsLexer(VoltronOutputLexer)
        ## Main output TextArea
        self.scrolling_output = TextArea(focusable=True,
                                         text=default_text,
                                         lexer=lexer)

        self.buffer_queue = buffer_queue
        self.buffer_thread = UIBufferQueue(self, self.buffer_queue,
                                           self.scrolling_output)
        self.buffer_thread.start()
        self.prompt_queue = queue.Queue()

        ## Exit keybinds
        @key_bindings.add('c-q')
        @key_bindings.add('c-c')
        def _exit(event):
            self.buffer_queue.put('SHUTDOWN')
            self.buffer_thread.join()
            event.app.exit()

        ## TextArea for prompt
        self.prompt = TextArea(
            height=1,
            #prompt=DEFAULT_PROMPT,
            multiline=False,
            wrap_lines=True)
        self.prompt.accept_handler = self.input_recv

        ## Create status bar
        self.status_text = FormattedTextControl(text=DEFAULT_STATUS)
        self.scroll_text = FormattedTextControl(text="")

        self.status_window = Window(content=self.status_text,
                                    height=1,
                                    style="class:status-bar")
        self.scroll_window = Window(content=self.scroll_text,
                                    height=1,
                                    width=6,
                                    style="class:status-bar")
        status_split = VSplit([self.status_window, self.scroll_window])

        self.prompt_text = FormattedTextControl(text=DEFAULT_PROMPT)
        self.prompt_window = Window(content=self.prompt_text,
                                    height=1,
                                    width=len(DEFAULT_PROMPT) + 1)

        ## Create top bar
        self.main_container = HSplit([
            Window(content=FormattedTextControl(text=f"VoltronBot v{VERSION}"),
                   height=1,
                   style="class:title-bar"),
            self.scrolling_output,
            status_split,
            VSplit([self.prompt_window, self.prompt]),
        ])

        style = Style([
            ('title-bar', 'bg:ansiblue #000000'),
            ('status-bar', 'bg:ansicyan #000000'),
            ('status-bar-important', 'bg:ansired #000000'),
        ])

        self.layout = Layout(self.main_container, focused_element=self.prompt)

        ## Keybind for page up
        @key_bindings.add('pageup')
        def _scroll_up(event):
            self.layout.focus(self.scrolling_output)
            scroll_one_line_up(event)
            self.layout.focus(self.prompt)

            if not self._scrolled_to_bottom:
                self.scroll_text.text = '(more)'
            else:
                self.scroll_text.text = ''

        ## Keybind for page down
        @key_bindings.add('pagedown')
        def _scroll_down(event):
            self.layout.focus(self.scrolling_output)
            scroll_one_line_down(event)
            self.layout.focus(self.prompt)

            if not self._scrolled_to_bottom:
                self.scroll_text.text = '(more)'
            else:
                self.scroll_text.text = ''

        self._app = Application(layout=self.layout,
                                full_screen=True,
                                key_bindings=key_bindings,
                                style=style)

    @property
    def _scrolled_to_bottom(self):
        ## True if the main output is scrolled to the bottom
        if self.scrolling_output.window.render_info == None:
            return True
        return (self.scrolling_output.window.vertical_scroll +
                self.scrolling_output.window.render_info.window_height
                ) >= self.scrolling_output.window.render_info.content_height

    def build_completer(self):
        completions = {'?': {}}
        for module_name in self.modules:
            actions = {}
            for action in self.modules[module_name].available_admin_commands():
                actions[action] = None
            completions[module_name] = actions
            completions['?'][module_name] = actions

        self.prompt.completer = NestedCompleter.from_nested_dict(completions)

    def register_module(self, module):
        """
		Modules are registered through the UI so we know about admin commands

		Args:
			module (instance): The instance of the module
		"""
        if module.module_name in self.modules:
            raise Exception('Duplicate module: {}'.format(module.module_name))
        self.modules[module.module_name] = module
        self.build_completer()

    def update_status_text(self, text=None):
        """
		Update the status text on the bottom bar

		Args:
			text (string): String to show on the status bar. If None it will reset to default
		"""
        if text:
            self.status_text.text = text
            self.status_window.style = 'class:status-bar-important'
            self.scroll_window.style = 'class:status-bar-important'
        else:
            self.status_text.text = DEFAULT_STATUS
            self.status_window.style = 'class:status-bar'
            self.scroll_window.style = 'class:status-bar'
        self._app.invalidate()

    def run(self):
        self._app.run()

    def reset(self):
        self.modules = {}

    def terminate_mod_prompt(self, ident):
        """
		Cancel the prompt identified by ident

		Args:
			ident (string): Indentifier for the prompt to be cancelled
		"""
        if self.prompt_ident == ident:
            self.module_prompt_callback = None
            self.mod_prompt()

    def mod_prompt(self, prompt=None, callback=None):
        """
		Change the prompt to send input to <callback>.
		This is used in modules to receive user input

		Args:
			prompt (string): The prompt to display
			callback (func): Function to call when user input is received
		"""
        ident = uuid4().hex

        if self.module_prompt_callback and not callback:
            return

        if self.module_prompt_callback and callback:
            self.prompt_queue.put((prompt, callback, ident))
            return ident

        ## Add prompts to a queue in case a module is already waiting on a prompt
        if not callback and not self.prompt_queue.empty():
            while not self.prompt_queue.empty():
                prompt, callback, ident = self.prompt_queue.get_nowait()
                if ident in self.prompt_ident_skip:
                    self.prompt_ident_skip.remove(ident)
                    prompt, callback, ident = (None, None, None)
                else:
                    break

        self.prompt_ident = ident

        if prompt:
            prompt = prompt.strip()
            self.prompt_text.text = prompt
            self.prompt_window.width = len(prompt) + 1
        else:
            self.prompt_text.text = DEFAULT_PROMPT
            self.prompt_window.width = len(DEFAULT_PROMPT) + 1
        self.module_prompt_callback = callback

        ## Must call invalidate on app to refresh UI
        self._app.invalidate()

        ## Return the unique identifier
        return self.prompt_ident

    def input_recv(self, buff):
        """
		The default function called upon user input to the prompt
		"""
        ## If there is an active module wanting input, pass the data to
        ## the appropriate function
        if self.module_prompt_callback:
            status = self.module_prompt_callback(self.prompt.text)
            if status:
                self.module_prompt_callback = None
                self.mod_prompt(None, None)
            return

        if self.prompt.text.strip().lower() == 'quit':
            self.buffer_queue.put('SHUTDOWN')
            self.buffer_thread.join()
            get_app().exit()
            return

        ## Check for help command
        match = re.search(r'^\? ?([^ ]+)?( [^ ]+)?$', self.prompt.text)
        if match:
            module_name = match.group(1)
            command_name = match.group(2)
            if command_name:
                command_name = command_name.strip()

            self.show_help(module_name, command_name)
            return

        ## Check for a valid command
        match = re.search(r'^([^ ]+) ([^ ]+) ?(.*)$', self.prompt.text)
        if match:
            module_name = match.group(1)
            trigger = match.group(2)
            params = match.group(3)

            self._execute_admin_command(module_name, trigger, params)

    def _execute_admin_command(self, module_name, trigger, params):
        ## Execute an admin command for the appropriate module
        if not module_name in self.modules:
            pass
        elif trigger not in self.modules[module_name].available_admin_commands(
        ):
            pass
        else:
            command = self.modules[module_name].admin_command(trigger)
            command.execute(params.strip())

    def show_help(self, module=None, trigger=None):
        """
		Output help text for <module>

		Args:
			module (string): Name of the module. If none display installed modules
			trigger (string): Module command. If None display valid commands for <module>
		"""
        if module and module in self.modules.keys():
            ## Check for valid module and trigger
            if trigger and trigger in self.modules[
                    module].available_admin_commands():
                help_str = 'Help for {module} {trigger}:\n'.format(
                    module=module, trigger=trigger)
                command = self.modules[module].admin_command(trigger)
                help_str += '    ' + command.description + '\n'
                help_str += '    Usage: ' + command.usage

            else:
                ## Module specified but no trigger
                help_str = ""
                if hasattr(self.modules[module], 'module_description'):
                    help_str += self.modules[module].module_description.strip()
                    help_str += '\n\n'
                help_str += f"Commands for {module} module:\n"
                count = 0
                this_line = "    "
                for trigger in self.modules[module].available_admin_commands():
                    if count == 3:
                        help_str += f"{this_line}\n"
                        count = 0
                        this_line = "    "

                    this_line += trigger.ljust(20)
                    count += 1

                help_str += "{}\n".format(this_line)

                help_str += f"Type '? {module} <command>' for more help."
            self.buffer_queue.put(("VOLTRON", '\n' + help_str + '\n'))
        else:
            ## Show available modules
            help_str = "Available Modules:\n"
            for module_name in self.modules:
                if hasattr(self.modules[module_name], 'configurable'
                           ) and not self.modules[module_name].configurable:
                    continue
                help_str += "    {module_name}\n".format(
                    module_name=module_name)
            help_str += "Type '? <module>' for more help."
            self.buffer_queue.put(('VOLTRON', '\n' + help_str + '\n'))
Esempio n. 17
0
def main():

    home = str(Path.home())
    engine = chess.engine.SimpleEngine.popen_uci(home + "/stockfish_10_x64")

    username = prompt(HTML('<violet>Enter your lichess username: </violet>'))

    client = berserk.Client()

    move_place = 0
    moves = []
    game_list = []
    game_number = 0
    analysis_archive = []

    kb = KeyBindings()
    kba = KeyBindings()

    @kb.add('c-q')
    def exit_(event):
        nonlocal move_place
        nonlocal moves
        move_place = 0
        moves = []
        game_list = []
        game_number = 0
        event.app.exit()

    @kb.add('c-a')
    def prev(event):
        nonlocal move_place
        nonlocal moves
        if move_place > 0:
            move_place = move_place - 1

        display_simple_screen(event, game_list, game_number, moves, move_place)

    @kb.add('c-d')
    def next(event):
        nonlocal move_place
        nonlocal moves
        if move_place < len(moves) - 1:
            move_place = move_place + 1

        display_simple_screen(event, game_list, game_number, moves, move_place)

    @kba.add('c-q')
    def exit_(event):
        nonlocal move_place
        nonlocal moves
        move_place = 0
        moves = []
        game_list = []
        game_number = 0
        analysis_archive = []
        event.app.exit()

    @kba.add('c-a')
    def prev(event):
        nonlocal move_place
        nonlocal moves
        if move_place > 0:
            move_place = move_place - 1

        display_analysis_screen(event, game_list, game_number, moves,
                                move_place, analysis_archive)

    @kba.add('c-d')
    def next(event):
        nonlocal move_place
        nonlocal moves
        if move_place < len(moves) - 1:
            move_place = move_place + 1

        display_analysis_screen(event, game_list, game_number, moves,
                                move_place, analysis_archive)

    try:
        game_generator = client.games.export_by_player(username,
                                                       as_pgn=False,
                                                       max=10)

        game_list = list(game_generator)

        command = prompt(
            HTML(
                '\n\u265A <cyan>Welcome to ChessView!</cyan> \u2654\nType "help" for info on commands\n>'
            ))
        while (command != 'exit'):
            if (command == 'list'):
                print_games(game_list)

            elif (command == 'help'):
                help()

            elif (command.startswith('info(')):
                print_formatted_text(game_list[int(command[5:6])])

            elif (re.match('view\(\d\)', command)):
                game_number = int(command[5:6])
                moves = game_to_fenlist(game_list[game_number]['moves'])

                chess_text = set_simple_chess_text(game_list, game_number,
                                                   moves, 0)

                root_container = VSplit([
                    Window(width=30,
                           content=FormattedTextControl(),
                           dont_extend_width=True,
                           wrap_lines=True,
                           allow_scroll_beyond_bottom=True,
                           always_hide_cursor=True),
                    Window(width=1, char='|', always_hide_cursor=True),
                    Window(content=FormattedTextControl(text=HTML(chess_text)),
                           always_hide_cursor=True)
                ])

                layout = Layout(root_container)
                app = Application(key_bindings=kb,
                                  layout=layout,
                                  full_screen=True)
                app.run()

            elif (re.match('analyze\(\d\)', command)):
                game_number = int(command[8:9])
                moves = game_to_fenlist(game_list[game_number]['moves'])
                analysis_archive = analysis_to_move_archive(
                    game_list[game_number]['moves'], engine)

                chess_text = set_analysis_chess_text(game_list, game_number,
                                                     moves, 0,
                                                     analysis_archive)

                root_container = VSplit([
                    Window(width=30,
                           content=FormattedTextControl(),
                           dont_extend_width=True,
                           wrap_lines=True,
                           allow_scroll_beyond_bottom=True,
                           always_hide_cursor=True),
                    Window(width=1, char='|', always_hide_cursor=True),
                    Window(content=FormattedTextControl(text=HTML(chess_text)),
                           always_hide_cursor=True)
                ])

                layout = Layout(root_container)
                app = Application(key_bindings=kba,
                                  layout=layout,
                                  full_screen=True)
                app.run()

            command = prompt(HTML('>'))
    except Exception as e:
        print("Username not found or does not exist.")
    engine.quit()
#!/usr/bin/env python
# vim: set fileencoding=utf-8

from prompt_toolkit import Application

# vytvoření aplikace s textovým uživatelským rozhraním
application = Application()

# spuštění aplikace
application.run()
Esempio n. 19
0
class IGCLI:
    kb = KeyBindings()
    strf_string = '%a %d %b %Y | %H:%M:%S'
    config_default = {'refresh': 5, 'currency': 'USD', 'tracked': []}

    def __init__(self) -> None:
        self.logger = logging.getLogger(self.__class__.__name__)
        self.config_file = os.getenv('IG_CLI_CONFIG', 'config.yml')
        self.config = {}
        self._id = None
        self.authd = False
        self._stop_update = Event()
        self.client = None
        self.positions_thread = None
        self.activity_thread = None
        self.orders_thread = None
        self.trackers_thread = None
        self.status_thread = RepeatTimer(self.update_status, 1)

        self.style = Style([('output-field', 'bg:#5F9EA0 #F0FFFF'),
                            ('input-field', 'bg:#20B2AA #F0FFFF'),
                            ('separator', '#000000'),
                            ('status-bar', 'bg:#D3D3D3 #2F4F4F')])

        self.trackers_field = TextArea(style='class:output-field')
        self.positions_field = TextArea(style='class:output-field')
        self.orders_field = TextArea(style='class:output-field')
        self.activity_field = TextArea(height=7, style='class:output-field')
        self.msg_field = TextArea(height=7, style='class:output-field')

        self.output_container = HSplit([
            VSplit([
                self.positions_field,
                Window(width=1, char='|', style='class:separator'),
                HSplit([
                    self.trackers_field,
                    Window(height=1, char='-', style='class:separator'),
                    self.orders_field
                ])
            ]),
            Window(height=1, char='-', style='class:separator'),
            VSplit([
                self.msg_field,
                Window(width=1, char='|', style='class:separator'),
                self.activity_field
            ])
        ])

        self.search_field = SearchToolbar()
        self.input_field = TextArea(height=1,
                                    prompt='>>> ',
                                    style='class:input-field',
                                    multiline=False,
                                    wrap_lines=False,
                                    search_field=self.search_field)

        self.input_field.accept_handler = self.parse

        self.status_field = TextArea(height=1,
                                     style='class:status-bar',
                                     multiline=False,
                                     wrap_lines=False,
                                     text=self.status)
        self.time_field = TextArea(height=1,
                                   style='class:status-bar',
                                   multiline=False,
                                   wrap_lines=False,
                                   text=self.get_time())

        self.container = HSplit([
            self.output_container,
            Window(height=1, char='-', style='class:separator'),
            self.input_field, self.search_field, self.status_field
        ])

        self.app = Application(Layout(self.container,
                                      focused_element=self.input_field),
                               style=self.style,
                               full_screen=True,
                               mouse_support=True,
                               key_bindings=self.kb)
        self.autologin()
        self.status_thread.start()

    def get_time(self):
        return datetime.utcnow().strftime(self.strf_string)

    @req_auth
    def load_config(self, filename: str = 'config.yml'):
        self.msg_out(f'Loading {self._id} configuration...')
        with open(filename) as f:
            loaded = yaml.safe_load(f)
        if loaded:
            self.config = loaded.get(self._id, {})
            if self.config:
                for key, default in self.config_default.items():
                    if key not in self.config:
                        self.config[key] = default
        else:
            self.config = self.config_default.copy()
        self.msg_out(f'... Refresh rate: {self.config["refresh"]} s\n'
                     f'... Currency: {self.config["currency"]}\n'
                     f'... Added {len(self.config["tracked"])} trackers')

    @property
    def status(self):
        s = self.get_time()
        s += ' || Status: '
        if not self.authd:
            s += 'Offline |'
        else:
            s += f'Online | ID: {self._id} '
        return s

    def update_status(self):
        self.status_field.buffer.document = Document(text=self.status)

    def autologin(self):
        api_key = os.getenv('IG_API_KEY')
        identifier = os.getenv('IG_ID')
        password = os.getenv('IG_PWD')
        if api_key and identifier and password:
            self.set_api(api_key)
            self.login(api_key, identifier, password)

    def set_api(self, api_key: str) -> None:
        self.client = IGClient(api_key=api_key)

    def login(self, identifier: str, password: str) -> bool:
        successful = self.client.login(identifier, password)
        if successful:
            self.authd = True
            self._id = identifier
            self.load_config()
            self.start_threads()
            return True
        return False

    @req_auth
    def logout(self) -> None:
        self.__api_key = None
        self._id = None
        self.__password = None
        self.config = {}
        self.stop_treads()

    @req_auth
    def start_threads(self) -> None:
        if self.positions_thread and self.trackers_thread:
            self.logger.error('Threads already running!')
            return

        # Reset stop _threads if needed
        global stop_threads
        if stop_threads is None:
            stop_threads = Event()

        self.positions_thread = RepeatTimer(self.update_positions,
                                            self.config['refresh'])
        self.activity_thread = RepeatTimer(self.update_activity,
                                           self.config['refresh'])
        self.orders_thread = RepeatTimer(self.update_orders,
                                         self.config['refresh'])
        self.trackers_thread = RepeatTimer(self.update_trackers,
                                           self.config['refresh'])

        self.positions_thread.start()
        self.activity_thread.start()
        self.orders_thread.start()
        self.trackers_thread.start()

    @req_auth
    def stop_threads(self) -> None:
        global stop_threads
        stop_threads.set()
        self.positions_thread = None
        self.activity_thread = None
        self.orders_thread = None
        self.trackers_thread = None
        stop_threads = None

    @req_auth
    def restart_threads(self) -> None:
        self.stop_threads()
        self.start_threads()

    @req_auth
    def write_config(self) -> None:
        with open(self.config_file, 'r') as f:
            loaded = yaml.safe_load(f)
        if not loaded:
            loaded = {}
        loaded[self._id] = self.config
        with open(self.config_file, 'w') as f:
            yaml.dump(loaded, f)

    @req_auth
    def add_tracker(self, tracker: str) -> None:
        try:
            self.client.get_market(tracker)
            self.config['tracked'].append(tracker)
        except NotFoundError:
            self.msg_out(f'Unable to find market: {tracker}')

    @req_auth
    def del_tracker(self, tracker: str) -> None:
        if tracker in self.config['tracked']:
            self.config['tracked'].remove(tracker)

    def parse(self, buf: Document) -> None:
        self.logger.debug(f'Input: {buf.text}')
        args = buf.text.split()

        # replace aliases
        a_args = []
        for arg in args:
            if arg in self.config['alias']:
                a_args = a_args + self.config['alias'][arg].split(' ')
            else:
                a_args.append(arg)
        args = a_args

        # try find command
        try:
            command = getattr(self, f'_cmd__{args[0]}')
        except AttributeError:
            self.msg_out(f'Unrecognised command: {args[0]}')
            return

        # run command
        command(*args[1:])

    def msg_out(self, text: str) -> None:
        new_text = self.msg_field.text + f'\n{text}'
        self.msg_field.buffer.document = \
            Document(text=new_text, cursor_position=len(new_text))

    # cant figure out how to colour text for the Document
    @req_auth
    def update_positions(self) -> None:
        self.logger.debug('Updating positions...')
        positions = self.client.get_positions_profitloss()
        buf = f"{' POSITIONS ':-^60}\n"
        for i, pos in enumerate(positions):
            line = '{direction:4} {name:15} {size:>5.2f} ' +\
                   '{currency:3} @ {level:>10.2f} ' +\
                   '|| {profitloss:>10}'
            line = line.format(direction=pos['position']['direction'],
                               name=pos['market']['instrumentName'],
                               size=pos['position']['size'],
                               currency=pos['position']['currency'],
                               level=pos['position']['level'],
                               profitloss=pos['profitloss'])
            buf += line
            if i + 1 != len(positions):  #not last
                buf += '\n'
        self.positions_field.buffer.document = Document(text=buf)

    @req_auth
    def update_activity(self) -> None:
        self.logger.debug('Updating activity...')
        activities = self.client.get_activity()['activities']
        buf = ''
        for i, activity in enumerate(activities):
            line = '{date} {activity:15} {name:10} {size:>5} ' +\
                   '{currency:3} @ {level:>10} ' +\
                   '|| {status:>10}'
            line = line.format(date=activity['date'],
                               activity=activity['activity'],
                               name=activity['marketName'],
                               size=activity['size'],
                               currency=activity['currency'],
                               level=activity['level'],
                               status=activity['actionStatus'])
            buf += line
            if i + 1 != len(activities):  #not last
                buf += '\n'
        self.activity_field.buffer.document = Document(text=buf)

    @req_auth
    def update_orders(self) -> None:
        self.logger.debug('Updating orders...')
        orders = self.client.get_working_orders()['workingOrders']
        buf = f"{' ORDERS ':-^60}\n"
        for i, order in enumerate(orders):
            line = '{direction:4} {name:15} {size:>5.2f} ' +\
                   '{currency:3} @ {level:>10.2f} '
            line = line.format(
                direction=order['workingOrderData']['direction'],
                name=order['marketData']['instrumentName'],
                size=order['workingOrderData']['orderSize'],
                currency=order['workingOrderData']['currencyCode'],
                level=order['workingOrderData']['orderLevel'])
            buf += line
            if i + 1 != len(orders):  #not last
                buf += '\n'
        self.orders_field.buffer.document = Document(text=buf)

    @req_auth
    def update_trackers(self) -> None:
        self.logger.debug('Updating trackers...')
        markets = self.client.get_markets(
            *self.config['tracked'])['marketDetails']
        buf = f"{' TRACKERS ':-^60}\n"
        for i, market in enumerate(markets):
            line = '{name:15} || {low:>9} | {high:>9} || {bid:>9} | {offer:>9}'
            line = line.format(name=market['instrument']['name'],
                               low=market['snapshot']['low'] or '-',
                               high=market['snapshot']['high'] or '-',
                               bid=market['snapshot']['bid'] or '-',
                               offer=market['snapshot']['offer'] or '-')
            buf += line
            if i + 1 != len(self.config['tracked']):
                buf += '\n'
        self.trackers_field.buffer.document = Document(text=buf)

    # This does some super weird shit. The decorator calls this
    # without passing self. I'm too dumb to figure out where/how this
    # happens to monkey-patch (I think a flag on self would be better)
    # Thus, the global stop_threads.

    @kb.add('c-q')
    @kb.add('c-c')
    def exit_ctrl_q(event) -> None:
        global stop_threads
        stop_threads.set()
        event.app.exit()

    def __call__(self) -> None:
        self.logger.info('Starting CLI...')
        self.app.run()

    def __del__(self) -> None:
        self.stop_threads()

    # User Commands
    # all user commands should start with '_cmd__', and accept *args
    @req_auth
    def _cmd__update(self, *args: List[str]) -> None:
        self.update_positions()
        self.update_orders()
        self.update_trackers()
        self.msg_out('Updated positions, orders and trackers')

    def _cmd__api(self, *args: List[str]) -> None:
        if len(args) != 1:
            self.msg_out('Invalid syntax, expected: api <key>')
            return
        self.set_api(args[0])
        self.msg_out('Updated API key')

    def _cmd__login(self, *args: List[str]):
        if len(args) != 2:
            self.msg_out('Invalid syntax, expected: login: '******'<username> <password>')
            return
        username, password = args
        successful = self.login(username, password)
        if successful:
            self.msg_out('Login successful')
        else:
            self.msg_out('Login failed')

    def _cmd__save(self, *args: List[str]) -> None:
        self.write_config()
        self.msg_out('Configuration saved')

    def _cmd__track(self, *args: List[str]) -> None:
        for arg in args:
            self.add_tracker(arg)
        self.msg_out('Added tracked market(s)')

    def _cmd__stoptrack(self, *args: List[str]) -> None:
        for arg in args:
            self.del_tracker(arg)
        self.msg_out('Removed tracked market(s)')

    def _cmd__search(self, *args: List[str]) -> None:
        markets = self.client.search_market(args[0])['markets']
        s = 'Found epics: '
        s += ', '.join([
            f'{market["instrumentName"]}: {market["epic"]}'
            for market in markets
        ])
        self.msg_out(s)

    def _cmd__buy(self, *args: List[str]) -> None:
        size, epic = args
        currency = self.config['currency']
        try:
            self.client.get_market(epic)
        except BadRequestError:
            self.msg_out(f'Unable to find market: {epic}')
            return
        self.client.add_position('BUY', 'MARKET', epic, size, currency)
        self.msg_out(f'Submitted position on {epic} @ {size} {currency}')

    def _cmd__alias(self, *args: List[str]) -> None:
        self.config['alias'][args[0]] = ' '.join(args[1:])
        self.msg_out(f'Added alias: {args[0]} = {" ".join(args[1:])}')
Esempio n. 20
0
def run():
    app = Application(full_screen=True, mouse_support=True, key_bindings=kb, layout=main_layout)
    app.run()
                            content=controls.BufferControl(buffer=buffer), height=1
                        ),
                        containers.Window(height=1, char="-", style="class:line"),
                        containers.Window(content=display),
                    ]
                ),
                floats=[
                    containers.Float(
                        xcursor=True,
                        ycursor=True,
                        content=menus.CompletionsMenu(max_height=12, scroll_offset=1),
                    )
                ],
            ),
        ]
    )
)


kb = KeyBindings()


@kb.add("c-g")
@kb.add("c-c")
def exit_(event):
    event.app.exit()


app = Application(layout=layout, full_screen=True, key_bindings=kb)
app.run()
Esempio n. 22
0
def start_app(store: RetroStore, connection_string: str = ''):
    kb = KeyBindings()

    @kb.add('c-q')
    def exit_(event):
        event.app.exit()

    @kb.add('c-r')
    def refresh_(event):
        refresh()

    def refresh():
        items = store.list()

        texts = {
            Category.GOOD: StringIO(),
            Category.NEUTRAL: StringIO(),
            Category.BAD: StringIO(),
        }
        for item in items:
            texts[item.category].write(f'{item.key}. {item.text}\n')

        good_buffer.text = texts[Category.GOOD].getvalue()
        neutral_buffer.text = texts[Category.NEUTRAL].getvalue()
        bad_buffer.text = texts[Category.BAD].getvalue()

    @kb.add('c-m')
    def enter_(event):
        text = input_buffer.text

        if text.startswith('+'):
            input_buffer.reset()
            store.add_item(text[1:].strip(), Category.GOOD)
        elif text.startswith('.'):
            input_buffer.reset()
            store.add_item(text[1:].strip(), Category.NEUTRAL)
        elif text.startswith('-'):
            input_buffer.reset()
            store.add_item(text[1:].strip(), Category.BAD)

        elif text.startswith('mv '):
            cmd, key, column = text.split()

            categories = {
                '+': Category.GOOD,
                '.': Category.NEUTRAL,
                '-': Category.BAD,
            }

            input_buffer.reset()
            store.move_item(int(key), categories[column])

        elif text.startswith('rm '):
            cmd, key = text.split()

            input_buffer.reset()
            store.remove(int(key))

        refresh()

    @kb.add('c-p')
    def ping_(event):
        start = time()
        store.list(Category.GOOD)
        app.print_text(f'latency: {time() - start:.3f}')

    good_buffer = Buffer()
    neutral_buffer = Buffer()
    bad_buffer = Buffer()

    input_buffer = Buffer()
    input = Window(content=BufferControl(buffer=input_buffer), height=1)

    root_container = HSplit([
        VSplit([
            HSplit([
                Window(content=FormattedTextControl(text=':)'),
                       height=1,
                       align=WindowAlign.CENTER),
                Window(height=1, char='-'),
                Window(content=BufferControl(buffer=good_buffer)),
            ],
                   style="fg:white bold bg:ansigreen"),
            Window(width=2, char='|'),
            HSplit([
                Window(content=FormattedTextControl(text=':|'),
                       height=1,
                       align=WindowAlign.CENTER),
                Window(height=1, char='-'),
                Window(content=BufferControl(buffer=neutral_buffer)),
            ],
                   style="fg:white bold bg:ansiyellow"),
            Window(width=2, char='|'),
            HSplit([
                Window(content=FormattedTextControl(text=':('),
                       height=1,
                       align=WindowAlign.CENTER),
                Window(height=1, char='-'),
                Window(content=BufferControl(buffer=bad_buffer)),
            ],
                   style="fg:white bold bg:ansired"),
        ]),
        Window(
            content=FormattedTextControl(text=f'Invite: {connection_string}'),
            height=1,
            align=WindowAlign.CENTER), input
    ],
                            style='bg:grey')

    layout = Layout(root_container)
    layout.focus(input)

    app = Application(layout=layout, key_bindings=kb, full_screen=True)

    async def active_refresh():
        while True:
            refresh()
            await asyncio.sleep(2)

    app.create_background_task(active_refresh())

    app.run()
Esempio n. 23
0
class OOApplication:
    @staticmethod
    def source(self, event):
        """
        Show and modify source of the object under cursor.
        """

        source_is_already_open = False
        for tab in self.session.tabs:
            if tab.name == 'Source':
                source_is_already_open = True

        if not source_is_already_open:
            cursor_row_index = self.python_code_buffer.document.cursor_position_row
            cursor_col_index = self.python_code_buffer.document.cursor_position_col
            current_row = self.python_code_buffer.document.lines[
                cursor_row_index]
            text_before_cursor = current_row[:cursor_col_index]

            self.inspected_class_object, self.inspected_method_object, source_code = inspect_code(
                text_before_cursor, self.interface)

            self.source_code_original = source_code
            self.source_code_buffer = Buffer()
            self.source_code_buffer.document = Document(text=source_code)

            formatted_text = BufferControl(buffer=self.source_code_buffer,
                                           lexer=PythonLexer(
                                               self.source_code_buffer))

            source_window = Window(formatted_text, width=120, wrap_lines=True)

            tab_index = self.session.add_tab(Tab("Source", source_window))
            self.tabs_container.set_selected_tab(tab_index)

        # Source float is already exist, so saving the modified version of the source and closing the float.
        else:
            # Source code modifications only works on method right now.
            # so it only works if source code inspector return both class ans method object.
            if self.inspected_class_object and \
               self.inspected_method_object and \
               self.source_code_original != self.source_code_buffer.document.text: # Only modify the method object if the code has actually changed
                try:
                    # Should be method definition
                    source = self.source_code_buffer.document.text

                    # Evaluting the method object (with the original name)
                    exec(source, self.interface)

                    method_name = self.inspected_method_object.__name__

                    # The moment we evaluated the new method in the exec above,
                    # we can get a pointer to that method using its name in the local context(scope)
                    new_method_object = eval(method_name, self.interface)

                    setattr(
                        self.inspected_class_object, method_name,
                        new_method_object.__get__(
                            self.inspected_class_object,
                            type(self.inspected_class_object)))

                    # setattr(class_object, method_name, eval(method_name))
                except Exception as e:
                    self.__send_to_output("Exception: {}".format(e))

            self.session.remove_tab_by_name("Source")
            self.tabs_container.update_selected_tab()

    @staticmethod
    def execute(self, event):
        """
        Execute the code in the python code buffer in the current interpreter session.
        """
        code = self.python_code_buffer.document.text
        output = None
        try:
            import sys
            from io import StringIO

            codeOut = StringIO()
            codeErr = StringIO()

            sys.stdout = codeOut
            sys.stderr = codeErr

            exec(code, self.interface)

            # restore stdout and stderr
            sys.stdout = sys.__stdout__
            sys.stderr = sys.__stderr__

            # codeErr.getvalue()
            output = codeOut.getvalue()

            codeOut.close()
            codeErr.close()

        except Exception as e:
            output = e

        self.__send_to_output("------- start of python output -------")
        self.__send_to_output(output)
        self.__send_to_output("-------- end of python output --------")

    @staticmethod
    def exit(self, event):
        """
        Pressing Ctrl-Q will exit the user interface.

        Setting a return value means: quit the event loop that drives the user
        interface and return this value from the `Application.run()` call.
        """
        event.app.exit()

    @staticmethod
    def focus_next(self, event):
        selected_window = self.tabs_container.focus_next()

        self.app.layout.focus(selected_window)

    @staticmethod
    def return_to_command_line(self, event):
        self.app.layout.focus(self.input_container)

    def __configure_bindings(self):
        # Configure key bindings for app
        self.key_bindings = KeyBindings()

        # Bind  Ctrl-c to return to command
        @self.key_bindings.add('c-c')
        def return_to_command_line_(event):
            OOApplication.return_to_command_line(self, event)

        # Bind Alt-Tab to change focus to next window
        @self.key_bindings.add('escape', 'c-i')
        def focus_next_(event):
            OOApplication.focus_next(self, event)

        # Bind Ctrl-s to view the source of a method
        @self.key_bindings.add('c-s')
        def source_(event):
            OOApplication.source(self, event)

        # Bind Ctrl-e for executing the python code.
        @self.key_bindings.add('c-e')
        def execute_(event):
            OOApplication.execute(self, event)

        # Bind Ctrl-q for existing the application.
        @self.key_bindings.add('c-q')
        def exit_(event):
            OOApplication.exit(self, event)

    def __configure_snippets(self):
        snippets = Snippets()

        # Add default snippets
        # snippets["modify_object_method"] = modify_object_method
        setattr(snippets, "modify_object_method", modify_object_method)

        if self.snippets_path == None:
            self.add_object_to_interface("snippets", snippets)
            return

        # Add user-defined snippets
        path.append(self.snippets_path)  # So the import will work...

        files = [
            join(self.snippets_path, file_name)
            for file_name in listdir(self.snippets_path)
            if isfile(join(self.snippets_path, file_name))
        ]
        files = [
            file_name for file_name in listdir(self.snippets_path)
            if isfile(join(self.snippets_path, file_name))
            and file_name.endswith('.py')
        ]

        for f in files:
            try:
                module_name = splitext(f)[0]
                module = importlib.import_module(module_name)
                setattr(snippets, module_name, module)

                self.__send_to_output("[-] {} - loaded.".format(f))
            except Exception as e:
                self.__send_to_output("[!] {} - Falied to load: {}".format(
                    f, e))

        self.add_object_to_interface("snippets", snippets)

    def __configure_layout(self):
        # Configure completers used by the application.
        commands_completer = NestedCommandsFuzzyWordCompleter(
            self.commands, completers=self.completers)

        # Configure PythonRuntimeCompleter
        python_runtime_completer = PythonRuntimeCompleter(self)

        # --------- This is the CLI input container ---------
        # Comfigure the input container and handler.
        self.input_container = TextArea(prompt='{}> '.format(self.app_name),
                                        style='class:input-field',
                                        multiline=False,
                                        wrap_lines=True,
                                        completer=commands_completer,
                                        history=InMemoryHistory())
        self.input_container.accept_handler = lambda command: self.__root_command_handler(
            self.input_container.text)

        # Configure the python buffer to write interactive pytho code.
        self.python_code_buffer = Buffer(completer=python_runtime_completer)

        # --------- This is the Python code container ---------
        self.python_code_container = Window(
            width=130,  # Is there any way to use precentage?
            content=BufferControl(buffer=self.python_code_buffer,
                                  lexer=PythonLexer(self.python_code_buffer)),
            get_line_prefix=self.__get_line_prefix,
            wrap_lines=True)

        # Configure the output buffer to 'print' out results.
        self.output_buffer = Buffer()

        # --------- This is the Output container ---------
        self.output_container = Window(
            content=BufferControl(buffer=self.output_buffer), wrap_lines=True)

        self.session = Session()
        self.session.add_tab(Tab("Console", self.output_container))
        self.session.add_tab(
            Tab("Python Interpreter Environment", self.python_code_container))

        self.tabs_container = TabbedBuffersContainer(self.session)
        self.tabs_container.set_selected_tab(0)

        # Configure the application layout.
        root_container = HSplit([
            VSplit([
                # Window for python code.
                self.tabs_container,
            ]),
            # Seperation line.
            Window(height=1, char='-', style='class:line'),
            # Command line prompt.
            self.input_container,
        ])

        self.floating_container = FloatContainer(
            content=root_container,
            floats=[
                Float(xcursor=True,
                      ycursor=True,
                      content=CompletionsMenu(max_height=16, scroll_offset=1))
            ])

        self.body_layout = Layout(self.floating_container)

    def __init__(self, app_name, commands, completers={}, snippets_path=None):
        # Configure the application name.
        self.app_name = app_name

        # Initialize the interface of this app.
        self.interface = {}

        self.snippets_path = snippets_path
        self.completers = completers
        self.commands = commands

        self.__configure_bindings()

        self.__configure_layout()

        self.__configure_snippets()

        # Creating the application.
        self.app = Application(layout=self.body_layout,
                               key_bindings=self.key_bindings,
                               full_screen=True,
                               editing_mode=EditingMode.VI)

        # Focus on command line
        self.app.layout.focus(self.input_container)

        self.add_object_to_interface("ooa", self)

    def __get_line_prefix(self, line_number, wrap_count):
        return ''

    def __send_to_output(self, message):
        new_text = self.output_buffer.text + "{}\n".format(message)
        self.output_buffer.document = Document(text=new_text,
                                               cursor_position=len(new_text))

    def __root_command_handler(self, command):
        commands = command.split()

        if len(commands) == 0: return

        try:
            curr_state = self.commands

            for c in commands:
                if not isinstance(curr_state, types.FunctionType):
                    curr_state = curr_state[c]

            output = curr_state(self, commands)

            self.__send_to_output(output)
        except:
            pass

    def remove_object_from_interface(self, object_name):
        if object_name in self.interface:
            del self.interface[object_name]

    def add_object_to_interface(self, object_name, object_instance):
        self.interface[object_name] = object_instance

    def run(self):
        self.app.run()  # You won't be able to Exit this app
Esempio n. 24
0
class PybreakGui(Bdb):
    def __init__(self):
        super().__init__()
        self.paused = True
        self.app_thread = threading.Thread(target=self.start_gui, args=(asyncio.get_event_loop(),))
        self.frame_history = FrameHistory()

        self.search_toolbar = SearchToolbar(
            text_if_not_searching=[("class:not-searching", "Press '/' to start searching.")]
        )

        def get_view_file():
            if len(self.frame_history.history) > 0:
                return self.frame_history.hist_frame.filename
            return ".py"

        self.text_area = TextArea(
            lexer=DynamicLexer(
                lambda: PygmentsLexer.from_filename(
                    get_view_file(), sync_from_start=False
                )
            ),
            search_field=self.search_toolbar,
            scrollbar=True,
            line_numbers=True,
        )
        self.container = HSplit(
            [
                self.text_area,
                self.search_toolbar,
            ]
        )

        kb = KeyBindings()

        @kb.add("c-q")
        def _(event: KeyPressEvent):
            self.paused = False
            self._quit()

        @kb.add("c-n")
        def _(event):
            self.set_next(self.frame_history.exec_frame.raw_frame)
            self.paused = False  # allow another frame to be processed

        self.app = Application(
            full_screen=True,
            layout=Layout(container=self.container),
            key_bindings=kb,
        )
        self.app.loop = asyncio.get_event_loop()

    def start_gui(self, loop):
        asyncio.set_event_loop(loop)
        self.app.run()
        self.text_area.buffer.insert_text("HELLO WORLD")

    def start(self, frame):
        self.app_thread.start()
        super().set_trace(frame)

    def _quit(self):
        sys.settrace(None)
        self.quitting = True
        self.app.exit()

    def user_call(self, frame: types.FrameType, argument_list):
        # if self.stop_here(frame):
        # self.frame_history.append(frame)
        pass

    def user_line(self, frame: types.FrameType):
        """
        This method is called from dispatch_line() when either
        stop_here() or break_here() yields True.
        i.e. when we stop OR break at this line.
         * stop_here() yields true if the frame lies below the frame where
         debugging started on the call stack. i.e. it will be called for
         every line after we start debugging.
         * break_here() yields true only if there's a breakpoint for this
         line
        """
        self.text_area.buffer.insert_text(f"FRAME = {frame.f_code.co_filename}:{frame.f_lineno}")
        if self.stop_here(frame):
            self.text_area.buffer.insert_text(str(frame.f_code.co_filename) + str(frame.f_lineno) + "\n")
            self.frame_history.append(frame)

            while self.paused:
                time.sleep(.1)
            self.paused = True
Esempio n. 25
0
        now.strftime("DATE_NOW:%m/%d/%Y,%H:%M:%S"))


@kb.add('c-c', 'q', 'u', 'i', 't')
def exit_(event):
    event.app.exit()


buffer1 = Buffer()
buffer2 = Buffer()
root_container = VSplit(
    [
        # One window that holds the BufferControl with the default buffer on
        # the left.
        Window(content=BufferControl(buffer=buffer1)),

        # A vertical line in the middle. We explicitly specify the width, to
        # make sure that the layout engine will not try to divide the whole
        # width by three for all these windows. The window will simply fill its
        # content by repeating this character.
        Window(width=1, char='|'),

        # Display the text 'Hello world' on the right.
        Window(content=BufferControl(buffer=buffer2)),
    ], )

layout = Layout(root_container, )

app = Application(key_bindings=kb, full_screen=True, layout=layout)
app.run()
Esempio n. 26
0
def cli(ctx, email, password, token, graphql, **kwargs):
    '''Music player'''
    ctx.obj.u = lambda: user.User.new(email=email, password=password, token=token, graphql=graphql)
    mf = mfilter.Filter(**kwargs)
    p = ctx.obj.u().do_filter(mf)
    if not p:
        logger.warning('Empty playlist')
        return
    instance = vlc.Instance()
    songs = [song['path'] for song in p]
    player = instance.media_list_player_new()
    media_list = instance.media_list_new(songs)
    player.set_media_list(media_list)
    bindings = KeyBindings()

    @bindings.add('p')
    def _play_binding(event):
        def play():
            """Play song"""
            player.play()
        run_in_terminal(play)

    @bindings.add('q')
    def _quit_binding(event):
        player.pause()
        event.app.exit()

    @bindings.add('s')
    def _pause_binding(event):
        player.pause()

    @bindings.add('l')
    def _playlist_binding(event):
        def playlist():
            """List songs"""
            for s in songs:
                print(s)
        run_in_terminal(playlist)

    @bindings.add('right')
    def _next_binding(event):
        player.next()

    @bindings.add('left')
    def _previous_binding(event):
        player.previous()

    def bottom_toolbar():
        media_player = player.get_media_player()
        media = media_player.get_media()
        media.parse()
        media_time = seconds_to_human(round(media_player.get_time() / 1000))
        media_length = seconds_to_human(round(media_player.get_length() / 1000))
        artist = media.get_meta(vlc.Meta.Artist)
        album = media.get_meta(vlc.Meta.Album)
        title = media.get_meta(vlc.Meta.Title)
        current = '({} / {}) {} - {} - {}'.format(media_time, media_length, artist, album, title)
        get_app().invalidate()
        return HTML('Current song: {}'.format(current))

    player.play()
    print(HTML('Bindings: q = quit | p = play | s = pause/continue | right = next song | left = previous song | l = playlist'))

    root_container = HSplit(
        [Window(FormattedTextControl(lambda: bottom_toolbar, style='class:bottom-toolbar.text'), style='class:bottom-toolbar')]
    )
    layout = Layout(root_container)
    app = Application(layout=layout, key_bindings=bindings)
    app.run()