def meta_enter_message(python_input: "PythonInput") -> Container: """ Create the `Layout` for the 'Meta+Enter` message. """ def get_text_fragments() -> StyleAndTextTuples: return [("class:accept-message", " [Meta+Enter] Execute ")] @Condition def extra_condition() -> bool: " Only show when... " b = python_input.default_buffer return (python_input.show_meta_enter_message and (not b.document.is_cursor_at_the_end or python_input.accept_input_on_enter is None) and "\n" in b.text) visible = ~is_done & has_focus(DEFAULT_BUFFER) & extra_condition return ConditionalContainer(content=Window( FormattedTextControl(get_text_fragments)), filter=visible)
def show_sidebar_button_info(my_app: "sqlApp") -> Container: """ Create `Layout` for the information in the right-bottom corner. (The right part of the status bar.) """ @if_mousedown def toggle_sidebar(mouse_event: MouseEvent) -> None: " Click handler for the menu. " my_app.show_sidebar = not my_app.show_sidebar # TO DO: app version rather than python version = sys.version_info tokens: StyleAndTextTuples = [ ("class:status-toolbar.key", "[C-t]", toggle_sidebar), ("class:status-toolbar", " Object Browser", toggle_sidebar), ("class:status-toolbar", " - "), ("class:status-toolbar.cli-version", "odbcli %s" % __version__), ("class:status-toolbar", " "), ] width = fragment_list_width(tokens) def get_text_fragments() -> StyleAndTextTuples: # Python version return tokens return ConditionalContainer( content=Window( FormattedTextControl(get_text_fragments), style="class:status-toolbar", height=Dimension.exact(1), width=Dimension.exact(width), ), filter=~is_done & Condition( lambda: not my_app.show_exit_confirmation ) & renderer_height_is_known )
def create_tutorial_layout(self): """ layout for example tutorial """ lexer, _, _ = get_lexers(self.shell_ctx.lexer, None, None) layout_full = HSplit([ FloatContainer( Window( BufferControl( input_processors=self.input_processors, lexer=lexer, preview_search=Always()), get_height=get_height), [ Float(xcursor=True, ycursor=True, content=CompletionsMenu( max_height=MAX_COMPLETION, scroll_offset=1, extra_filter=(HasFocus(DEFAULT_BUFFER))))]), ConditionalContainer( HSplit([ get_hline(), get_param(lexer), get_hline(), Window( content=BufferControl( buffer_name='example_line', lexer=lexer ), ), Window( TokenListControl( get_tutorial_tokens, default_char=Char(' ', Token.Toolbar)), height=LayoutDimension.exact(1)), ]), filter=~IsDone() & RendererHeightIsKnown() ) ]) return layout_full
def meta_enter_message(python_input): """ Create the `Layout` for the 'Meta+Enter` message. """ def get_tokens(cli): return [(Token.AcceptMessage, ' [Meta+Enter] Execute ')] def extra_condition(cli): " Only show when... " b = cli.buffers[DEFAULT_BUFFER] return ( python_input.show_meta_enter_message and (not b.document.is_cursor_at_the_end or python_input.accept_input_on_enter is None) and b.is_multiline()) visible = ~IsDone() & HasFocus(DEFAULT_BUFFER) & Condition(extra_condition) return ConditionalContainer( content=Window(TokenListControl(get_tokens)), filter=visible)
def select_prompt(message, options, mark='>'): control = SelectControl(options) def get_formatted_text(): return control.select_option_text(mark) layout = Layout( HSplit([ Window( height=Dimension.exact(1), content=FormattedTextControl(lambda: message + '\n', show_cursor=False), ), Window(height=Dimension.exact(len(control.options)), content=FormattedTextControl(get_formatted_text)), ConditionalContainer(Window(control), filter=~IsDone()) ])) app = Application(layout=layout, key_bindings=control.key_bindings, full_screen=False) return app.run()
def __init__(self, search_buffer=None, vi_mode=False, text_if_not_searching='', forward_search_prompt='I-search: ', backward_search_prompt='I-search backward: ', ignore_case=False): assert search_buffer is None or isinstance(search_buffer, Buffer) if search_buffer is None: search_buffer = Buffer() @Condition def is_searching(): return self.control in get_app().layout.search_links def get_before_input(): if not is_searching(): return text_if_not_searching elif self.control.searcher_search_state.direction == SearchDirection.BACKWARD: return ('?' if vi_mode else backward_search_prompt) else: return ('/' if vi_mode else forward_search_prompt) self.search_buffer = search_buffer self.control = SearchBufferControl( buffer=search_buffer, input_processors=[ BeforeInput(get_before_input, style='class:search-toolbar.prompt') ], lexer=SimpleLexer(style='class:search-toolbar.text'), ignore_case=ignore_case) self.container = ConditionalContainer(content=Window( self.control, height=1, style='class:search-toolbar'), filter=is_searching)
def show_sidebar_button_info(python_input): """ Create `Layout` for the information in the right-bottom corner. (The right part of the status bar.) """ def toggle_sidebar(cli, mouse_event): " Click handler for the menu. " if mouse_event.event_type == MouseEventTypes.MOUSE_DOWN: python_input.show_sidebar = not python_input.show_sidebar else: return NotImplemented token = Token.Toolbar.Status version = sys.version_info tokens = [ (token.Key, '[F2]', toggle_sidebar), (token, ' Menu', toggle_sidebar), (token, ' - '), (token.PythonVersion, '%s %i.%i.%i' % (platform.python_implementation(), version[0], version[1], version[2])), (token, ' '), ] width = token_list_width(tokens) def get_tokens(cli): # Python version return tokens return ConditionalContainer( content=Window(TokenListControl(get_tokens, default_char=Char(token=token)), height=LayoutDimension.exact(1), width=LayoutDimension.exact(width)), filter=~IsDone() & RendererHeightIsKnown() & Condition(lambda cli: python_input.show_status_bar and not python_input.show_exit_confirmation))
def create_exit_confirmation( python_input: "PythonInput", style="class:exit-confirmation" ) -> Container: """ Create `Layout` for the exit message. """ def get_text_fragments() -> StyleAndTextTuples: # Show "Do you really want to exit?" return [ (style, "\n %s ([y]/n) " % python_input.exit_message), ("[SetCursorPosition]", ""), (style, " \n"), ] visible = ~is_done & Condition(lambda: python_input.show_exit_confirmation) return ConditionalContainer( content=Window( FormattedTextControl(get_text_fragments, focusable=True), style=style ), filter=visible, )
def __init__(self, prompt='Shell command: ', enable_global_bindings=True): self.prompt = prompt self.enable_global_bindings = to_filter(enable_global_bindings) self.system_buffer = Buffer(name=SYSTEM_BUFFER) self._bindings = self._build_key_bindings() self.buffer_control = BufferControl( buffer=self.system_buffer, lexer=SimpleLexer(style='class:system-toolbar.text'), input_processors=[ BeforeInput(lambda: self.prompt, style='class:system-toolbar') ], key_bindings=self._bindings) self.window = Window(self.buffer_control, height=1, style='class:system-toolbar') self.container = ConditionalContainer(content=self.window, filter=has_focus( self.system_buffer))
def __init__(self, show_position=False): def get_formatted_text(): buff = get_app().current_buffer if buff.validation_error: row, column = buff.document.translate_index_to_position( buff.validation_error.cursor_position) if show_position: text = '%s (line=%s column=%s)' % ( buff.validation_error.message, row + 1, column + 1) else: text = buff.validation_error.message return [('class:validation-toolbar', text)] else: return [] self.control = FormattedTextControl(get_formatted_text) self.container = ConditionalContainer(content=Window(self.control, height=1), filter=has_validation_error)
def __init__(self, app=None, show=False, height=Dimension(preferred=22), width=Dimension(preferred=25)): self.app = app self.show = show self.cursor_line = 0 self.lexer = DisassemblyLexer(self) self.buffer = Buffer(document=Document(), multiline=True) self.control = BufferControl(buffer=self.buffer, focusable=True, lexer=self.lexer, focus_on_click=True) self.window = Window(content=self.control, height=height, wrap_lines=False, scroll_offsets = ScrollOffsets(top=0)) self.info = InfoLine('[Disassembly]', width=240) self.container = ConditionalContainer( content=HSplit([self.info.get_ui(), self.window]), filter=Condition(lambda: self.show))
def __init__(self): self.container = ConditionalContainer(content=Window( _CompletionsToolbarControl(), height=1, style='class:completion-toolbar'), filter=has_completions)
def __init__( self, message: InquirerPyMessage, style: InquirerPyStyle = None, vi_mode: bool = False, default: InquirerPyDefault = 0, float_allowed: bool = False, max_allowed: Union[int, float] = None, min_allowed: Union[int, float] = None, decimal_symbol: str = ". ", replace_mode: bool = False, qmark: str = INQUIRERPY_QMARK_SEQUENCE, amark: str = "?", instruction: str = "", long_instruction: str = "", validate: InquirerPyValidate = None, invalid_message: str = "Invalid input", transformer: Callable[[str], Any] = None, filter: Callable[[str], Any] = None, keybindings: InquirerPyKeybindings = None, wrap_lines: bool = True, raise_keyboard_interrupt: bool = True, mandatory: bool = True, mandatory_message: str = "Mandatory prompt", session_result: InquirerPySessionResult = None, ) -> None: super().__init__( message=message, style=style, vi_mode=vi_mode, qmark=qmark, amark=amark, transformer=transformer, filter=filter, invalid_message=invalid_message, validate=validate, instruction=instruction, long_instruction=long_instruction, wrap_lines=wrap_lines, raise_keyboard_interrupt=raise_keyboard_interrupt, mandatory=mandatory, mandatory_message=mandatory_message, session_result=session_result, ) self._float = float_allowed self._is_float = Condition(lambda: self._float) self._max = max_allowed self._min = min_allowed self._value_error_message = "Remove any non-integer value" self._decimal_symbol = decimal_symbol self._whole_replace = False self._integral_replace = False self._replace_mode = replace_mode self._leading_zero_pattern = re.compile(r"^(0*)[0-9]+.*") self._sn_pattern = re.compile(r"^.*E-.*") self._no_default = False if default is None: default = 0 self._no_default = True if isinstance(default, Callable): default = cast(Callable, default)(session_result) if self._float: default = Decimal(str(float(cast(int, default)))) if self._float: if not isinstance(default, float) and not isinstance( default, Decimal): raise InvalidArgument( f"{type(self).__name__} argument 'default' should return type of float or Decimal" ) elif not isinstance(default, int): raise InvalidArgument( f"{type(self).__name__} argument 'default' should return type of int" ) self._default = default if keybindings is None: keybindings = {} self.kb_maps = { "down": [ { "key": "down" }, { "key": "c-n", "filter": ~self._is_vim_edit }, { "key": "j", "filter": self._is_vim_edit }, ], "up": [ { "key": "up" }, { "key": "c-p", "filter": ~self._is_vim_edit }, { "key": "k", "filter": self._is_vim_edit }, ], "left": [ { "key": "left" }, { "key": "c-b", "filter": ~self._is_vim_edit }, { "key": "h", "filter": self._is_vim_edit }, ], "right": [ { "key": "right" }, { "key": "c-f", "filter": ~self._is_vim_edit }, { "key": "l", "filter": self._is_vim_edit }, ], "dot": [{ "key": "." }], "focus": [{ "key": Keys.Tab }, { "key": "s-tab" }], "input": [{ "key": str(i) } for i in range(10)], "negative_toggle": [{ "key": "-" }], **keybindings, } self.kb_func_lookup = { "down": [{ "func": self._handle_down }], "up": [{ "func": self._handle_up }], "left": [{ "func": self._handle_left }], "right": [{ "func": self._handle_right }], "focus": [{ "func": self._handle_focus }], "input": [{ "func": self._handle_input }], "negative_toggle": [{ "func": self._handle_negative_toggle }], "dot": [{ "func": self._handle_dot }], } @self.register_kb(Keys.Any) def _(_): pass self._whole_width = 1 self._whole_buffer = Buffer( on_text_changed=self._on_whole_text_change, on_cursor_position_changed=self._on_cursor_position_change, ) self._integral_width = 1 self._integral_buffer = Buffer( on_text_changed=self._on_integral_text_change, on_cursor_position_changed=self._on_cursor_position_change, ) self._whole_window = Window( height=LayoutDimension.exact(1) if not self._wrap_lines else None, content=BufferControl( buffer=self._whole_buffer, lexer=SimpleLexer("class:input"), ), width=lambda: Dimension( min=self._whole_width, max=self._whole_width, preferred=self._whole_width, ), dont_extend_width=True, ) self._integral_window = Window( height=LayoutDimension.exact(1) if not self._wrap_lines else None, content=BufferControl( buffer=self._integral_buffer, lexer=SimpleLexer("class:input"), ), width=lambda: Dimension( min=self._integral_width, max=self._integral_width, preferred=self._integral_width, ), ) self._layout = Layout( HSplit([ VSplit( [ Window( height=LayoutDimension.exact(1) if not self._wrap_lines else None, content=FormattedTextControl( self._get_prompt_message), wrap_lines=self._wrap_lines, dont_extend_height=True, dont_extend_width=True, ), ConditionalContainer(self._whole_window, filter=~IsDone()), ConditionalContainer( Window( height=LayoutDimension.exact(1) if not self._wrap_lines else None, content=FormattedTextControl( [("", self._decimal_symbol)]), wrap_lines=self._wrap_lines, dont_extend_height=True, dont_extend_width=True, ), filter=self._is_float & ~IsDone(), ), ConditionalContainer( self._integral_window, filter=self._is_float & ~IsDone()), ], align=HorizontalAlign.LEFT, ), ConditionalContainer( Window(content=DummyControl()), filter=~IsDone() & self._is_displaying_long_instruction, ), ValidationWindow( invalid_message=self._get_error_message, filter=self._is_invalid & ~IsDone(), wrap_lines=self._wrap_lines, ), InstructionWindow( message=self._long_instruction, filter=~IsDone() & self._is_displaying_long_instruction, wrap_lines=self._wrap_lines, ), ]), ) self.focus = self._whole_window self._application = Application( layout=self._layout, style=self._style, key_bindings=self._kb, after_render=self._after_render, editing_mode=self._editing_mode, )
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', None) qmark = kwargs.pop('qmark', '?') # TODO style defaults on detail level style = kwargs.pop('style', default_style) ic = InquirerControl(choices, default=default) def get_prompt_tokens(cli): tokens = [] tokens.append((Token.QuestionMark, qmark)) tokens.append((Token.Question, ' %s ' % message)) if ic.answered: tokens.append((Token.Answer, ' ' + ic.get_selection()[0])) else: tokens.append((Token.Instruction, ' (Use arrow keys)')) return tokens # assemble layout layout = HSplit([ Window(height=D.exact(1), content=TokenListControl(get_prompt_tokens)), ConditionalContainer(Window(ic), 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][2]: _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][2]: _prev() @manager.registry.add_binding(Keys.Enter, eager=True) def set_answer(event): ic.answered = True event.cli.set_return_value(ic.get_selection()[1]) return Application(layout=layout, key_bindings_registry=manager.registry, mouse_support=True, style=style)
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())
def __init__( self, message: InquirerPyMessage, choices: InquirerPyListChoices, default: InquirerPyDefault = None, style: InquirerPyStyle = None, vi_mode: bool = False, qmark: str = "?", amark: str = "?", pointer: str = INQUIRERPY_POINTER_SEQUENCE, instruction: str = "", long_instruction: str = "", transformer: Callable[[Any], Any] = None, filter: Callable[[Any], Any] = None, height: Union[int, str] = None, max_height: Union[int, str] = None, multiselect: bool = False, marker: str = INQUIRERPY_POINTER_SEQUENCE, marker_pl: str = " ", border: bool = False, validate: InquirerPyValidate = None, invalid_message: str = "Invalid input", keybindings: Dict[str, List[Dict[str, Any]]] = None, show_cursor: bool = True, cycle: bool = True, wrap_lines: bool = True, raise_keyboard_interrupt: bool = True, mandatory: bool = True, mandatory_message: str = "Mandatory prompt", session_result: InquirerPySessionResult = None, ) -> None: if not hasattr(self, "_content_control"): self.content_control = InquirerPyListControl( choices=choices, default=default, pointer=pointer, marker=marker, session_result=session_result, multiselect=multiselect, marker_pl=marker_pl, ) super().__init__( message=message, style=style, border=border, vi_mode=vi_mode, qmark=qmark, amark=amark, instruction=instruction, long_instruction=long_instruction, transformer=transformer, filter=filter, validate=validate, invalid_message=invalid_message, multiselect=multiselect, keybindings=keybindings, cycle=cycle, wrap_lines=wrap_lines, raise_keyboard_interrupt=raise_keyboard_interrupt, mandatory=mandatory, mandatory_message=mandatory_message, session_result=session_result, ) self._show_cursor = show_cursor self._dimmension_height, self._dimmension_max_height = calculate_height( height, max_height, height_offset=self.height_offset) main_content_window = Window( content=self.content_control, height=Dimension( max=self._dimmension_max_height, preferred=self._dimmension_height, ), dont_extend_height=True, ) if self._border: main_content_window = Frame(main_content_window) self._layout = FloatContainer( content=HSplit([ MessageWindow( message=self._get_prompt_message_with_cursor if self._show_cursor else self._get_prompt_message, filter=True, wrap_lines=self._wrap_lines, show_cursor=self._show_cursor, ), ConditionalContainer(main_content_window, filter=~IsDone()), ConditionalContainer( Window(content=DummyControl()), filter=~IsDone() & self._is_displaying_long_instruction, ), InstructionWindow( message=self._long_instruction, filter=~IsDone() & self._is_displaying_long_instruction, wrap_lines=self._wrap_lines, ), ]), floats=[ ValidationFloat( invalid_message=self._get_error_message, filter=self._is_invalid & ~IsDone(), wrap_lines=self._wrap_lines, left=0, bottom=self._validation_window_bottom_offset, ), ], ) self.application = Application( layout=Layout(self._layout), style=self._style, key_bindings=self._kb, after_render=self._after_render, )
height=1), # Display each row HSplit([ VSplit([ Window(FormattedTextControl(HTML(str(row))), width=2), *[ Window(FormattedTextControl(get_cell(cell)), width=10) for cell in controller.view.get_visible_cells(row, row=True) ] ]) for row in controller.view.visible_rows() ], height=controller.view.rows_to_show), HorizontalLine(), Window(content=FormattedTextControl( controller.view.get_current_cell_formula), height=1), ConditionalContainer(content=cell_input_dialog, filter=Condition(lambda: controller.input_mode)) ]) root_container = HSplit([ # Header for the columns name VSplit([ Window(FormattedTextControl(), width=10), *[ Window(FormattedTextControl(get_column_name(column)), width=10) for column in controller.view.visible_columns() ] ], height=1), # Display each row HSplit( [ # For each cell in the row, display it's content
def status_bar(python_input: "PythonInput") -> Container: """ Create the `Layout` for the status bar. """ TB = "class:status-toolbar" @if_mousedown def toggle_paste_mode(mouse_event: MouseEvent) -> None: python_input.paste_mode = not python_input.paste_mode @if_mousedown def enter_history(mouse_event: MouseEvent) -> None: python_input.enter_history() def get_text_fragments() -> StyleAndTextTuples: python_buffer = python_input.default_buffer result: StyleAndTextTuples = [] append = result.append append((TB, " ")) result.extend(get_inputmode_fragments(python_input)) append((TB, " ")) # Position in history. append(( TB, "%i/%i " % (python_buffer.working_index + 1, len(python_buffer._working_lines)), )) # Shortcuts. app = get_app() if (not python_input.vi_mode and app.current_buffer == python_input.search_buffer): append((TB, "[Ctrl-G] Cancel search [Enter] Go to this position.")) elif bool(app.current_buffer.selection_state ) and not python_input.vi_mode: # Emacs cut/copy keys. append( (TB, "[Ctrl-W] Cut [Meta-W] Copy [Ctrl-Y] Paste [Ctrl-G] Cancel")) else: result.extend([ (TB + " class:status-toolbar.key", "[F3]", enter_history), (TB, " History ", enter_history), (TB + " class:status-toolbar.key", "[F6]", toggle_paste_mode), (TB, " ", toggle_paste_mode), ]) if python_input.paste_mode: append((TB + " class:paste-mode-on", "Paste mode (on)", toggle_paste_mode)) else: append((TB, "Paste mode", toggle_paste_mode)) return result return ConditionalContainer( content=Window(content=FormattedTextControl(get_text_fragments), style=TB), filter=~is_done & renderer_height_is_known & Condition(lambda: python_input.show_status_bar and not python_input. show_exit_confirmation), )
def question(message, **kwargs): # TODO extract common parts for list, checkbox, rawlist, expand if not 'choices' in kwargs: raise PromptParameterException('choices') # this does not implement default, use checked... # TODO # if 'default' in kwargs: # raise ValueError('rawlist does not implement \'default\' ' # 'use \'checked\':True\' in choice!') qmark = kwargs.pop('qmark', '?') choices = kwargs.pop('choices', None) if len(choices) > 9: raise ValueError('rawlist supports only a maximum of 9 choices!') # TODO style defaults on detail level style = kwargs.pop('style', default_style) ic = InquirerControl(choices) def get_prompt_tokens(): tokens = [] tokens.append(('class:questionmark', qmark)) tokens.append(('class:question', ' %s ' % message)) if ic.answered: tokens.append(('class:answer', ' %s' % ic.get_selected_value())) return tokens # assemble layout layout = HSplit([ Window(height=D.exact(1), content=FormattedTextControl(get_prompt_tokens) ), ConditionalContainer( Window(ic), filter=~IsDone() ) ]) # key bindings kb = KeyBindings() @kb.add('c-q', eager=True) @kb.add('c-c', eager=True) def _(event): raise KeyboardInterrupt() # add key bindings for choices for i, c in enumerate(ic.choices): if not isinstance(c, Separator): def _reg_binding(i, keys): # trick out late evaluation with a "function factory": # http://stackoverflow.com/questions/3431676/creating-functions-in-a-loop @kb.add(keys, eager=True) def select_choice(event): ic.pointer_index = i _reg_binding(i, '%d' % c[0]) @kb.add('enter', eager=True) def set_answer(event): ic.answered = True event.app.exit(result=ic.get_selected_value()) return Application( layout=Layout(layout), key_bindings=kb, mouse_support=True, style=style )
def generate_layout(input_field: TextArea, output_field: TextArea, log_field: TextArea, right_pane_toggle: Button, log_field_button: Button, search_field: SearchToolbar, timer: TextArea, process_monitor: TextArea, trade_monitor: TextArea, command_tabs: Dict[str, CommandTab], ): components = {} components["item_top_version"] = Window(FormattedTextControl(get_version), style="class:header") components["item_top_active"] = Window(FormattedTextControl(get_active_strategy), style="class:header") components["item_top_file"] = Window(FormattedTextControl(get_strategy_file), style="class:header") components["item_top_gateway"] = Window(FormattedTextControl(get_gateway_status), style="class:header") components["item_top_toggle"] = right_pane_toggle components["pane_top"] = VSplit([components["item_top_version"], components["item_top_active"], components["item_top_file"], components["item_top_gateway"], components["item_top_toggle"]], height=1) components["pane_bottom"] = VSplit([trade_monitor, process_monitor, timer], height=1) output_pane = Box(body=output_field, padding=0, padding_left=2, style="class:output-field") input_pane = Box(body=input_field, padding=0, padding_left=2, padding_top=1, style="class:input-field") components["pane_left"] = HSplit([output_pane, input_pane], width=Dimension(weight=1)) if all(not t.is_selected for t in command_tabs.values()): log_field_button.window.style = "class:tab_button.focused" else: log_field_button.window.style = "class:tab_button" tab_buttons = [log_field_button] for tab in sorted(command_tabs.values(), key=lambda x: x.tab_index): if tab.button is not None: if tab.is_selected: tab.button.window.style = "class:tab_button.focused" else: tab.button.window.style = "class:tab_button" tab.close_button.window.style = tab.button.window.style tab_buttons.append(VSplit([tab.button, tab.close_button])) pane_right_field = log_field focused_right_field = [tab.output_field for tab in command_tabs.values() if tab.is_selected] if focused_right_field: pane_right_field = focused_right_field[0] components["pane_right_top"] = VSplit(tab_buttons, height=1, style="class:log-field", padding_char=" ", padding=2) components["pane_right"] = ConditionalContainer( Box(body=HSplit([components["pane_right_top"], pane_right_field, search_field], width=Dimension(weight=1)), padding=0, padding_left=2, style="class:log-field"), filter=True ) components["hint_menus"] = [Float(xcursor=True, ycursor=True, transparent=True, content=CompletionsMenu(max_height=16, scroll_offset=1))] root_container = HSplit([ components["pane_top"], VSplit( [FloatContainer(components["pane_left"], components["hint_menus"]), components["pane_right"]]), components["pane_bottom"], ]) return Layout(root_container, focused_element=input_field), components
def signature_toolbar(python_input): """ Return the `Layout` for the signature. """ def get_text_fragments(): result = [] append = result.append Signature = 'class:signature-toolbar' if python_input.signatures: sig = python_input.signatures[0] # Always take the first one. append((Signature, ' ')) try: append((Signature, sig.full_name)) except IndexError: # Workaround for #37: https://github.com/jonathanslenders/python-prompt-toolkit/issues/37 # See also: https://github.com/davidhalter/jedi/issues/490 return [] append((Signature + ',operator', '(')) try: enumerated_params = enumerate(sig.params) except AttributeError: # Workaround for #136: https://github.com/jonathanslenders/ptpython/issues/136 # AttributeError: 'Lambda' object has no attribute 'get_subscope_by_name' return [] for i, p in enumerated_params: # Workaround for #47: 'p' is None when we hit the '*' in the signature. # and sig has no 'index' attribute. # See: https://github.com/jonathanslenders/ptpython/issues/47 # https://github.com/davidhalter/jedi/issues/598 description = (p.description if p else '*') #or '*' sig_index = getattr(sig, 'index', 0) if i == sig_index: # Note: we use `_Param.description` instead of # `_Param.name`, that way we also get the '*' before args. append((Signature + ',current-name', str(description))) else: append((Signature, str(description))) append((Signature + ',operator', ', ')) if sig.params: # Pop last comma result.pop() append((Signature + ',operator', ')')) append((Signature, ' ')) return result return ConditionalContainer( content=Window(FormattedTextControl(get_text_fragments), height=Dimension.exact(1)), filter= # Show only when there is a signature HasSignature(python_input) & # And there are no completions to be shown. (would cover signature pop-up.) ~(has_completions & (show_completions_menu(python_input) | show_multi_column_completions_menu(python_input))) # Signature needs to be shown. & ShowSignature(python_input) & # Not done yet. ~is_done)
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)
def create_layout(python_input, history_mapping): """ Create and return a `Container` instance for the history application. """ processors = [ HighlightSearchProcessor(preview_search=True), HighlightSelectionProcessor() ] help_window = create_popup_window( title='History Help', body=Window(content=BufferControl(buffer_name=HELP_BUFFER, default_char=Char(token=Token), lexer=PygmentsLexer(RstLexer), input_processors=processors), right_margins=[ScrollbarMargin()], scroll_offsets=ScrollOffsets(top=2, bottom=2))) return HSplit([ # Top title bar. TokenListToolbar(get_tokens=_get_top_toolbar_tokens, align_center=True, default_char=Char(' ', Token.Toolbar.Status)), FloatContainer( content=VSplit([ # Left side: history. Window(content=BufferControl(buffer_name=HISTORY_BUFFER, lexer=PygmentsLexer(PythonLexer), input_processors=processors), wrap_lines=False, left_margins=[HistoryMargin(history_mapping)], scroll_offsets=ScrollOffsets(top=2, bottom=2)), # Separator. Window(width=D.exact(1), content=FillControl(BORDER.LIGHT_VERTICAL, token=Token.Separator)), # Right side: result. Window( content=BufferControl(buffer_name=DEFAULT_BUFFER, input_processors=processors + [GrayExistingText(history_mapping)], lexer=PygmentsLexer(PythonLexer)), wrap_lines=False, left_margins=[ResultMargin(history_mapping)], scroll_offsets=ScrollOffsets(top=2, bottom=2)), ]), floats=[ # Help text as a float. Float( width=60, top=3, bottom=2, content=ConditionalContainer( # (We use InFocusStack, because it's possible to search # through the help text as well, and at that point the search # buffer has the focus.) content=help_window, filter=InFocusStack(HELP_BUFFER))), ]), # Bottom toolbars. ArgToolbar(), SearchToolbar(), TokenListToolbar(get_tokens=partial(_get_bottom_toolbar_tokens, python_input=python_input), default_char=Char(' ', Token.Toolbar.Status)), ])
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) ic = InquirerControl(choices, pointer_index) qmark = kwargs.pop('qmark', '?') def get_prompt_tokens(cli): tokens = [] tokens.append((Token.QuestionMark, qmark)) 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][1] # value 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[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 @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[ 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 = [] @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) or \ ic.choices[ic.pointer_index][2]: _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) or \ ic.choices[ic.pointer_index][2]: _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)
def __init__(self, command=['/bin/bash'], before_exec_func=None, bell_func=None, style='', width=None, height=None, done_callback=None): self.terminal_control = _TerminalControl( command=command, before_exec_func=before_exec_func, bell_func=bell_func, done_callback=done_callback) self.terminal_window = _Window(terminal_control=self.terminal_control, content=self.terminal_control, wrap_lines=False) # Key bindigns for copy buffer. kb = KeyBindings() @kb.add('c-c') def _(event): self.exit_copy_mode() @kb.add('space') def _(event): " Reset selection. " event.current_buffer.start_selection() @kb.add('enter', filter=has_selection) def _(event): " Reset selection. " data = event.current_buffer.copy_selection() event.app.clipboard.set_data(data) self.search_toolbar = SearchToolbar( forward_search_prompt='Search down: ', backward_search_prompt='Search up: ') self.copy_buffer = Buffer(read_only=True) self.copy_buffer_control = BufferControl( buffer=self.copy_buffer, search_buffer_control=self.search_toolbar.control, include_default_input_processors=False, input_processors=[ _UseStyledTextProcessor(self), HighlightSelectionProcessor(), HighlightSearchProcessor(), HighlightIncrementalSearchProcessor(), ], preview_search= True, # XXX: not sure why we need twice preview_search. key_bindings=kb) self.copy_window = Window(content=self.copy_buffer_control, wrap_lines=False) self.is_copying = False self.styled_copy_lines = [ ] # List of lists of (style, text) tuples, for each line. @Condition def is_copying(): return self.is_copying self.container = FloatContainer( content=HSplit( [ # Either show terminal window or copy buffer. VSplit([ # XXX: this nested VSplit should not have been necessary, # but the ConditionalContainer which width can become # zero will collapse the other elements. ConditionalContainer(self.terminal_window, filter=~is_copying), ConditionalContainer(self.copy_window, filter=is_copying), ]), ConditionalContainer(self.search_toolbar, filter=is_copying), ], style=style, width=width, height=height), floats=[ Float(top=0, right=0, height=1, content=ConditionalContainer(Window( content=FormattedTextControl( text=self._copy_position_formatted_text), style='class:copy-mode-cursor-position'), filter=is_copying)) ])
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', None) qmark = kwargs.pop('qmark', '?') # TODO style defaults on detail level style = kwargs.pop('style', default_style) ic = InquirerControl(choices, default=default) def get_prompt_tokens(): tokens = [] tokens.append(('class:questionmark', qmark)) tokens.append(('class:question', ' %s ' % message)) if ic.answered: tokens.append(('class:answer', ' ' + ic.get_selection()[0])) else: tokens.append(('class:instruction', '')) return tokens # assemble layout layout = HSplit([ Window(height=D.exact(1), content=FormattedTextControl(get_prompt_tokens)), ConditionalContainer(Window(ic), 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('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][2]: _next() @kb.add('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][2]: _prev() @kb.add('enter', eager=True) def set_answer(event): ic.answered = True event.app.exit(result="Select Task- %s" % ic.choices[ic.selected_option_index][0]) @kb.add('c-a', eager=True) def set_answer(event): ic.answered = True event.app.exit(result="Add Task") @kb.add('c-w', eager=True) def set_answer(event): ic.answered = True event.app.exit(result="Delete Task - %s" % ic.choices[ic.selected_option_index][0]) @kb.add('c-h', eager=True) def set_answer(event): ic.answered = True event.app.exit(result="Precedent Task - %s" % ic.choices[ic.selected_option_index][0]) return Application(layout=Layout(layout), key_bindings=kb, mouse_support=False, style=style)
def create_layout(python_input, lexer=PythonLexer, extra_body=None, extra_toolbars=None, extra_buffer_processors=None, input_buffer_height=None): D = Dimension extra_body = [extra_body] if extra_body else [] extra_toolbars = extra_toolbars or [] extra_buffer_processors = extra_buffer_processors or [] input_buffer_height = input_buffer_height or D(min=6) search_toolbar = SearchToolbar(python_input.search_buffer) def create_python_input_window(): def menu_position(): """ When there is no autocompletion menu to be shown, and we have a signature, set the pop-up position at `bracket_start`. """ b = python_input.default_buffer if b.complete_state is None and python_input.signatures: row, col = python_input.signatures[0].bracket_start index = b.document.translate_row_col_to_index(row - 1, col) return index return Window( BufferControl( buffer=python_input.default_buffer, search_buffer_control=search_toolbar.control, lexer=lexer, include_default_input_processors=False, input_processors=[ ConditionalProcessor( processor=HighlightIncrementalSearchProcessor(), filter=has_focus(SEARCH_BUFFER) | has_focus(search_toolbar.control), ), HighlightSelectionProcessor(), DisplayMultipleCursors(), # Show matching parentheses, but only while editing. ConditionalProcessor( processor=HighlightMatchingBracketProcessor( chars='[](){}'), filter=has_focus(DEFAULT_BUFFER) & ~is_done & Condition(lambda: python_input. highlight_matching_parenthesis)), ConditionalProcessor(processor=AppendAutoSuggestion(), filter=~is_done) ] + extra_buffer_processors, menu_position=menu_position, # Make sure that we always see the result of an reverse-i-search: preview_search=True, ), left_margins=[PythonPromptMargin(python_input)], # Scroll offsets. The 1 at the bottom is important to make sure the # cursor is never below the "Press [Meta+Enter]" message which is a float. scroll_offsets=ScrollOffsets(bottom=1, left=4, right=4), # As long as we're editing, prefer a minimal height of 6. height=(lambda: (None if get_app().is_done or python_input. show_exit_confirmation else input_buffer_height)), wrap_lines=Condition(lambda: python_input.wrap_lines), ) root_container = HSplit([ VSplit([ HSplit([ FloatContainer( content=HSplit([create_python_input_window()] + extra_body), floats=[ Float(xcursor=True, ycursor=True, content=ConditionalContainer( content=CompletionsMenu(scroll_offset=( lambda: python_input. completion_menu_scroll_offset), max_height=12), filter=show_completions_menu(python_input))), Float(xcursor=True, ycursor=True, content=ConditionalContainer( content=MultiColumnCompletionsMenu(), filter=show_multi_column_completions_menu( python_input))), Float(xcursor=True, ycursor=True, content=signature_toolbar(python_input)), Float(left=2, bottom=1, content=exit_confirmation(python_input)), Float(bottom=0, right=0, height=1, content=meta_enter_message(python_input), hide_when_covering_content=True), Float(bottom=1, left=1, right=0, content=python_sidebar_help(python_input)), ]), ArgToolbar(), search_toolbar, SystemToolbar(), ValidationToolbar(), ConditionalContainer(content=CompletionsToolbar(), filter=show_completions_toolbar( python_input)), # Docstring region. ConditionalContainer(content=Window( height=D.exact(1), char='\u2500', style='class:separator'), filter=HasSignature(python_input) & ShowDocstring(python_input) & ~is_done), ConditionalContainer( content=Window( BufferControl( buffer=python_input.docstring_buffer, lexer=SimpleLexer(style='class:docstring'), #lexer=PythonLexer, ), height=D(max=12)), filter=HasSignature(python_input) & ShowDocstring(python_input) & ~is_done), ]), ConditionalContainer(content=HSplit([ python_sidebar(python_input), Window(style='class:sidebar,separator', height=1), python_sidebar_navigation(python_input), ]), filter=ShowSidebar(python_input) & ~is_done) ]), ] + extra_toolbars + [ VSplit([ status_bar(python_input), show_sidebar_button_info(python_input), ]) ]) return Layout(root_container)
def __init__( self, body: AnyContainer, title: AnyFormattedText = "", style: str = "", width: AnyDimension = None, height: AnyDimension = None, key_bindings: Optional[KeyBindings] = None, modal: bool = False, ) -> None: self.title = title self.body = body fill = partial(Window, style="class:frame.border") style = "class:frame " + style top_row_with_title = VSplit( [ fill(width=1, height=1, char="├"), fill(char=Border.HORIZONTAL), # Notice: we use `Template` here, because `self.title` can be an # `HTML` object for instance. Label( lambda: Template(" {} ").format(self.title), style="class:frame.label", dont_extend_width=True, ), fill(char=Border.HORIZONTAL), fill(width=1, height=1, char="┤"), ], height=1, ) top_row_without_title = VSplit( [ fill(width=1, height=1, char=Border.TOP_LEFT), fill(char=Border.HORIZONTAL), fill(width=1, height=1, char=Border.TOP_RIGHT), ], height=1, ) @Condition def has_title() -> bool: return bool(self.title) self.container = HSplit( [ ConditionalContainer(content=top_row_with_title, filter=has_title), ConditionalContainer(content=top_row_without_title, filter=~has_title), VSplit( [ fill(width=1, char=Border.VERTICAL), DynamicContainer(lambda: self.body), fill(width=1, char=Border.VERTICAL), # Padding is required to make sure that if the content is # too small, the right frame border is still aligned. ], padding=0, ), ], width=width, height=height, style=style, key_bindings=key_bindings, modal=modal, )
def _create_layout(self): """ Create `Layout` for this prompt. """ dyncond = self._dyncond # Create functions that will dynamically split the prompt. (If we have # a multiline prompt.) has_before_fragments, get_prompt_text_1, get_prompt_text_2 = \ _split_multiline_prompt(self._get_prompt) default_buffer = self.default_buffer search_buffer = self.search_buffer # Create processors list. all_input_processors = [ HighlightIncrementalSearchProcessor(), HighlightSelectionProcessor(), ConditionalProcessor(AppendAutoSuggestion(), has_focus(default_buffer) & ~is_done), ConditionalProcessor(PasswordProcessor(), dyncond('is_password')), DisplayMultipleCursors(), # Users can insert processors here. DynamicProcessor( lambda: merge_processors(self.input_processors or [])), # For single line mode, show the prompt before the input. ConditionalProcessor( merge_processors([ BeforeInput(get_prompt_text_2), ShowArg(), ]), ~dyncond('multiline')) ] # Create bottom toolbars. bottom_toolbar = ConditionalContainer( Window(FormattedTextControl(lambda: self.bottom_toolbar, style='class:bottom-toolbar.text'), style='class:bottom-toolbar', dont_extend_height=True, height=Dimension(min=1)), filter=~is_done & renderer_height_is_known & Condition(lambda: self.bottom_toolbar is not None)) search_toolbar = SearchToolbar( search_buffer, ignore_case=dyncond('search_ignore_case')) search_buffer_control = SearchBufferControl( buffer=search_buffer, input_processors=[ ReverseSearchProcessor(), ShowArg(), ], ignore_case=dyncond('search_ignore_case')) system_toolbar = SystemToolbar( enable_global_bindings=dyncond('enable_system_prompt')) def get_search_buffer_control(): " Return the UIControl to be focused when searching start. " if _true(self.multiline): return search_toolbar.control else: return search_buffer_control default_buffer_control = BufferControl( buffer=default_buffer, search_buffer_control=get_search_buffer_control, input_processors=all_input_processors, include_default_input_processors=False, lexer=DynamicLexer(lambda: self.lexer), preview_search=True) default_buffer_window = Window( default_buffer_control, height=self._get_default_buffer_control_height, left_margins=[ # In multiline mode, use the window margin to display # the prompt and continuation fragments. ConditionalMargin( PromptMargin(get_prompt_text_2, self._get_continuation), filter=dyncond('multiline'), ) ], wrap_lines=dyncond('wrap_lines')) @Condition def multi_column_complete_style(): return self.complete_style == CompleteStyle.MULTI_COLUMN # Build the layout. layout = HSplit([ # The main input, with completion menus floating on top of it. FloatContainer( HSplit([ ConditionalContainer( Window(FormattedTextControl(get_prompt_text_1), dont_extend_height=True), Condition(has_before_fragments)), ConditionalContainer( default_buffer_window, Condition(lambda: get_app().layout.current_control != search_buffer_control), ), ConditionalContainer( Window(search_buffer_control), Condition(lambda: get_app().layout.current_control == search_buffer_control), ), ]), [ # Completion menus. Float(xcursor=True, ycursor=True, content=CompletionsMenu( max_height=16, scroll_offset=1, extra_filter=has_focus(default_buffer) & ~multi_column_complete_style)), Float(xcursor=True, ycursor=True, content=MultiColumnCompletionsMenu( show_meta=True, extra_filter=has_focus(default_buffer) & multi_column_complete_style)), # The right prompt. Float(right=0, top=0, hide_when_covering_content=True, content=_RPrompt(lambda: self.rprompt)), ]), ConditionalContainer(ValidationToolbar(), filter=~is_done), ConditionalContainer(system_toolbar, dyncond('enable_system_prompt') & ~is_done), # In multiline mode, we use two toolbars for 'arg' and 'search'. ConditionalContainer( Window(FormattedTextControl(self._get_arg_text), height=1), dyncond('multiline') & has_arg), ConditionalContainer(search_toolbar, dyncond('multiline') & ~is_done), bottom_toolbar, ]) return Layout(layout, default_buffer_window)
]), buttons=[ok_button], width=D(preferred=80), modal=True) def __pt_container__(self): return self.dialog body = HSplit([ text_field, search_toolbar, ConditionalContainer( content=VSplit([ Window(FormattedTextControl(get_statusbar_text), style='class:status'), Window(FormattedTextControl(get_statusbar_right_text), style='class:status.right', width=9, align=WindowAlign.RIGHT), ], height=1), filter=Condition(lambda: ApplicationState.show_status_bar)), ]) # Global key bindings. bindings = KeyBindings() @bindings.add('c-c') def _(event): " Focus menu. " event.app.layout.focus(root_container.window)