예제 #1
0
def python_sidebar(python_input):
    """
    Create the `Layout` for the sidebar with the configurable options.
    """
    def get_tokens(cli):
        tokens = []
        T = Token.Sidebar

        def append_category(category):
            tokens.extend([
                (T, '  '),
                (T.Title, '   %-36s' % category.title),
                (T, '\n'),
            ])

        def append(index, label, status):
            selected = index == python_input.selected_option_index

            @if_mousedown
            def select_item(cli, mouse_event):
                python_input.selected_option_index = index

            @if_mousedown
            def goto_next(cli, mouse_event):
                " Select item and go to next value. "
                python_input.selected_option_index = index
                option = python_input.selected_option
                option.activate_next()

            token = T.Selected if selected else T

            tokens.append((T, ' >' if selected else '  '))
            tokens.append((token.Label, '%-24s' % label, select_item))
            tokens.append((token.Status, ' ', select_item))
            tokens.append((token.Status, '%s' % status, goto_next))

            if selected:
                tokens.append((Token.SetCursorPosition, ''))

            tokens.append((token.Status, ' ' * (13 - len(status)), goto_next))
            tokens.append((T, '<' if selected else ''))
            tokens.append((T, '\n'))

        i = 0
        for category in python_input.options:
            append_category(category)

            for option in category.options:
                append(i, option.title, '%s' % option.get_current_value())
                i += 1

        tokens.pop()  # Remove last newline.

        return tokens

    class Control(TokenListControl):
        def move_cursor_down(self, cli):
            python_input.selected_option_index += 1

        def move_cursor_up(self, cli):
            python_input.selected_option_index -= 1

    return ConditionalContainer(content=Window(
        Control(get_tokens,
                Char(token=Token.Sidebar),
                has_focus=ShowSidebar(python_input) & ~IsDone()),
        width=LayoutDimension.exact(43),
        height=LayoutDimension(min=3),
        scroll_offsets=ScrollOffsets(top=1, bottom=1)),
                                filter=ShowSidebar(python_input) & ~IsDone())
예제 #2
0
    def __init__(
            self,
            options,
            default_index=0,
            header_filter=lambda x: x,
            match_filter=lambda x: x,
            custom_filter=None,
            search_buffer=Buffer(multiline=False),
            cpu_count=multiprocessing.cpu_count()
            ):

        assert(isinstance(options, list))
        assert(callable(header_filter))
        assert(callable(match_filter))
        assert(isinstance(default_index, int))

        self.search_buffer = search_buffer
        self.last_query_text = ''
        self.search_buffer.on_text_changed += self.update

        self.header_filter = header_filter
        self.match_filter = match_filter
        self.current_index = default_index
        self.entries_left_offset = 0
        self.pool = multiprocessing.Pool(cpu_count)

        self.options_headers_linecount = []
        self._indices_to_lines = []

        self._options = []
        self.marks = []
        self.max_entry_height = 1
        # Options are processed here also through the setter
        self.options = options
        self.cursor = Point(0, 0)

        self.content = FormattedTextControl(
            text=self.get_tokens,
            focusable=False,
            key_bindings=None,
            get_cursor_position=lambda: self.cursor,
        )
        self.content_window = Window(
            content=self.content,
            wrap_lines=False,
            allow_scroll_beyond_bottom=True,
            scroll_offsets=ScrollOffsets(bottom=self.max_entry_height),
            cursorline=False,
            cursorcolumn=False,
            # right_margins=[NumberedMargin()],
            # left_margins=[NumberedMargin()],
            align=WindowAlign.LEFT,
            height=None,
            get_line_prefix=self.get_line_prefix
            # get_line_prefix=lambda line, b: [('bg:red', '  ')]
        )

        self.update()

        super(OptionsList, self).__init__(
            content=self.content_window,
            filter=(
                custom_filter
                if custom_filter is not None
                else has_focus(self.search_buffer)
            )
        )
예제 #3
0
    def __init__(self, my_app: "sqlApp") -> None:

        self.my_app = my_app
        self.search_field = SearchToolbar()
        history_file = config_location() + 'history'
        ensure_dir_exists(history_file)
        hist = ThreadedHistory(FileHistory(expanduser(history_file)))
        self.input_buffer = Buffer(
            name="defaultbuffer",
            tempfile_suffix=".py",
            multiline=MultilineFilter(self.my_app),
            history=hist,
            completer=DynamicCompleter(
                lambda: ThreadedCompleter(self.my_app.completer)),
            #                    lambda: self.my_app.completer),
            auto_suggest=ThreadedAutoSuggest(AutoSuggestFromHistory()),
            complete_while_typing=Condition(
                lambda: self.my_app.active_conn is not None))
        main_win_control = BufferControl(
            buffer=self.input_buffer,
            lexer=PygmentsLexer(SqlLexer),
            search_buffer_control=self.search_field.control,
            include_default_input_processors=False,
            input_processors=[AppendAutoSuggestion()],
            preview_search=True)

        self.main_win = Window(
            main_win_control,
            height=(
                lambda:
                (None if get_app().is_done else
                 (Dimension(min=self.my_app.min_num_menu_lines)
                  if not self.my_app.show_preview else Dimension(
                      min=self.my_app.min_num_menu_lines, preferred=180)))),
            get_line_prefix=partial(sql_line_prefix, my_app=self.my_app),
            scroll_offsets=ScrollOffsets(bottom=1, left=4, right=4))

        self.lprompt = login_prompt(self.my_app)
        self.preview = preview_element(self.my_app)
        self.disconnect_dialog = disconnect_dialog(self.my_app)
        container = HSplit([
            VSplit([
                FloatContainer(
                    content=HSplit([
                        self.main_win,
                        self.search_field,
                    ]),
                    floats=[
                        Float(
                            bottom=1,
                            left=1,
                            right=0,
                            content=sql_sidebar_help(self.my_app),
                        ),
                        Float(content=self.lprompt),
                        Float(content=self.preview, ),
                        Float(content=self.disconnect_dialog, ),
                        Float(left=2,
                              bottom=1,
                              content=exit_confirmation(self.my_app)),
                        Float(xcursor=True,
                              ycursor=True,
                              transparent=True,
                              content=CompletionsMenu(scroll_offset=1,
                                                      max_height=16,
                                                      extra_filter=has_focus(
                                                          self.input_buffer)))
                    ]),
                ConditionalContainer(
                    content=sql_sidebar(self.my_app),
                    filter=ShowSidebar(self.my_app) & ~is_done,
                )
            ]),
            VSplit([
                status_bar(self.my_app),
                show_sidebar_button_info(self.my_app)
            ])
        ])

        def accept(buff):
            app = get_app()
            app.exit(result=["non-preview", buff.text])
            app.pre_run_callables.append(buff.reset)
            return True

        self.input_buffer.accept_handler = accept
        self.layout = Layout(container, focused_element=self.main_win)
