def __init__(self, text: str, handler: Optional[Callable[[], None]] = None, width: int = 12) -> None: self.text = text self.handler = handler self.width = width self.control = FormattedTextControl( self._get_text_fragments, key_bindings=self._get_key_bindings(), focusable=True) def get_style() -> str: if get_app().layout.has_focus(self): return 'class:button.focused' else: return 'class:button' self.window = Window(self.control, align=WindowAlign.CENTER, height=1, width=width, style=get_style, dont_extend_width=True, dont_extend_height=True)
def __init__(self, text: AnyFormattedText, style: str = '', **kw) -> None: # Note: The style needs to be applied to the toolbar as a whole, not # just the `FormattedTextControl`. super().__init__(FormattedTextControl(text, **kw), style=style, dont_extend_height=True, height=Dimension(min=1))
def __init__(self, text: AnyFormattedText, style: str = '', width: AnyDimension = None, dont_extend_height: bool = True, dont_extend_width: bool = False) -> None: self.text = text def get_width() -> AnyDimension: if width is None: text_fragments = to_formatted_text(self.text) text = fragment_list_to_text(text_fragments) if text: longest_line = max( get_cwidth(line) for line in text.splitlines()) else: return D(preferred=0) return D(preferred=longest_line) else: return width self.formatted_text_control = FormattedTextControl( text=lambda: self.text) self.window = Window(content=self.formatted_text_control, width=get_width, style='class:label ' + style, dont_extend_height=dont_extend_height, dont_extend_width=dont_extend_width)
def __init__(self, values: Sequence[Tuple[_T, AnyFormattedText]]) -> None: assert len(values) > 0 self.values = values # current_values will be used in multiple_selection, # current_value will be used otherwise. self.current_values: List[_T] = [] self.current_value: _T = values[0][0] self._selected_index = 0 # Key bindings. kb = KeyBindings() @kb.add('up') def _(event: E) -> None: self._selected_index = max(0, self._selected_index - 1) @kb.add('down') def _(event: E) -> None: self._selected_index = min( len(self.values) - 1, self._selected_index + 1) @kb.add('pageup') def _(event: E) -> None: w = event.app.layout.current_window self._selected_index = max( 0, self._selected_index - len(w.render_info.displayed_lines)) @kb.add('pagedown') def _(event: E) -> None: w = event.app.layout.current_window self._selected_index = min( len(self.values) - 1, self._selected_index + len(w.render_info.displayed_lines)) @kb.add('enter') @kb.add(' ') def _(event: E) -> None: self._handle_enter() @kb.add(Keys.Any) def _(event: E) -> None: # We first check values after the selected value, then all values. for value in self.values[self._selected_index + 1:] + self.values: if value[1].startswith(event.data): self._selected_index = self.values.index(value) return # Control and window. self.control = FormattedTextControl(self._get_text_fragments, key_bindings=kb, focusable=True) self.window = Window(content=self.control, style=self.container_style, right_margins=[ ScrollbarMargin(display_arrows=True), ], dont_extend_height=True)
def __init__(self) -> None: def get_formatted_text() -> StyleAndTextTuples: arg = get_app().key_processor.arg or '' if arg == '-': arg = '-1' return [ ('class:arg-toolbar', 'Repeat: '), ('class:arg-toolbar.text', arg), ] self.window = Window(FormattedTextControl(get_formatted_text), height=1) self.container = ConditionalContainer(content=self.window, filter=has_arg)
def __init__(self, show_position: bool = False) -> None: def get_formatted_text() -> StyleAndTextTuples: 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)
risus aliquam sit amet. Pellentesque blandit scelerisque felis, faucibus consequat ante. Curabitur tempor tortor a imperdiet tincidunt. Nam sed justo sit amet odio bibendum congue. Quisque varius ligula nec ligula gravida, sed convallis augue faucibus. Nunc ornare pharetra bibendum. Praesent blandit ex quis sodales maximus. """ * 100).split()) # 1. The layout left_text = "Floating\nleft" right_text = "Floating\nright" top_text = "Floating\ntop" bottom_text = "Floating\nbottom" center_text = "Floating\ncenter" quit_text = "Press 'q' to quit." body = FloatContainer( content=Window(FormattedTextControl(LIPSUM), wrap_lines=True), floats=[ # Important note: Wrapping the floating objects in a 'Frame' is # only required for drawing the border around the # floating text. We do it here to make the layout more # obvious. # Left float. Float(Frame(Window(FormattedTextControl(left_text), width=10, height=2), style='bg:#44ffff #ffffff'), left=0), # Right float. Float(Frame(Window(FormattedTextControl(right_text),
search_field = SearchToolbar( text_if_not_searching=[('class:not-searching', "Press '/' to start searching.")]) text_area = TextArea(text=text, read_only=True, scrollbar=True, line_numbers=True, search_field=search_field, lexer=PygmentsLexer(PythonLexer)) root_container = HSplit([ # The top toolbar. Window(content=FormattedTextControl(get_statusbar_text), height=D.exact(1), style='class:status'), # The main content. text_area, search_field, ]) # Key bindings. bindings = KeyBindings() @bindings.add('c-c') @bindings.add('q') def _(event):
placerat massa tempor elementum. Sed tristique mauris ac suscipit euismod. Ut tempus vehicula augue non venenatis. Mauris aliquam velit turpis, nec congue risus aliquam sit amet. Pellentesque blandit scelerisque felis, faucibus consequat ante. Curabitur tempor tortor a imperdiet tincidunt. Nam sed justo sit amet odio bibendum congue. Quisque varius ligula nec ligula gravida, sed convallis augue faucibus. Nunc ornare pharetra bibendum. Praesent blandit ex quis sodales maximus.""" # 1. The layout left_text = '\nLeft aligned text. - (Press "q" to quit)\n\n' + LIPSUM center_text = 'Centered text.\n\n' + LIPSUM right_text = 'Right aligned text.\n\n' + LIPSUM body = HSplit([ Window(FormattedTextControl(left_text), align=WindowAlign.LEFT), Window(height=1, char='-'), Window(FormattedTextControl(center_text), align=WindowAlign.CENTER), Window(height=1, char='-'), Window(FormattedTextControl(right_text), align=WindowAlign.RIGHT), ]) # 2. Key bindings kb = KeyBindings() @kb.add('q') def _(event): " Quit application. " event.app.exit()
dignissim placerat. In vel dictum ex, vulputate accumsan mi. Donec ut quam placerat massa tempor elementum. Sed tristique mauris ac suscipit euismod. Ut tempus vehicula augue non venenatis. Mauris aliquam velit turpis, nec congue risus aliquam sit amet. Pellentesque blandit scelerisque felis, faucibus consequat ante. Curabitur tempor tortor a imperdiet tincidunt. Nam sed justo sit amet odio bibendum congue. Quisque varius ligula nec ligula gravida, sed convallis augue faucibus. Nunc ornare pharetra bibendum. Praesent blandit ex quis sodales maximus. """ left_top = Window(BufferControl(Buffer(document=Document(LIPSUM)))) left_bottom = Window(BufferControl(Buffer(document=Document(LIPSUM)))) right_top = Window(BufferControl(Buffer(document=Document(LIPSUM)))) right_bottom = Window(BufferControl(Buffer(document=Document(LIPSUM)))) body = HSplit([ Window(FormattedTextControl(top_text), height=2, style='reverse'), Window(height=1, char='-'), # Horizontal line in the middle. VSplit([left_top, Window(width=1, char='|'), right_top]), Window(height=1, char='-'), # Horizontal line in the middle. VSplit([left_bottom, Window(width=1, char='|'), right_bottom]), ]) # 2. Key bindings kb = KeyBindings() @kb.add('q') def _(event): " Quit application. " event.app.exit()
# Ctrl-R.) It would be really annoying if the search key bindings are handled, # but the user doesn't see any feedback. We will add the search toolbar to the # bottom by using an HSplit. def get_titlebar_text(): return [ ('class:title', ' Hello world '), ('class:title', ' (Press [Ctrl-Q] to quit.)'), ] root_container = HSplit([ # The titlebar. Window(height=1, content=FormattedTextControl(get_titlebar_text), align=WindowAlign.CENTER), # Horizontal separator. Window(height=1, char='-', style='class:line'), # The 'body', like defined above. body, ]) # 2. Adding key bindings # -------------------- # As a demonstration, we will add just a ControlQ key binding to exit the # application. Key bindings are registered in a
#!/usr/bin/env python """ Vertical split example. """ from prompt_toolkit_dev.application import Application from prompt_toolkit_dev.key_binding import KeyBindings from prompt_toolkit_dev.layout.containers import VSplit, Window from prompt_toolkit_dev.layout.controls import FormattedTextControl from prompt_toolkit_dev.layout.layout import Layout # 1. The layout left_text = "\nVertical-split example. Press 'q' to quit.\n\n(left pane.)" right_text = "\n(right pane.)" body = VSplit([ Window(FormattedTextControl(left_text)), Window(width=1, char='|'), # Vertical line in the middle. Window(FormattedTextControl(right_text)), ]) # 2. Key bindings kb = KeyBindings() @kb.add('q') def _(event): " Quit application. " event.app.exit() # 3. The `Application`
from prompt_toolkit_dev.layout.dimension import D from prompt_toolkit_dev.layout.layout import Layout from prompt_toolkit_dev.widgets import Frame TITLE = HTML(""" <u>VSplit VerticalAlign</u> example. Press <b>'q'</b> to quit.""") LIPSUM = """ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas quis interdum enim. Nam viverra, mauris et blandit malesuada, ante est bibendum mauris, ac dignissim dui tellus quis ligula. Aenean condimentum leo at dignissim placerat.""" # 1. The layout body = HSplit([ Frame(Window(FormattedTextControl(TITLE), height=2), style='bg:#88ff88 #000000'), VSplit([ Window(FormattedTextControl(HTML(' <u>VerticalAlign.TOP</u>')), height=4, ignore_content_width=True, style='bg:#ff3333 #000000 bold', align=WindowAlign.CENTER), Window(FormattedTextControl(HTML(' <u>VerticalAlign.CENTER</u>')), height=4, ignore_content_width=True, style='bg:#ff3333 #000000 bold', align=WindowAlign.CENTER), Window(FormattedTextControl(HTML(' <u>VerticalAlign.BOTTOM</u>')), height=4, ignore_content_width=True,
'[%s] <style bg="orange" fg="black">--></style> ') % lineno text = str(lineno) + '-' + '*' * (lineno // 2) + ': ' return HTML('[%s.%s] <style bg="ansigreen" fg="ansiblack">%s</style>') % ( lineno, wrap_count, text) # Global wrap lines flag. wrap_lines = True # The layout buff = Buffer(complete_while_typing=True) buff.text = LIPSUM body = FloatContainer(content=HSplit([ Window(FormattedTextControl( 'Press "q" to quit. Press "w" to enable/disable wrapping.'), height=1, style='reverse'), Window(BufferControl(buffer=buff), get_line_prefix=get_line_prefix, wrap_lines=Condition(lambda: wrap_lines)), ]), floats=[ Float(xcursor=True, ycursor=True, content=CompletionsMenu(max_height=16, scroll_offset=1)) ]) # Key bindings kb = KeyBindings()
def __init__(self, body: AnyContainer, menu_items: List['MenuItem'], floats: Optional[List[Float]] = None, key_bindings: Optional[KeyBindingsBase] = None) -> None: self.body = body self.menu_items = menu_items self.selected_menu = [0] # Key bindings. kb = KeyBindings() @Condition def in_main_menu() -> bool: return len(self.selected_menu) == 1 @Condition def in_sub_menu() -> bool: return len(self.selected_menu) > 1 # Navigation through the main menu. @kb.add('left', filter=in_main_menu) def _(event: E) -> None: self.selected_menu[0] = max(0, self.selected_menu[0] - 1) @kb.add('right', filter=in_main_menu) def _(event: E) -> None: self.selected_menu[0] = min( len(self.menu_items) - 1, self.selected_menu[0] + 1) @kb.add('down', filter=in_main_menu) def _(event: E) -> None: self.selected_menu.append(0) @kb.add('c-c', filter=in_main_menu) @kb.add('c-g', filter=in_main_menu) def _(event: E) -> None: " Leave menu. " event.app.layout.focus_last() # Sub menu navigation. @kb.add('left', filter=in_sub_menu) @kb.add('c-g', filter=in_sub_menu) @kb.add('c-c', filter=in_sub_menu) def _(event: E) -> None: " Go back to parent menu. " if len(self.selected_menu) > 1: self.selected_menu.pop() @kb.add('right', filter=in_sub_menu) def _(event: E) -> None: " go into sub menu. " if self._get_menu(len(self.selected_menu) - 1).children: self.selected_menu.append(0) # If This item does not have a sub menu. Go up in the parent menu. elif len(self.selected_menu) == 2 and self.selected_menu[0] < len(self.menu_items) - 1: self.selected_menu = [min( len(self.menu_items) - 1, self.selected_menu[0] + 1)] if self.menu_items[self.selected_menu[0]].children: self.selected_menu.append(0) @kb.add('up', filter=in_sub_menu) def _(event: E) -> None: " Select previous (enabled) menu item or return to main menu. " # Look for previous enabled items in this sub menu. menu = self._get_menu(len(self.selected_menu) - 2) index = self.selected_menu[-1] previous_indexes = [i for i, item in enumerate(menu.children) if i < index and not item.disabled] if previous_indexes: self.selected_menu[-1] = previous_indexes[-1] elif len(self.selected_menu) == 2: # Return to main menu. self.selected_menu.pop() @kb.add('down', filter=in_sub_menu) def _(event: E) -> None: " Select next (enabled) menu item. " menu = self._get_menu(len(self.selected_menu) - 2) index = self.selected_menu[-1] next_indexes = [i for i, item in enumerate(menu.children) if i > index and not item.disabled] if next_indexes: self.selected_menu[-1] = next_indexes[0] @kb.add('enter') def _(event: E) -> None: " Click the selected menu item. " item = self._get_menu(len(self.selected_menu) - 1) if item.handler: event.app.layout.focus_last() item.handler() # Controls. self.control = FormattedTextControl( self._get_menu_fragments, key_bindings=kb, focusable=True, show_cursor=False) self.window = Window( height=1, content=self.control, style='class:menu-bar') submenu = self._submenu(0) submenu2 = self._submenu(1) submenu3 = self._submenu(2) @Condition def has_focus() -> bool: return get_app().layout.current_window == self.window self.container = FloatContainer( content=HSplit([ # The titlebar. self.window, # The 'body', like defined above. body, ]), floats=[ Float(xcursor=True, ycursor=True, content=ConditionalContainer( content=Shadow(body=submenu), filter=has_focus)), Float(attach_to_window=submenu, xcursor=True, ycursor=True, allow_cover_cursor=True, content=ConditionalContainer( content=Shadow(body=submenu2), filter=has_focus & Condition(lambda: len(self.selected_menu) >= 1))), Float(attach_to_window=submenu2, xcursor=True, ycursor=True, allow_cover_cursor=True, content=ConditionalContainer( content=Shadow(body=submenu3), filter=has_focus & Condition(lambda: len(self.selected_menu) >= 2))), # -- ] + (floats or []), key_bindings=key_bindings, )
def _submenu(self, level: int = 0) -> Window: def get_text_fragments() -> StyleAndTextTuples: result: StyleAndTextTuples = [] if level < len(self.selected_menu): menu = self._get_menu(level) if menu.children: result.append(('class:menu', Border.TOP_LEFT)) result.append(('class:menu', Border.HORIZONTAL * (menu.width + 4))) result.append(('class:menu', Border.TOP_RIGHT)) result.append(('', '\n')) try: selected_item = self.selected_menu[level + 1] except IndexError: selected_item = -1 def one_item(i: int, item: MenuItem) -> Iterable[OneStyleAndTextTuple]: def mouse_handler(mouse_event: MouseEvent) -> None: if mouse_event.event_type == MouseEventType.MOUSE_UP: app = get_app() if item.handler: app.layout.focus_last() item.handler() else: self.selected_menu = self.selected_menu[:level + 1] + [i] if i == selected_item: yield ('[SetCursorPosition]', '') style = 'class:menu-bar.selected-item' else: style = '' yield ('class:menu', Border.VERTICAL) if item.text == '-': yield (style + 'class:menu-border', '{}'.format(Border.HORIZONTAL * (menu.width + 3)), mouse_handler) else: yield (style, ' {}'.format(item.text).ljust(menu.width + 3), mouse_handler) if item.children: yield (style, '>', mouse_handler) else: yield (style, ' ', mouse_handler) if i == selected_item: yield ('[SetMenuPosition]', '') yield ('class:menu', Border.VERTICAL) yield ('', '\n') for i, item in enumerate(menu.children): result.extend(one_item(i, item)) result.append(('class:menu', Border.BOTTOM_LEFT)) result.append(('class:menu', Border.HORIZONTAL * (menu.width + 4))) result.append(('class:menu', Border.BOTTOM_RIGHT)) return result return Window( FormattedTextControl(get_text_fragments), style='class:menu')
dignissim placerat. In vel dictum ex, vulputate accumsan mi. Donec ut quam placerat massa tempor elementum. Sed tristique mauris ac suscipit euismod. Ut tempus vehicula augue non venenatis. Mauris aliquam velit turpis, nec congue risus aliquam sit amet. Pellentesque blandit scelerisque felis, faucibus consequat ante. Curabitur tempor tortor a imperdiet tincidunt. Nam sed justo sit amet odio bibendum congue. Quisque varius ligula nec ligula gravida, sed convallis augue faucibus. Nunc ornare pharetra bibendum. Praesent blandit ex quis sodales maximus. """ * 100).split()) # 1. The layout left_text = HTML("<reverse>transparent=False</reverse>\n") right_text = HTML("<reverse>transparent=True</reverse>") quit_text = "Press 'q' to quit." body = FloatContainer( content=Window(FormattedTextControl(LIPSUM), wrap_lines=True), floats=[ # Important note: Wrapping the floating objects in a 'Frame' is # only required for drawing the border around the # floating text. We do it here to make the layout more # obvious. # Left float. Float(Frame(Window(FormattedTextControl(left_text), width=20, height=4)), transparent=False, left=0), # Right float. Float(Frame(
TITLE = HTML(""" <u>HSplit HorizontalAlign</u> example. Press <b>'q'</b> to quit.""") LIPSUM = """\ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas quis interdum enim.""" # 1. The layout body = HSplit([ Frame( Window(FormattedTextControl(TITLE), height=2), style='bg:#88ff88 #000000'), HSplit([ # Left alignment. VSplit([ Window(FormattedTextControl(HTML('<u>LEFT</u>')), width=10, ignore_content_width=True, style='bg:#ff3333 ansiblack', align=WindowAlign.CENTER), VSplit([ Window(FormattedTextControl(LIPSUM), height=4, style='bg:#444488'), Window(FormattedTextControl(LIPSUM), height=4, style='bg:#444488'), Window(FormattedTextControl(LIPSUM), height=4, style='bg:#444488'), ], padding=1, padding_style='bg:#888888', align=HorizontalAlign.LEFT, height=5, padding_char='|'), ]), # Center alignment. VSplit([ Window(FormattedTextControl(HTML('<u>CENTER</u>')), width=10, ignore_content_width=True, style='bg:#ff3333 ansiblack', align=WindowAlign.CENTER),
placerat massa tempor elementum. Sed tristique mauris ac suscipit euismod. Ut tempus vehicula augue non venenatis. Mauris aliquam velit turpis, nec congue risus aliquam sit amet. Pellentesque blandit scelerisque felis, faucibus consequat ante. Curabitur tempor tortor a imperdiet tincidunt. Nam sed justo sit amet odio bibendum congue. Quisque varius ligula nec ligula gravida, sed convallis augue faucibus. Nunc ornare pharetra bibendum. Praesent blandit ex quis sodales maximus.""" * 40 # Create text buffers. The margins will update if you scroll up or down. buff = Buffer() buff.text = LIPSUM # 1. The layout body = HSplit([ Window(FormattedTextControl('Press "q" to quit.'), height=1, style='reverse'), Window( BufferControl(buffer=buff), # Add margins. left_margins=[NumberedMargin(), ScrollbarMargin()], right_margins=[ScrollbarMargin(), ScrollbarMargin()], ), ]) # 2. Key bindings kb = KeyBindings()
Label(text=text), ]), 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')