예제 #4
0
파일: sidebar.py 프로젝트: detule/odbc-cli
def sql_sidebar(my_app: "sqlApp") -> Window:
    """
    Create the `Layout` for the sidebar with the configurable objects.
    """
    @if_mousedown
    def expand_item(obj: "myDBObject") -> None:
        obj.expand()

    def tokenize_obj(obj: "myDBObject") -> StyleAndTextTuples:
        " Recursively build the token list "
        tokens: StyleAndTextTuples = []
        selected = obj is my_app.selected_object
        expanded = obj.children is not None
        connected = obj.otype == "Connection" and obj.conn.connected()
        active = my_app.active_conn is not None and my_app.active_conn is obj.conn and obj.level == 0

        act = ",active" if active else ""
        sel = ",selected" if selected else ""
        if len(obj.name) > 24 - 2 * obj.level:
            name_trim = obj.name[:24 - 2 * obj.level - 3] + "..."
        else:
            name_trim = ("%-" + str(24 - 2 * obj.level) + "s") % obj.name

        tokens.append(
            ("class:sidebar.label" + sel + act, " >" if connected else "  "))
        tokens.append(
            ("class:sidebar.label" + sel, " " * 2 * obj.level, expand_item))
        tokens.append(
            ("class:sidebar.label" + sel + act, name_trim, expand_item))
        tokens.append(("class:sidebar.status" + sel + act, " ", expand_item))
        tokens.append(("class:sidebar.status" + sel + act, "%+12s" % obj.otype,
                       expand_item))

        if selected:
            tokens.append(("[SetCursorPosition]", ""))

        if expanded:
            tokens.append(("class:sidebar.status" + sel + act, "\/"))
        else:
            tokens.append(("class:sidebar.status" + sel + act,
                           " <" if selected else "  "))

        # Expand past the edge of the visible buffer to get an even panel
        tokens.append(("class:sidebar.status" + sel + act, " " * 10))
        return tokens

    def _buffer_pos_changed(buff):
        """ When the cursor changes in the sidebar buffer, make sure the appropriate
            database object is market as selected
        """
        # Only when this buffer has the focus.
        try:
            line_no = buff.document.cursor_position_row

            if line_no < 0:  # When the cursor is above the inserted region.
                raise IndexError

            idx = 0
            obj = my_app.obj_list[0]
            while idx < line_no:
                if not obj.next_object:
                    raise IndexError
                idx += 1
                obj = obj.next_object

            my_app.selected_object = obj

        except IndexError:
            pass

    search_buffer = Buffer(name="sidebarsearchbuffer")
    search_field = SearchToolbar(search_buffer=search_buffer, ignore_case=True)
    sidebar_buffer = Buffer(name="sidebarbuffer",
                            read_only=True,
                            on_cursor_position_changed=_buffer_pos_changed)

    class myLexer(Lexer):
        def __init__(self, token_list=None, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.token_list = token_list

        def lex_document(
                self,
                document: Document) -> Callable[[int], StyleAndTextTuples]:
            def get_line(lineno: int) -> StyleAndTextTuples:
                # TODO: raise out-of-range exception
                return self.token_list[lineno]

            return get_line

        def reset_tokens(self, tokens: [StyleAndTextTuples]):
            self.token_list = tokens

    sidebar_lexer = myLexer()

    class myControl(BufferControl):
        def move_cursor_down(self):
            my_app.select_next()

        # Need to figure out what do do here
        # AFAICT thse are only called for the mouse handler
        # when events are otherwise not handled
        def move_cursor_up(self):
            my_app.select_previous()

        def mouse_handler(self,
                          mouse_event: MouseEvent) -> "NotImplementedOrNone":
            """
                There is an intricate relationship between the cursor position
                in the sidebar document and which object is market as 'selected'
                in the linked list.  Let's not muck that up by allowing the user
                to change the cursor position in the sidebar document with the mouse.
            """
            return NotImplemented

        def create_content(self, width: int,
                           height: Optional[int]) -> UIContent:
            res = []
            res_tokens = []
            count = 0
            obj = my_app.obj_list[0]
            res.append(obj.name)
            res_tokens.append(tokenize_obj(obj))
            found_selected = obj is my_app.selected_object
            idx = 0
            while obj.next_object is not my_app.obj_list[0]:
                res.append(obj.next_object.name)
                res_tokens.append(tokenize_obj(obj.next_object))
                if obj is not my_app.selected_object and not found_selected:
                    count += 1
                    idx += len(obj.name) + 1  # Newline character
                else:
                    found_selected = True
                obj = obj.next_object

            self.buffer.set_document(
                Document(text="\n".join(res), cursor_position=idx), True)
            self.lexer.reset_tokens(res_tokens)
            return super().create_content(width, height)

    sidebar_control = myControl(
        buffer=sidebar_buffer,
        lexer=sidebar_lexer,
        search_buffer_control=search_field.control,
        focusable=True,
    )

    return HSplit([
        search_field,
        Window(sidebar_control,
               right_margins=[ScrollbarMargin(display_arrows=True)],
               style="class:sidebar",
               width=Dimension.exact(45),
               height=Dimension(min=7, preferred=33),
               scroll_offsets=ScrollOffsets(top=1, bottom=1)),
        Window(
            height=Dimension.exact(1),
            char="\u2500",
            style="class:sidebar,separator",
        ),
        expanding_object_notification(my_app),
        sql_sidebar_navigation()
    ])
예제 #5
0
파일: __init__.py 프로젝트: sjas/ptpdb
    def __init__(self):
        pdb.Pdb.__init__(self)

        # Cache for the grammar.
        self._grammar_cache = None  # (current_pdb_commands, grammar) tuple.

        self.completer = None
        self.validator = None
        self.lexer = None

        self._source_code_window = Window(BufferControl(
            buffer_name='source_code',
            lexer=PygmentsLexer(PythonLexer),
            input_processors=[
                HighlightSearchProcessor(preview_search=True),
                HighlightSelectionProcessor(),
            ],
        ),
                                          left_margins=[
                                              SourceCodeMargin(self),
                                              NumberredMargin(),
                                          ],
                                          right_margins=[ScrollbarMargin()],
                                          scroll_offsets=ScrollOffsets(
                                              top=2, bottom=2),
                                          height=LayoutDimension(preferred=10))

        # Callstack window.
        callstack = CallStack(weakref.ref(self))
        self.callstack_focussed = False  # When True, show cursor there, and allow navigation through it.
        self.callstack_selected_frame = 0  # Top frame.

        show_pdb_content_filter = ~IsDone() & Condition(
            lambda cli: not self.python_input.show_exit_confirmation)

        self.python_input = PythonInput(
            get_locals=lambda: self.curframe.f_locals,
            get_globals=lambda: self.curframe.f_globals,
            _completer=DynamicCompleter(lambda: self.completer),
            _validator=DynamicValidator(lambda: self.validator),
            _accept_action=self._create_accept_action(),
            _extra_buffers={'source_code': Buffer(read_only=True)},
            _input_buffer_height=LayoutDimension(min=2, max=4),
            _lexer=PdbLexer(),
            _extra_buffer_processors=[
                ConditionalProcessor(processor=CompletionHint(),
                                     filter=~IsDone())
            ],
            _extra_layout_body=ConditionalContainer(
                HSplit([
                    VSplit([
                        HSplit([
                            SourceTitlebar(weakref.ref(self)),
                            FloatContainer(
                                content=self._source_code_window,
                                floats=[
                                    Float(right=0,
                                          bottom=0,
                                          content=BreakPointInfoToolbar(
                                              weakref.ref(self)))
                                ]),
                        ]),
                        HSplit([
                            Window(width=LayoutDimension.exact(1),
                                   height=LayoutDimension.exact(1),
                                   content=FillControl(
                                       '\u252c', token=Token.Toolbar.Title)),
                            Window(width=LayoutDimension.exact(1),
                                   content=FillControl('\u2502',
                                                       token=Token.Separator)),
                        ]),
                        HSplit([
                            StackTitlebar(weakref.ref(self)),
                            Window(callstack,
                                   scroll_offsets=ScrollOffsets(top=2,
                                                                bottom=2),
                                   right_margins=[ScrollbarMargin()],
                                   height=LayoutDimension(preferred=10)),
                        ]),
                    ]),
                ]),
                filter=show_pdb_content_filter),
            _extra_toolbars=[
                ConditionalContainer(PdbShortcutsToolbar(weakref.ref(self)),
                                     show_pdb_content_filter)
            ],
            history_filename=os.path.expanduser('~/.ptpdb_history'),
        )

        # Override prompt style.
        self.python_input.all_prompt_styles['pdb'] = PdbPromptStyle(
            self._get_current_pdb_commands())
        self.python_input.prompt_style = 'pdb'

        # Override exit message.
        self.python_input.exit_message = 'Do you want to quit BDB? This raises BdbQuit.'

        # Set UI styles.
        self.python_input.ui_styles = {
            'ptpdb': get_ui_style(),
        }
        self.python_input.use_ui_colorscheme('ptpdb')

        # Set autocompletion style. (Multi-column works nicer.)
        self.python_input.completion_visualisation = CompletionVisualisation.MULTI_COLUMN

        # Load additional key bindings.
        load_custom_pdb_key_bindings(self,
                                     self.python_input.key_bindings_registry)

        self.cli = CommandLineInterface(
            eventloop=create_eventloop(),
            application=self.python_input.create_application())
예제 #6
0
파일: layout.py 프로젝트: xmonader/pyvim
    def __init__(self, editor):
        def highlight_location(location, search_string, default_token):
            """
            Return a tokenlist with the `search_string` highlighted.
            """
            result = [(default_token, c) for c in location]

            # Replace token of matching positions.
            for m in re.finditer(re.escape(search_string), location):
                for i in range(m.start(), m.end()):
                    result[i] = ('class:searchmatch', result[i][1])

            if location == search_string:
                result[0] = (result[0][0] + ' [SetCursorPosition]',
                             result[0][1])

            return result

        def get_tokens():
            wa = editor.window_arrangement
            buffer_infos = wa.list_open_buffers()

            # Filter infos according to typed text.
            input_params = editor.command_buffer.text.lstrip().split(None, 1)
            search_string = input_params[1] if len(input_params) > 1 else ''

            if search_string:

                def matches(info):
                    """
                    True when we should show this entry.
                    """
                    # When the input appears in the location.
                    if input_params[1] in (info.editor_buffer.location or ''):
                        return True

                    # When the input matches this buffer his index number.
                    if input_params[1] in str(info.index):
                        return True

                    # When this entry is part of the current completions list.
                    b = editor.command_buffer

                    if b.complete_state and any(
                            info.editor_buffer.location in c.display
                            for c in b.complete_state.completions
                            if info.editor_buffer.location is not None):
                        return True

                    return False

                buffer_infos = [info for info in buffer_infos if matches(info)]

            # Render output.
            if len(buffer_infos) == 0:
                return [('', ' No match found. ')]
            else:
                result = []

                # Create title.
                result.append(('', '  '))
                result.append(('class:title', 'Open buffers\n'))

                # Get length of longest location
                max_location_len = max(
                    len(info.editor_buffer.get_display_name())
                    for info in buffer_infos)

                # Show info for each buffer.
                for info in buffer_infos:
                    eb = info.editor_buffer
                    char = '%' if info.is_active else ' '
                    char2 = 'a' if info.is_visible else ' '
                    char3 = ' + ' if info.editor_buffer.has_unsaved_changes else '   '
                    t = 'class:active' if info.is_active else ''

                    result.extend([
                        ('', ' '),
                        (t, '%3i ' % info.index),
                        (t, '%s' % char),
                        (t, '%s ' % char2),
                        (t, '%s ' % char3),
                    ])
                    result.extend(
                        highlight_location(eb.get_display_name(),
                                           search_string, t))
                    result.extend([
                        (t, ' ' *
                         (max_location_len - len(eb.get_display_name()))),
                        (t + ' class:lineno', '  line %i' %
                         (eb.buffer.document.cursor_position_row + 1)),
                        (t, ' \n')
                    ])
                return result

        super(BufferListOverlay,
              self).__init__(Window(FormattedTextControl(get_tokens),
                                    style='class:bufferlist',
                                    scroll_offsets=ScrollOffsets(top=1,
                                                                 bottom=1)),
                             filter=_bufferlist_overlay_visible(editor))
예제 #7
0
def get_app(choices):
    class InquirerControl(TokenListControl):
        selected_option_index = 0
        answered = False
        choices = []

        def __init__(self, choices, **kwargs):
            self.choices = choices
            super(InquirerControl, self).__init__(self._get_choice_tokens,
                                                  **kwargs)

        @property
        def choice_count(self):
            return len(self.choices)

        def _get_choice_tokens(self, cli):
            tokens = []
            T = Token

            def append(index, label):
                selected = (index == self.selected_option_index)
                tokens.append((T.Selected if selected else T,
                               '> ' if selected else '  '))
                if selected:
                    tokens.append((Token.SetCursorPosition, ''))
                tokens.append((T.Selected if selected else T, '%-24s' % label))
                tokens.append((T, '\n'))

            for i, choice in enumerate(self.choices):
                append(i, choice)
            tokens.pop()  # Remove last newline.
            return tokens

        def get_selection(self):
            return self.choices[self.selected_option_index]

    ic = InquirerControl(choices)

    def get_prompt_tokens(cli):
        tokens = []
        if ic.answered:
            cli.return_value = lambda: ic.get_selection()
        return tokens

    layout = HSplit([
        Window(height=D.exact(0),
               content=TokenListControl(get_prompt_tokens,
                                        align_center=False)),
        ConditionalContainer(Window(ic,
                                    width=D.exact(43),
                                    height=D(min=3),
                                    scroll_offsets=ScrollOffsets(top=1,
                                                                 bottom=1)),
                             filter=~IsDone())
    ])

    manager = KeyBindingManager.for_prompt()

    @manager.registry.add_binding(Keys.ControlQ, eager=True)
    @manager.registry.add_binding(Keys.ControlC, eager=True)
    def _(event):
        event.cli.set_return_value(None)

    @manager.registry.add_binding(Keys.Down, eager=True)
    @manager.registry.add_binding(Keys.ControlN, eager=True)
    def move_cursor_down(event):
        ic.selected_option_index = ((ic.selected_option_index + 1) %
                                    ic.choice_count)

    @manager.registry.add_binding(Keys.Up, eager=True)
    @manager.registry.add_binding(Keys.ControlP, eager=True)
    def move_cursor_up(event):
        ic.selected_option_index = ((ic.selected_option_index - 1) %
                                    ic.choice_count)

    @manager.registry.add_binding(Keys.Enter, eager=True)
    def set_answer(event):
        ic.answered = True
        event.cli.set_return_value(None)

    inquirer_style = style_from_dict({
        Token.QuestionMark: '#5F819D',
        Token.Selected: '#FF9D00',
        Token.Instruction: '',
        Token.Answer: '#FF9D00 bold',
        Token.Question: 'bold',
    })

    app = Application(layout=layout,
                      key_bindings_registry=manager.registry,
                      mouse_support=True,
                      style=inquirer_style)

    return app
예제 #8
0
    tokens.append((Token.Question, string_query))
    if ic.answered:
        tokens.append((Token.Answer, ' ' + ic.get_selection()))
        selected_item(ic.get_selection())
    else:
        tokens.append((Token.Instruction, inst))
    return tokens


layout = HSplit([
    Window(height=D.exact(1),
           content=TokenListControl(get_prompt_tokens, align_center=False)),
    ConditionalContainer(Window(ic,
                                width=D.exact(43),
                                height=D(min=3),
                                scroll_offsets=ScrollOffsets(top=1, bottom=1)),
                         filter=~IsDone())
])

manager = KeyBindingManager.for_prompt()


@manager.registry.add_binding(Keys.ControlQ, eager=True)
@manager.registry.add_binding(Keys.ControlC, eager=True)
def _(event):
    event.cli.set_return_value(None)


@manager.registry.add_binding(Keys.Down, eager=True)
def move_cursor_down(event):
    ic.selected_option_index = ((ic.selected_option_index + 1) %
예제 #9
0
    def execute_code(self, frame):
        code = frame.code
        parsed_code = parse_code(frame)
        
        while True:
            inst = Inst(code[frame.ip])
            
            operand_stack_layout = []
            i = 0
            for v in frame.stack[::-1]:
                operand_stack_layout += [Label(f'TOS: {v}' if i == 0 else f'     {v}')]
                i += 1
                if isinstance(v, (np.longlong, np.double)):
                    operand_stack_layout += [Label('')]
                    i += 1
                    
            code_layout = []
            focused_element = None
            for ip, insn in parsed_code.items():
                if ip==frame.ip:
                    focused_element = Label(insn, style='bold fg:red')
                    code_layout += [focused_element]
                else:
                    code_layout += [Label(insn)]

            container = HSplit([
                VSplit([
                    HSplit([
                        PTFrame(
                            HSplit([
                                TextArea(f'NUMSTEPS'),
                                Label(f'Class: {frame.current_class.name()}'),
                                Label(f'Method: {frame.current_class.name()}.{frame.current_method.name}:{frame.current_method.desc}'),
                            ], height=3),
                            title='Context',
                        ),
                        PTFrame(
                            ScrollablePane(HSplit(code_layout, height=len(parsed_code) or 1), 
                                           scroll_offsets=ScrollOffsets(top=5, bottom=5),
                                           show_scrollbar=False),
                            title='ByteCode',
                        ),
                    ]),
                    HSplit([
                        PTFrame(
                            HSplit([Label(f'{i}: {v}') for i, v in enumerate(frame.locals)
                                   ], height=len(frame.locals) or 1),
                            title='Local Variables Stack',
                        ),
                        PTFrame(
                            HSplit(operand_stack_layout, height=len(operand_stack_layout) or 1),
                            title='Operands Stack',
                        )
                    ])
                ]),
                Window(),
                Label('UP/DOWN: step backward/forward. gg/GG: jump to the start/end. v: toggle view. q: quit.')
            ])

            global LAYOUT_STACK
            
            layout = Layout(container=container, focused_element=focused_element)
            LAYOUT_STACK += [layout]
            
            #print(frame.ip, inst.name)

            if len(frame.stack) > frame.max_stack + 1:
                print("MAX STACK")
                break

            if inst in OPCODES:
                OPCODES[inst](frame)
            elif inst == Inst.IASTORE or inst == Inst.AASTORE:
                val = frame.stack.pop()
                index = frame.stack.pop()
                array = frame.stack.pop()

                array[index] = val
            elif inst == Inst.IREM:
                v2 = frame.stack.pop()
                v1 = frame.stack.pop()
                frame.stack.append(v1 % v2)
            elif inst == Inst.IINC:
                index = read_byte(frame)
                const = read_signed_byte(frame)

                frame.set_local(index, frame.get_local(index) + const)
            elif inst == Inst.IFNE:
                v1 = frame.stack.pop()

                branch = read_signed_short(frame)

                if v1 != 0:
                    frame.ip -= 3
                    frame.ip += branch
            elif inst == Inst.IFLT:
                v1 = frame.stack.pop()
                branch = read_signed_short(frame)

                if v1 < 0:
                    frame.ip -= 3
                    frame.ip += branch
            elif inst == Inst.IFGE:
                v1 = frame.stack.pop()

                branch = read_signed_short(frame)

                if v1 >= 0:
                    frame.ip -= 3
                    frame.ip += branch
            elif inst == Inst.IFLE:
                v1 = frame.stack.pop()

                branch = read_signed_short(frame)

                if v1 <= 0:
                    frame.ip -= 3
                    frame.ip += branch
            elif inst == Inst.IF_ICMPLT:
                v2 = frame.stack.pop()
                v1 = frame.stack.pop()

                branch = read_signed_short(frame)

                if type(v1) is str and len(v1) == 1:
                    v1 = ord(v1)

                if type(v2) is str and len(v2) == 1:
                    v2 = ord(v2)

                if v1 < v2:
                    frame.ip -= 3
                    frame.ip += branch
            elif inst == Inst.IF_ICMPGE:
                v2 = frame.stack.pop()
                v1 = frame.stack.pop()

                branch = read_signed_short(frame)

                if type(v1) is str and len(v1) == 1:
                    v1 = ord(v1)

                if type(v2) is str and len(v2) == 1:
                    v2 = ord(v2)

                if v1 >= v2:
                    frame.ip -= 3
                    frame.ip += branch
            elif inst == Inst.IF_ICMPGT:
                v2 = frame.stack.pop()
                v1 = frame.stack.pop()

                branch = read_signed_short(frame)

                if type(v1) is str and len(v1) == 1:
                    v1 = ord(v1)

                if type(v2) is str and len(v2) == 1:
                    v2 = ord(v2)

                if v1 > v2:
                    frame.ip -= 3
                    frame.ip += branch
            elif inst == Inst.IF_ICMPLE:
                v2 = frame.stack.pop()
                v1 = frame.stack.pop()
                branch = read_signed_short(frame)

                if v1 <= v2:
                    frame.ip -= 3
                    frame.ip += branch
            elif inst == Inst.GOTO:
                branch = read_signed_short(frame)

                frame.ip -= 3
                frame.ip += branch
            elif inst == Inst.IRET or inst == Inst.LRET or inst == Inst.ARETURN or inst == Inst.DRETURN:
                return frame.stack.pop()
            elif inst == Inst.RETURN:
                return
            elif inst == Inst.GETSTATIC:
                index = read_unsigned_short(frame)

                methodRef = frame.current_class.const_pool[index - 1]
                name = frame.current_class.const_pool[methodRef.class_index - 1].name
                natIndex = methodRef.name_and_type_index
                nat = frame.current_class.const_pool[natIndex - 1]

                if name in self.class_files:
                    cl = self.class_files[name]
                    
                    if not cl.static_initialized:
                        cl.static_initialized = True
                        
                        # first parse and initialize all existing static fields
                        if isinstance(cl, ClassFile):
                            for c in cl.const_pool:
                                if c.tag and c.tag.name == 'FIELDREF':
                                    name = cl.const_pool[c.name_and_type_index-1].name
                                    desc = cl.const_pool[c.name_and_type_index-1].desc
                                    cl.set_field(name, DEFAULTS.get(desc, None))
                                    
                        # then run the initializers
                        cl.handleStatic('<clinit>', '()V', frame)
                    frame.stack.append(cl.get_field(nat.name))

                #print(name)
                #print(vars(nat))
                #frame.stack.append(PrintStream())
            elif inst == Inst.PUTSTATIC:
                index = read_unsigned_short(frame)

                methodRef = frame.current_class.const_pool[index - 1]
                name = frame.current_class.const_pool[methodRef.class_index - 1].name
                natIndex = methodRef.name_and_type_index
                nat = frame.current_class.const_pool[natIndex - 1]

                if name in self.class_files:
                    cl = self.class_files[name]
                    if not cl.static_initialized:
                        cl.static_initialized = True
                                    
                        # run the initializers
                        cl.handleStatic('<clinit>', '()V', frame)
                    cl.set_field(nat.name, frame.stack.pop())
            elif inst == Inst.GETFIELD:
                index = read_unsigned_short(frame)

                ref = frame.current_class.const_pool[index - 1]
                name = frame.current_class.const_pool[ref.class_index - 1].name
                natIndex = ref.name_and_type_index
                nat = frame.current_class.const_pool[natIndex - 1]

                #print(vars(nat))

                obj = frame.stack.pop()
                #print(obj)
                frame.stack.append(obj.get_field(nat.name))
            elif inst == Inst.PUTFIELD:
                index = read_unsigned_short(frame)

                ref = frame.current_class.const_pool[index - 1]
                name = frame.current_class.const_pool[ref.class_index - 1].name
                natIndex = ref.name_and_type_index
                nat = frame.current_class.const_pool[natIndex - 1]

                #print(vars(nat))

                value = frame.stack.pop()
                obj = frame.stack.pop()
                obj.set_field(nat.name, value)
            elif inst == Inst.INVOKEVIRTUAL:
                index = read_unsigned_short(frame)

                methodRef = frame.current_class.const_pool[index - 1]
                name = frame.current_class.const_pool[methodRef.class_index - 1].name
                natIndex = methodRef.name_and_type_index
                nat = frame.current_class.const_pool[natIndex - 1]

                #print(name)
                #print(vars(nat))

                if name in self.class_files:
                    cl = self.class_files[name]
                    if cl.canHandleMethod(nat.name, nat.desc):
                        ret = cl.handleMethod(nat.name, nat.desc, frame)
                        if not nat.desc.endswith('V'):
                            frame.push(ret)
                else:
                    for i in range(argumentCount(nat.desc)):
                        frame.stack.pop()
                    frame.stack.pop()
            elif inst == Inst.INVOKESPECIAL:
                index = read_unsigned_short(frame)

                methodRef = frame.current_class.const_pool[index - 1]
                name = frame.current_class.const_pool[methodRef.class_index - 1].name
                natIndex = methodRef.name_and_type_index
                nat = frame.current_class.const_pool[natIndex - 1]

                #print(vars(methodRef))
                #print(vars(nat))
                #print(name)

                if name in self.class_files:
                    cl = self.class_files[name]
                    if cl.canHandleMethod(nat.name, nat.desc):
                        ret = cl.handleMethod(nat.name, nat.desc, frame)
                    else:
                        frame.stack.pop()
                        
            elif inst == Inst.INVOKESTATIC:
                index = read_unsigned_short(frame)

                methodRef = frame.current_class.const_pool[index - 1]
                cname = frame.current_class.const_pool[methodRef.class_index - 1].name
                natIndex = methodRef.name_and_type_index
                nat = frame.current_class.const_pool[natIndex - 1]

                #print(vars(methodRef))
                #print(vars(nat))
                #print(cname)

                if cname in self.class_files:
                    cl = self.class_files[cname]
                    if cl.canHandleMethod(nat.name, nat.desc):
                        ret = cl.handleStatic(nat.name, nat.desc, frame)
                        if not nat.desc.endswith('V'):
                            frame.push(ret)
            elif inst == Inst.NEW:
                index = read_unsigned_short(frame)
                
                methodRef = frame.current_class.const_pool[index - 1]

                if methodRef.name in self.class_files:
                    obj = self.class_files[methodRef.name].__class__()
                    if self.class_files[methodRef.name].file_path:
                        obj.from_file(self.class_files[methodRef.name].file_path)

                    obj.python_initialize()

                    frame.stack.append(obj)
                else:
                    frame.stack.append(None)

            #print(frame.stack, frame.locals)
            frame.ip += 1
예제 #10
0
def python_sidebar(python_input):
    """
    Create the `Layout` for the sidebar with the configurable options.
    """
    def get_text_fragments():
        tokens = []

        def append_category(category):
            tokens.extend([
                ('class:sidebar', '  '),
                ('class:sidebar.title', '   %-36s' % category.title),
                ('class:sidebar', '\n'),
            ])

        def append(index, label, status):
            selected = index == python_input.selected_option_index

            @if_mousedown
            def select_item(mouse_event):
                python_input.selected_option_index = index

            @if_mousedown
            def goto_next(mouse_event):
                " Select item and go to next value. "
                python_input.selected_option_index = index
                option = python_input.selected_option
                option.activate_next()

            sel = ',selected' if selected else ''

            tokens.append(('class:sidebar' + sel, ' >' if selected else '  '))
            tokens.append(
                ('class:sidebar.label' + sel, '%-24s' % label, select_item))
            tokens.append(('class:sidebar.status' + sel, ' ', select_item))
            tokens.append(
                ('class:sidebar.status' + sel, '%s' % status, goto_next))

            if selected:
                tokens.append(('[SetCursorPosition]', ''))

            tokens.append(('class:sidebar.status' + sel,
                           ' ' * (13 - len(status)), goto_next))
            tokens.append(('class:sidebar', '<' if selected else ''))
            tokens.append(('class:sidebar', '\n'))

        i = 0
        for category in python_input.options:
            append_category(category)

            for option in category.options:
                append(i, option.title, '%s' % option.get_current_value())
                i += 1

        tokens.pop()  # Remove last newline.

        return tokens

    class Control(FormattedTextControl):
        def move_cursor_down(self):
            python_input.selected_option_index += 1

        def move_cursor_up(self):
            python_input.selected_option_index -= 1

    return Window(Control(get_text_fragments),
                  style='class:sidebar',
                  width=Dimension.exact(43),
                  height=Dimension(min=3),
                  scroll_offsets=ScrollOffsets(top=1, bottom=1))
예제 #11
0
def question(message, **kwargs):
    # TODO add bottom-bar (Move up and down to reveal more choices)
    # TODO extract common parts for list, checkbox, rawlist, expand
    # TODO disabled
    # TODO validate
    if not 'choices' in kwargs:
        raise PromptParameterException('choices')
    # this does not implement default, use checked...
    if 'default' in kwargs:
        raise ValueError('Checkbox does not implement \'default\' '
                         'use \'checked\':True\' in choice!')

    choices = kwargs.pop('choices', None)
    validator = setup_simple_validator(kwargs)

    # TODO style defaults on detail level
    style = kwargs.pop('style', default_style)

    ic = InquirerControl(choices)

    def get_prompt_tokens(cli):
        tokens = []
        T = Token

        tokens.append((Token.QuestionMark, '?'))
        tokens.append((Token.Question, ' %s ' % message))
        if ic.answered:
            nbr_selected = len(ic.selected_options)
            if nbr_selected == 0:
                tokens.append((Token.Answer, ' done'))
            elif nbr_selected == 1:
                tokens.append((Token.Answer, ' [%s]' % ic.selected_options[0]))
            else:
                tokens.append(
                    (Token.Answer, ' done (%d selections)' % nbr_selected))
        else:
            tokens.append((Token.Instruction,
                           ' (<up>, <down> to move, <space> to select, <a> '
                           'to toggle, <i> to invert)'))
        return tokens

    # assemble layout
    layout = HSplit([
        Window(height=D.exact(1),
               content=TokenListControl(get_prompt_tokens,
                                        align_center=False)),
        ConditionalContainer(Window(ic,
                                    width=D.exact(43),
                                    height=D(min=3),
                                    scroll_offsets=ScrollOffsets(top=1,
                                                                 bottom=1)),
                             filter=~IsDone())
    ])

    # key bindings
    manager = KeyBindingManager.for_prompt()

    @manager.registry.add_binding(Keys.ControlQ, eager=True)
    @manager.registry.add_binding(Keys.ControlC, eager=True)
    def _(event):
        raise KeyboardInterrupt()
        # event.cli.set_return_value(None)

    @manager.registry.add_binding(' ', eager=True)
    def toggle(event):
        pointed_choice = ic.choices[ic.pointer_index][0]  # name
        if pointed_choice in ic.selected_options:
            ic.selected_options.remove(pointed_choice)
        else:
            ic.selected_options.append(pointed_choice)

    @manager.registry.add_binding('i', eager=True)
    def invert(event):
        inverted_selection = [
            c[0] for c in ic.choices
            if not isinstance(c, Separator) and c[0] not in ic.selected_options
        ]
        ic.selected_options = inverted_selection

    @manager.registry.add_binding('a', eager=True)
    def all(event):
        all_selected = True  # all choices have been selected
        for c in ic.choices:
            if not isinstance(c,
                              Separator) and c[0] not in ic.selected_options:
                # add missing ones
                ic.selected_options.append(c[0])
                all_selected = False
        if all_selected:
            ic.selected_options = []

    @manager.registry.add_binding(Keys.Down, eager=True)
    def move_cursor_down(event):
        def _next():
            ic.pointer_index = ((ic.pointer_index + 1) % ic.line_count)

        _next()
        while isinstance(ic.choices[ic.pointer_index], Separator):
            _next()

    @manager.registry.add_binding(Keys.Up, eager=True)
    def move_cursor_up(event):
        def _prev():
            ic.pointer_index = ((ic.pointer_index - 1) % ic.line_count)

        _prev()
        while isinstance(ic.choices[ic.pointer_index], Separator):
            _prev()

    @manager.registry.add_binding(Keys.Enter, eager=True)
    def set_answer(event):
        ic.answered = True
        # TODO use validator
        event.cli.set_return_value(ic.get_selected_values())

    return Application(layout=layout,
                       key_bindings_registry=manager.registry,
                       mouse_support=True,
                       style=style)
예제 #12
0
def question(message, **kwargs):
    # TODO disabled, dict choices
    if not 'choices' in kwargs:
        raise PromptParameterException('choices')

    choices = kwargs.pop('choices', None)
    default = kwargs.pop('default', 0)  # TODO

    # TODO style defaults on detail level
    style = kwargs.pop('style', default_style)

    ic = InquirerControl(choices)

    def get_prompt_tokens(cli):
        tokens = []
        T = Token

        tokens.append((Token.QuestionMark, '?'))
        tokens.append((Token.Question, ' %s ' % message))
        if ic.answered:
            tokens.append((Token.Answer, ' ' + ic.get_selection()))
        else:
            tokens.append((Token.Instruction, ' (Use arrow keys)'))
        return tokens

    # assemble layout
    layout = HSplit([
        Window(height=D.exact(1),
               content=TokenListControl(get_prompt_tokens, align_center=False)),
        ConditionalContainer(
            Window(
                ic,
                width=D.exact(43),
                height=D(min=3),
                scroll_offsets=ScrollOffsets(top=1, bottom=1)
            ),
            filter=~IsDone()
        )
    ])

    # key bindings
    manager = KeyBindingManager.for_prompt()

    @manager.registry.add_binding(Keys.ControlQ, eager=True)
    @manager.registry.add_binding(Keys.ControlC, eager=True)
    def _(event):
        raise KeyboardInterrupt()
        # event.cli.set_return_value(None)

    @manager.registry.add_binding(Keys.Down, eager=True)
    def move_cursor_down(event):
        def _next():
            ic.selected_option_index = (
                (ic.selected_option_index + 1) % ic.choice_count)
        _next()
        while isinstance(ic.choices[ic.selected_option_index][0], Separator) or\
                ic.choices[ic.selected_option_index][1]:
            _next()

    @manager.registry.add_binding(Keys.Up, eager=True)
    def move_cursor_up(event):
        def _prev():
            ic.selected_option_index = (
                (ic.selected_option_index - 1) % ic.choice_count)
        _prev()
        while isinstance(ic.choices[ic.selected_option_index][0], Separator) or \
                ic.choices[ic.selected_option_index][1]:
            _prev()

    @manager.registry.add_binding(Keys.Enter, eager=True)
    def set_answer(event):
        ic.answered = True
        event.cli.set_return_value(ic.get_selection())

    return Application(
        layout=layout,
        key_bindings_registry=manager.registry,
        mouse_support=True,
        style=style
    )
예제 #13
0
파일: list.py 프로젝트: papis/papis
    def __init__(self,
                 options: Sequence[Option],
                 default_index: int = 0,
                 header_filter: Callable[[Option], str] = str,
                 match_filter: Callable[[Option], str] = str,
                 custom_filter: Optional[Callable[[str], bool]] = None,
                 search_buffer: Buffer = Buffer(multiline=False),
                 cpu_count: int = os.cpu_count()):

        self.search_buffer = search_buffer
        self.last_query_text = ''  # type: str
        self.search_buffer.on_text_changed += self.update

        self.header_filter = header_filter
        self.match_filter = match_filter
        self.current_index = default_index  # type: Optional[int]
        self.entries_left_offset = 0
        self.cpu_count = cpu_count

        self.options_headers_linecount = []  # type: List[int]
        self._indices_to_lines = []  # type: List[int]

        self.options_headers = []  # type: FormattedText
        self.options_matchers = []  # type: List[str]
        self.indices = []  # type: List[int]
        self._options = []  # type: Sequence[Option]
        self.marks = []  # type: List[int]
        self.max_entry_height = 1  # type: int

        # options are processed here also through the setter
        # ##################################################
        self.set_options(options)
        self.cursor = Point(0, 0)  # type: Point
        # ##################################################

        self.content = FormattedTextControl(
            text=self.get_tokens,
            focusable=False,
            key_bindings=None,
            get_cursor_position=lambda: self.cursor,
        )
        self.content_window = Window(
            content=self.content,
            wrap_lines=False,
            allow_scroll_beyond_bottom=True,
            scroll_offsets=ScrollOffsets(bottom=self.max_entry_height),
            cursorline=False,
            cursorcolumn=False,
            # right_margins=[NumberedMargin()],
            # left_margins=[NumberedMargin()],
            align=WindowAlign.LEFT,
            height=None,
            get_line_prefix=self.get_line_prefix
            # get_line_prefix=lambda line, b: [('bg:red', '  ')]
        )

        self.update()

        super(OptionsList,
              self).__init__(content=self.content_window,
                             filter=(custom_filter if custom_filter is not None
                                     else has_focus(self.search_buffer)))
예제 #14
0
def sidebar(name, kvdict):
    # shamelessly stolen and adapted from ptpython/layout.py
    _MAX_KEY_WIDTH = 8
    _VAL_WIDTH = 14  # sufficient to print "0x" + 12hex chars for a 48bit memory address
    _CTR_WIDTH = _MAX_KEY_WIDTH + _VAL_WIDTH

    def center_str(s, w):
        l = len(s)
        e = w - l
        t = ''
        i = 0
        while i < e / 2:
            t += ' '
            i += 1
        t += s
        i = len(t)
        while i < w:
            t += ' '
            i += 1
        return t

    def pad_or_cut(s, w):
        if len(s) > w: s = s[:w]
        while len(s) < w:
            s += ' '
        return s

    def get_text_fragments():
        tokens = []

        def append_title(title):
            @if_mousedown
            def focus_from_title(mouse_event):
                get_app().my.set_focus(name)

            foc = ',focused' if get_app().my.focused_control == name else ''
            tokens.extend([
                ('class:sidebar', ' ', focus_from_title),
                ('class:sidebar.title' + foc, center_str(title, _CTR_WIDTH),
                 focus_from_title),
                ('class:sidebar', '\n'),
            ])

        def append(index, label, status, max_key_len):
            key_len = min(_MAX_KEY_WIDTH, max_key_len)
            val_len = _CTR_WIDTH - key_len
            selected = get_app(
            ).my.controls[name].selected_option_index == index

            @if_mousedown
            def select_item(mouse_event):
                get_app().my.set_focus(name)
                get_app().my.controls[name].selected_option_index = index

            @if_mousedown
            def trigger_vardetail(mouse_event):
                get_app().my.set_focus(name)
                get_app().my.controls[name].selected_option_index = index
                vardetails_toggle_on_off()

            odd = 'odd' if index % 2 != 0 else ''
            sel = ',selected' if selected else ''
            chg = ',changed' if kvdict().was_changed(label) else ''
            tokens.append(('class:sidebar' + sel, '>' if selected else ' '))
            tokens.append(('class:sidebar.label' + odd + sel,
                           pad_or_cut(label, key_len), select_item))
            tokens.append(('class:sidebar.status' + odd + sel + chg,
                           pad_or_cut(status, val_len), trigger_vardetail))
            if selected:
                tokens.append(('[SetCursorPosition]', ''))
            tokens.append(('class:sidebar', '<' if selected else ' '))
            tokens.append(('class:sidebar', '\n'))

        i = 0
        append_title(name)
        mydict = kvdict() if callable(kvdict) else kvdict
        max_key_len = 0
        for key in mydict:
            max_key_len = max(max_key_len, len(key))
        for key in mydict:
            values = mydict[key]
            append(i, key, '%s' % values[0], max_key_len + 1)
            i += 1
        tokens.pop()  # Remove last newline.
        i += 1  # title
        get_app().my.controls[name].height = Dimension(min=2,
                                                       max=i +
                                                       1 if i > 1 else 2)
        return tokens

    ctrl = Window(SidebarControl(get_text_fragments),
                  style='class:sidebar',
                  width=Dimension.exact(_CTR_WIDTH + 2),
                  height=Dimension(min=2),
                  scroll_offsets=ScrollOffsets(top=1, bottom=1))
    ctrl.selected_option_index = 0
    return ctrl
예제 #15
0
def python_sidebar(python_input: "PythonInput") -> Window:
    """
    Create the `Layout` for the sidebar with the configurable options.
    """
    def get_text_fragments() -> StyleAndTextTuples:
        tokens: StyleAndTextTuples = []

        def append_category(category: "OptionCategory") -> None:
            tokens.extend([
                ("class:sidebar", "  "),
                ("class:sidebar.title", "   %-36s" % category.title),
                ("class:sidebar", "\n"),
            ])

        def append(index: int, label: str, status: str) -> None:
            selected = index == python_input.selected_option_index

            @if_mousedown
            def select_item(mouse_event: MouseEvent) -> None:
                python_input.selected_option_index = index

            @if_mousedown
            def goto_next(mouse_event: MouseEvent) -> None:
                " Select item and go to next value. "
                python_input.selected_option_index = index
                option = python_input.selected_option
                option.activate_next()

            sel = ",selected" if selected else ""

            tokens.append(("class:sidebar" + sel, " >" if selected else "  "))
            tokens.append(
                ("class:sidebar.label" + sel, "%-24s" % label, select_item))
            tokens.append(("class:sidebar.status" + sel, " ", select_item))
            tokens.append(
                ("class:sidebar.status" + sel, "%s" % status, goto_next))

            if selected:
                tokens.append(("[SetCursorPosition]", ""))

            tokens.append(("class:sidebar.status" + sel,
                           " " * (13 - len(status)), goto_next))
            tokens.append(("class:sidebar", "<" if selected else ""))
            tokens.append(("class:sidebar", "\n"))

        i = 0
        for category in python_input.options:
            append_category(category)

            for option in category.options:
                append(i, option.title, "%s" % option.get_current_value())
                i += 1

        tokens.pop()  # Remove last newline.

        return tokens

    class Control(FormattedTextControl):
        def move_cursor_down(self):
            python_input.selected_option_index += 1

        def move_cursor_up(self):
            python_input.selected_option_index -= 1

    return Window(
        Control(get_text_fragments),
        style="class:sidebar",
        width=Dimension.exact(43),
        height=Dimension(min=3),
        scroll_offsets=ScrollOffsets(top=1, bottom=1),
    )
예제 #16
0
    def __init__(self, history):
        search_toolbar = SearchToolbar()

        self.help_buffer_control = BufferControl(buffer=history.help_buffer,
                                                 lexer=PygmentsLexer(RstLexer))

        help_window = _create_popup_window(
            title="History Help",
            body=Window(
                content=self.help_buffer_control,
                right_margins=[ScrollbarMargin(display_arrows=True)],
                scroll_offsets=ScrollOffsets(top=2, bottom=2),
            ),
        )

        self.default_buffer_control = BufferControl(
            buffer=history.default_buffer,
            input_processors=[GrayExistingText(history.history_mapping)],
            lexer=PygmentsLexer(PythonLexer),
        )

        self.history_buffer_control = BufferControl(
            buffer=history.history_buffer,
            lexer=PygmentsLexer(PythonLexer),
            search_buffer_control=search_toolbar.control,
            preview_search=True,
        )

        history_window = Window(
            content=self.history_buffer_control,
            wrap_lines=False,
            left_margins=[HistoryMargin(history)],
            scroll_offsets=ScrollOffsets(top=2, bottom=2),
        )

        self.root_container = HSplit([
            #  Top title bar.
            Window(
                content=FormattedTextControl(_get_top_toolbar_fragments),
                align=WindowAlign.CENTER,
                style="class:status-toolbar",
            ),
            FloatContainer(
                content=VSplit([
                    # Left side: history.
                    history_window,
                    # Separator.
                    Window(
                        width=D.exact(1),
                        char=BORDER.LIGHT_VERTICAL,
                        style="class:separator",
                    ),
                    # Right side: result.
                    Window(
                        content=self.default_buffer_control,
                        wrap_lines=False,
                        left_margins=[ResultMargin(history)],
                        scroll_offsets=ScrollOffsets(top=2, bottom=2),
                    ),
                ]),
                floats=[
                    # Help text as a float.
                    Float(
                        width=60,
                        top=3,
                        bottom=2,
                        content=ConditionalContainer(
                            content=help_window,
                            filter=has_focus(history.help_buffer),
                        ),
                    )
                ],
            ),
            # Bottom toolbars.
            ArgToolbar(),
            search_toolbar,
            Window(
                content=FormattedTextControl(
                    partial(_get_bottom_toolbar_fragments, history=history)),
                style="class:status-toolbar",
            ),
        ])

        self.layout = Layout(self.root_container, history_window)
예제 #17
0
def question(message, **kwargs):
    # TODO add bottom-bar (Move up and down to reveal more choices)
    # TODO extract common parts for list, checkbox, rawlist, expand
    # TODO validate
    if not 'choices' in kwargs:
        raise PromptParameterException('choices')
    # this does not implement default, use checked...
    if 'default' in kwargs:
        raise ValueError('Checkbox does not implement \'default\' '
                         'use \'checked\':True\' in choice!')

    choices = kwargs.pop('choices', None)
    validator = setup_simple_validator(kwargs)

    # TODO style defaults on detail level
    style = kwargs.pop('style', default_style)

    pointer_index = kwargs.pop('pointer_index', 0)
    additional_parameters = dict()
    additional_parameters.update(
        {"pointer_sign": kwargs.pop('pointer_sign', '\u276f')})
    additional_parameters.update(
        {"selected_sign": kwargs.pop('selected_sign', '\u25cf')})
    additional_parameters.update(
        {"unselected_sign": kwargs.pop('unselected_sign', '\u25cb')})

    ic = InquirerControl(choices, pointer_index, **additional_parameters)
    qmark = kwargs.pop('qmark', '?')

    def get_prompt_tokens():
        tokens = []

        tokens.append(('class:questionmark', qmark))
        tokens.append(('class:question', ' %s ' % message))
        if ic.answered:
            nbr_selected = len(ic.selected_options)
            if nbr_selected == 0:
                tokens.append(('class:answer', ' done'))
            elif nbr_selected == 1:
                tokens.append(
                    ('class:Answer', ' [%s]' % ic.selected_options[0]))
            else:
                tokens.append(
                    ('class:answer', ' done (%d selections)' % nbr_selected))
        else:
            tokens.append(('class:instruction',
                           ' (<up>, <down> to move, <space> to select, <a> '
                           'to toggle, <i> to invert)'))
            if not ic.answered_correctly:
                tokens.append((Token.Error, ' Error: %s' % ic.error_message))
        return tokens

    # assemble layout
    layout = HSplit([
        Window(
            height=D.exact(1),
            content=FormattedTextControl(get_prompt_tokens),
            align=WindowAlign.CENTER,
        ),
        ConditionalContainer(Window(ic,
                                    width=D.exact(43),
                                    height=D(min=3),
                                    scroll_offsets=ScrollOffsets(top=1,
                                                                 bottom=1)),
                             filter=~IsDone())
    ])

    # key bindings
    kb = KeyBindings()

    @kb.add('c-q', eager=True)
    @kb.add('c-c', eager=True)
    def _(event):
        raise KeyboardInterrupt()
        # event.app.exit(result=None)

    @kb.add(' ', eager=True)
    def toggle(event):
        pointed_choice = ic.choices[ic.pointer_index][1]  # value
        if pointed_choice in ic.selected_options:
            ic.selected_options.remove(pointed_choice)
        else:
            ic.selected_options.append(pointed_choice)

    @kb.add('i', eager=True)
    def invert(event):
        inverted_selection = [
            c[1] for c in ic.choices if not isinstance(c, Separator)
            and c[1] not in ic.selected_options and not c[2]
        ]
        ic.selected_options = inverted_selection

    @kb.add('a', eager=True)
    def all(event):
        all_selected = True  # all choices have been selected
        for c in ic.choices:
            if not isinstance(c, Separator) and c[
                    1] not in ic.selected_options and not c[2]:
                # add missing ones
                ic.selected_options.append(c[1])
                all_selected = False
        if all_selected:
            ic.selected_options = []

    @kb.add('down', eager=True)
    def move_cursor_down(event):
        def _next():
            ic.pointer_index = ((ic.pointer_index + 1) % ic.line_count)

        _next()
        while isinstance(ic.choices[ic.pointer_index], Separator) or \
                ic.choices[ic.pointer_index][2]:
            _next()

    @kb.add('up', eager=True)
    def move_cursor_up(event):
        def _prev():
            ic.pointer_index = ((ic.pointer_index - 1) % ic.line_count)

        _prev()
        while isinstance(ic.choices[ic.pointer_index], Separator) or \
                ic.choices[ic.pointer_index][2]:
            _prev()

    @kb.add('enter', eager=True)
    def set_answer(event):
        ic.answered = True
        # TODO use validator
        event.app.exit(result=ic.get_selected_values())

    return Application(layout=Layout(layout),
                       key_bindings=kb,
                       mouse_support=True,
                       style=style)
예제 #18
0
def select_issue(choices, pointer_index):
    controller = IssuesController(message='choose issues',
                                  choices=choices,
                                  pointer_index=pointer_index)

    def get_prompt():
        prompt = []

        prompt.append(('class:qmark', '?'))
        prompt.append(('class:question', ' %s ' % 'Choose issues:'))

        return prompt

    layout = Layout(
        HSplit([
            Window(height=D.exact(1),
                   content=FormattedTextControl(get_prompt(),
                                                show_cursor=False)),
            ConditionalContainer(Window(content=controller,
                                        width=D.exact(43),
                                        height=D(min=3),
                                        scroll_offsets=ScrollOffsets(
                                            top=1, bottom=1)),
                                 filter=~IsDone())
        ]))

    bindings = KeyBindings()

    @bindings.add(Keys.ControlQ, eager=True)
    @bindings.add(Keys.ControlC, eager=True)
    def exit(event):
        event.app.exit(result=[])

    @bindings.add(' ', eager=True)
    def toggle(event):
        controller.toggle(controller.pointer_index)
        event.app.invalidate()

    @bindings.add('j', eager=True)
    @bindings.add(Keys.Down, eager=True)
    def move_cursor_down(event):
        def _next():
            controller.pointer_index = ((controller.pointer_index + 1) %
                                        controller.line_count)
            event.app.invalidate()

        _next()
        while controller.choices[controller.pointer_index][2]:
            _next()

    @bindings.add(Keys.Up, eager=True)
    @bindings.add('k', eager=True)
    def move_cursor_up(event):
        def _prev():
            controller.pointer_index = ((controller.pointer_index - 1) %
                                        controller.line_count)
            event.app.invalidate()

        _prev()
        while controller.choices[controller.pointer_index][2]:
            _prev()

    @bindings.add(Keys.Enter, eager=True)
    def set_answer(event):
        controller.answered = True
        event.app.exit(result=controller.selected)

    style = Style.from_dict({
        'separator': '#6C6C6C',
        'qmark': '#FF9D00 bold',
        'sel_issue': 'fg:#5Fff9D bg: bold',
        'pointer': '#FF9D00 bold',
        'answer': '#5F819D bold',
        'default': '',
    })

    app = Application(
        layout=layout,
        key_bindings=bindings,
        mouse_support=True,
        style=style,
    )

    if controller.has_active_choices():
        result = app.run()
        return result
    else:
        print_formatted_text(FormattedText(controller.get_formatted_choices()),
                             style=style)
        return []