def __init__(self, first_game, engine): self.completer = CustomCompleter(['start']) self.elements = { 'board': Window(FormattedTextControl( ANSI(show_board(chess.STARTING_BOARD_FEN))), width=35, height=13), 'input': TextArea(height=1, prompt='>>> ', style='class:input-field', width=80, completer=self.completer), 'p1': Window(FormattedTextControl(ANSI('Games')), width=31, height=13, wrap_lines=True), 'p2': Window(FormattedTextControl(ANSI('Legal Moves')), width=31, height=13, wrap_lines=True), } self.frames = {} self.frames['board'] = Float(Frame(self.elements['board'], style='bg:#2e2e2e #ffffff'), top=10) self.frames['input'] = Float(Frame(self.elements['input'], style='bg:#2e2e2e #ffffff'), top=30) self.frames['p1'] = Float(Frame(self.elements['p1'], style='bg:#1e1e1e #ffffff'), top=10, left=10) self.frames['p2'] = Float(Frame(self.elements['p2'], style='bg:#1e1e1e #ffffff'), top=10, right=10) self.body = FloatContainer(content=Window(FormattedTextControl('')), floats=[v for k, v in self.frames.items()]) self.kb = KeyBindings() self.app = Application(layout=Layout( self.body, focused_element=self.elements['input']), key_bindings=self.kb, full_screen=True) self.set_kb() self.game = first_game self.board = first_game.board() self.moves = list(first_game.main_line()) self.engine = engine self.state = 'init' self.now = 0 self.N = len(self.moves) self.chain = [] self.selected = None self.quit = False
def get_descript(lexer): """ command description window """ return Window( content=BufferControl(buffer_name="description", lexer=lexer))
def get_empty(): """ returns an empty window because of syntaxical issues """ return Window(content=FillControl(' '))
def get_vline(): """ gets a vertical line """ return Window( width=LayoutDimension.exact(1), height=LayoutDimension.exact(1), content=FillControl('*', token=Token.Line))
def __init__(self) -> None: self.window = Window(char=Border.VERTICAL, style='class:line,vertical-line', width=1)
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)))
def __init__(self, config, out_queue, state=TaskState()): self.config = config tui_config = config['tui'] self.tui_config = tui_config self.out_queue = out_queue def commandHandler(buffer): #check incoming command cmdString = buffer.text #executeCommand(cmdString) pass def commandPrompt(line_number, wrap_count): return "command> " ######################################################################## kb = KeyBindings() @kb.add('c-d') def exit_(event): """ Pressing Esc will exit the user interface. Setting a return value means: quit the event loop that drives the user interface and return this value from the `CommandLineInterface.run()` call. """ event.app.exit() @kb.add('tab') def tab_(event): focus_next(event) @kb.add('s-tab') def stab_(event): focus_previous(event) @kb.add('s-right') def next_tab(event): state.next_tab() event.app.invalidate() @kb.add('s-left') def next_tab(event): state.prev_tab() event.app.invalidate() orders_kb = KeyBindings() @orders_kb.add('f5') def _(event): #command = ('refresh', something...) #self.out_queue.put_nowait(command) pass ######################################################################## outputArea = TextArea( text="", multiline=True, wrap_lines=False, #lexer=lexer.OutputAreaLexer(), #scrollbar=enableScrollbar, style='class:output-field', read_only=True) content_container = Frame(outputArea, title="Output") log_container = Frame( Window( BufferControl( buffer=Buffer(name='logger_buffer', read_only=True), input_processors=[FormatTextHTML()], ), right_margins=[ScrollbarMargin(display_arrows=True) ], # low-level scrollbar ), title='Log', height=8, ) command_container = TextArea(text="", multiline=False, accept_handler=commandHandler, get_line_prefix=commandPrompt) commandWindowFrame = Frame( command_container, title= "TuiTerminal (Ctrl-D to exit, Tab to switch focus and refresh UI, 'help' for help)", height=4) root_container = HSplit( [content_container, log_container, commandWindowFrame]) layout = Layout(root_container, focused_element=command_container) style = Style.from_dict({ 'output-field': 'bg:#101010', 'frame.border': 'SteelBlue', 'frame.label': 'PowderBlue', }) application = Application( layout=layout, key_bindings=kb, style=style, full_screen=tui_config.getboolean('full_screen'), mouse_support=tui_config.getboolean('mouse_support'), #after_render=after_render, ) self.application = application
from prompt_toolkit.layout import Layout, HSplit from prompt_toolkit.key_binding import KeyBindings # naformátované zprávy message1 = HTML("<ansired>Hello</ansired>") message2 = HTML("<ansiblue>world!</ansiblue>") message3 = HTML("<ansiyellow>(Esc to quit)</ansiyellow>") # ovládací prvky s naformátovaným textem text1 = FormattedTextControl(text=message1) text2 = FormattedTextControl(text=message2) text3 = FormattedTextControl(text=message3) # okna obsahující jediný ovládací prvek window1 = Window(content=text1) window2 = Window(content=text2) window3 = Window(content=text3) # správce rozvržení hsplit = HSplit([ window1, window2, window3]) layout = Layout(hsplit) # napojení na klávesové zkratky key_bindings = KeyBindings() @key_bindings.add('escape')
def game_runner(self, old, proc_args: list, proc_cwd: str, options: dict): if options["cmd_args"].not_rich: old(proc_args, proc_cwd, options) return title_text = self.pmc.get_message( "start.run.richer.title", options.get("version", "unknown_version"), options.get("username", "anonymous"), options.get("uuid", "uuid")) buffer_window = RollingLinesWindow(400, lexer=ColoredLogLexer(), last_line_return=True) buffer_window.append( self.pmc.get_message("start.run.richer.command_line", " ".join(proc_args)), "\n") container = HSplit([ VSplit([ Window(width=2), Window(FormattedTextControl(text=title_text)), ], height=1, style="class:header"), VSplit([Window(width=1), buffer_window, Window(width=1)]) ]) keys = KeyBindings() double_exit = not options["cmd_args"].single_exit @keys.add("c-c") def _exit(event: KeyPressEvent): nonlocal process if not double_exit or process is None: event.app.exit() else: process.kill() application = self.build_application(container, keys) process = Popen(proc_args, cwd=proc_cwd, stdout=PIPE, stderr=PIPE, bufsize=1, universal_newlines=True) async def _run_process(): nonlocal process stdout_reader = ThreadedProcessReader(cast(TextIO, process.stdout)) stderr_reader = ThreadedProcessReader(cast(TextIO, process.stderr)) while True: code = process.poll() if code is None: done, pending = await asyncio.wait( (stdout_reader.poll(), stderr_reader.poll()), return_when=asyncio.FIRST_COMPLETED) for done_task in done: line = done_task.result() if line is not None: buffer_window.append(line) for pending_task in pending: pending_task.cancel() else: stdout_reader.wait_until_closed() stderr_reader.wait_until_closed() buffer_window.append(*stdout_reader.poll_all(), *stderr_reader.poll_all()) break process = None if double_exit: buffer_window.append( "", "Minecraft process has terminated, Ctrl+C again to close terminal." ) async def _run(): _done, _pending = await asyncio.wait( (_run_process(), application.run_async()), return_when=asyncio.ALL_COMPLETED if double_exit else asyncio.FIRST_COMPLETED) if process is not None: process.kill() process.wait(timeout=5) if application.is_running: application.exit() asyncio.get_event_loop().run_until_complete(_run())
'mouse', 'rabbit', 'rat', 'snake', 'spider', 'turkey', 'turtle', ], ignore_case=True) # The layout buff = Buffer(completer=animal_completer, complete_while_typing=True) body = FloatContainer(content=HSplit([ Window(FormattedTextControl('Press "q" to quit.'), height=1, style='reverse'), Window(BufferControl(buffer=buff)), ]), floats=[ Float(xcursor=True, ycursor=True, content=CompletionsMenu(max_height=16, scroll_offset=1)) ]) # Key bindings kb = KeyBindings() @kb.add('q')
def question(message, choices: List[Choice], default=None, qmark='?', key_bindings=None, **kwargs): """ Builds a `prompt-toolkit` Application that display a list of choices (ChoiceControl) along with search features and key bindings Paramaters ========== kwargs: Dict[Any, Any] Any additional arguments that a prompt_toolkit.application.Application can take. Passed as-is """ if key_bindings is None: key_bindings = KeyBindings() choices_control = ChoicesControl(choices, default=default) def get_prompt_tokens(): tokens = [] tokens.append(('class:question-mark', qmark)) tokens.append(('class:question', ' %s ' % message)) if choices_control.is_answered: tokens.append(('class:answer', ' ' + choices_control.get_selection().display_text)) else: tokens.append(('class:instruction', ' (Use arrow keys)')) return tokens @Condition def has_search_string(): return choices_control.get_search_string_tokens is not None @key_bindings.add(Keys.ControlQ, eager=True) def exit_menu(event): event.app.exit(exception=KeyboardInterrupt()) if not key_bindings.get_bindings_for_keys((Keys.ControlC, )): key_bindings.add(Keys.ControlC, eager=True)(exit_menu) @key_bindings.add(Keys.Down, eager=True) def move_cursor_down(_event): # pylint:disable=unused-variable choices_control.select_next_choice() @key_bindings.add(Keys.Up, eager=True) def move_cursor_up(_event): # pylint:disable=unused-variable choices_control.select_previous_choice() @key_bindings.add(Keys.Enter, eager=True) def set_answer(event): # pylint:disable=unused-variable choices_control.is_answered = True choices_control.reset_search_string() event.app.exit(result=choices_control.get_selection().value) def search_filter(event): choices_control.append_to_search_string(event.key_sequence[0].key) for character in string.printable: key_bindings.add(character, eager=True)(search_filter) @key_bindings.add(Keys.Backspace, eager=True) def delete_from_search_filter(_event): # pylint:disable=unused-variable choices_control.remove_last_char_from_search_string() layout = Layout( HSplit([ # Question Window( height=D.exact(1), content=FormattedTextControl(get_prompt_tokens), always_hide_cursor=True, ), # Choices ConditionalContainer( Window(choices_control), filter=~IsDone() # pylint:disable=invalid-unary-operand-type ), # Searched string ConditionalContainer( Window(height=D.exact(2), content=FormattedTextControl( choices_control.get_search_string_tokens)), filter=has_search_string & ~IsDone() # pylint:disable=invalid-unary-operand-type ), ])) return Application(layout=layout, key_bindings=key_bindings, mouse_support=False, style=default_style, **kwargs)
def question(message, **kwargs): # TODO extract common parts for list, checkbox, rawlist, expand # TODO up, down navigation 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) def get_prompt_tokens(): tokens = [] tokens.append(('class:questionmark', qmark)) tokens.append(('class:question', ' %s ' % message)) if not ic.answered: tokens.append(('class:instruction', ' (%s)' % ''.join( [k[0] for k in ic.choices if not isinstance(k, Separator)]))) else: tokens.append(('class:answer', ' %s' % ic.get_selected_value())) return tokens #@Condition #def is_help_active(): # return ic._help_active # assemble layout layout = HSplit([ Window(height=D.exact(1), content=FormattedTextControl(get_prompt_tokens) ), ConditionalContainer( Window(ic), #filter=is_help_active & ~IsDone() # ~ bitwise inverse filter=~IsDone() # ~ bitwise inverse ) ]) # 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 if c[0] not in ['h', 'H']: _reg_binding(i, c[0]) if c[0].isupper(): _reg_binding(i, c[0].lower()) @kb.add('H', eager=True) @kb.add('h', eager=True) def help_choice(event): ic._help_active = not ic._help_active @kb.add('enter', eager=True) def set_answer(event): selected_value = ic.get_selected_value() if selected_value == '__HELP__': ic._help_active = True else: ic.answered = True event.app.exit(result=selected_value) return Application( layout=Layout(layout), key_bindings=kb, mouse_support=True, style=style )
# containers use absolute coordinates, while user controls paint on their own # `Screen` with a relative coordinates. # The Window class itself is a container that can contain a user control, so # that's the adaptor between the two. The Window class also takes care of # scrolling the content if the user control is painting on a screen that is # larger than what was available to the window. # So, for this example, we create a layout that shows the content of the # default buffer on the left, shows a line in the middle and another buffer # (called 'RESULT') on the right. layout = VSplit([ # One window that holds the BufferControl with the default buffer on the # left. Window(content=BufferControl(buffer_name=DEFAULT_BUFFER)), # A vertical line in the middle. We explicitely specify the width, to make # sure that the layout engine will not try to divide the whole width by # three for all these windows. The `FillControl` will simply fill the whole # window by repeating this character. Window(width=D.exact(1), content=FillControl('|', token=Token.Line)), # Display the Result buffer on the right. Window(content=BufferControl(buffer_name='RESULT')), ]) # As a demonstration. Let's add a title bar to the top, displaying "Hello world". # somewhere, because usually the default key bindings include searching. (Press # Ctrl-R.) It would be really annoying if the search key bindings are handled,
def __init__( self, options, default_index=0, header_filter=lambda x: x, match_filter=lambda x: x ): self.info_window = InfoWindow() self.help_window = HelpWindow() self.message_toolbar = MessageToolbar(style="class:message_toolbar") self.error_toolbar = MessageToolbar(style="class:error_toolbar") self.status_line = MessageToolbar(style="class:status_line") self.status_line_format = config.get( 'status_line_format', section="tui" ) self.options_list = OptionsList( options, default_index, header_filter, match_filter, custom_filter=~has_focus(self.help_window) ) self.options_list.search_buffer.on_text_changed += self.update commands, commands_kb = get_commands(self) self.command_line_prompt = CommandLinePrompt(commands=commands) kb = merge_key_bindings([create_keybindings(self), commands_kb]) _root_container = HSplit([ HSplit([ Window( content=BufferControl( input_processors=[BeforeInput('> ')], buffer=self.options_list.search_buffer ) ), self.options_list, self.info_window, ]), self.help_window, self.error_toolbar, self.message_toolbar, self.status_line, self.command_line_prompt.window, ]) help_text = "" keys_info = get_keys_info() for k in keys_info: help_text += ( "<ansired>{k[key]}</ansired>: {k[help]}\n".format( k=keys_info[k] ) ) self.help_window.text = HTML(help_text) self.layout = Layout(_root_container) super(Picker, self).__init__( input=None, output=None, editing_mode=EditingMode.EMACS if config.get('editmode', section='tui') == 'emacs' else EditingMode.VI, layout=self.layout, style=Style.from_dict({ 'options_list.selected_margin': config.get( 'options_list.selected_margin_style', section='tui' ), 'options_list.unselected_margin': config.get( 'options_list.unselected_margin_style', section='tui' ), 'error_toolbar': config.get( 'error_toolbar_style', section='tui' ), 'message_toolbar': config.get( 'message_toolbar_style', section='tui' ), 'status_line': config.get( 'status_line_style', section='tui' ), }), key_bindings=kb, include_default_pygments_style=False, full_screen=True, enable_page_navigation_bindings=True ) self.update()
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_toggle"] = right_pane_toggle components["pane_top"] = VSplit([ components["item_top_version"], components["item_top_active"], components["item_top_file"], 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 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!') 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(cli): tokens = [] T = Token tokens.append((T.QuestionMark, '?')) tokens.append((T.Question, ' %s ' % message)) if ic.answered: tokens.append((T.Answer, ' %s' % ic.get_selected_value())) 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() # 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 @manager.registry.add_binding(keys, eager=True) def select_choice(event): ic.pointer_index = i _reg_binding(i, '%d' % c[0]) @manager.registry.add_binding(Keys.Enter, eager=True) def set_answer(event): ic.answered = True event.cli.set_return_value(ic.get_selected_value()) return Application(layout=layout, key_bindings_registry=manager.registry, mouse_support=True, style=style)
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),
def main(): # The layout. search_field = SearchToolbar() # For reverse search. output_field = TextArea(style='class:output-field', text=help_text) input_field = TextArea( height=1, prompt='>>> ', style='class:input-field', multiline=False, wrap_lines=False, search_field=search_field) container = HSplit([ output_field, Window(height=1, char='-', style='class:line'), input_field, search_field, ]) # Attach accept handler to the input field. We do this by assigning the # handler to the `TextArea` that we created earlier. it is also possible to # pass it to the constructor of `TextArea`. # NOTE: It's better to assign an `accept_handler`, rather then adding a # custom ENTER key binding. This will automatically reset the input # field and add the strings to the history. def accept(buff): # Evaluate "calculator" expression. try: output = '\n\nIn: {}\nOut: {}'.format( input_field.text, eval(input_field.text)) # Don't do 'eval' in real code! except BaseException as e: output = '\n\n{}'.format(e) new_text = output_field.text + output # Add text to output buffer. output_field.buffer.document = Document( text=new_text, cursor_position=len(new_text)) input_field.accept_handler = accept # The key bindings. kb = KeyBindings() @kb.add('c-c') @kb.add('c-q') def _(event): " Pressing Ctrl-Q or Ctrl-C will exit the user interface. " event.app.exit() # Style. style = Style([ ('output-field', 'bg:#000044 #ffffff'), ('input-field', 'bg:#000000 #ffffff'), ('line', '#004400'), ]) # Run application. application = Application( layout=Layout(container, focused_element=input_field), key_bindings=kb, style=style, mouse_support=True, full_screen=True) application.run()
def create_layout(python_input, history_mapping): """ Create and return a `Container` instance for the history application. """ default_processors = [ HighlightSearchProcessor(preview_search=Always()), 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=default_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, wrap_lines=False, lexer=PygmentsLexer(PythonLexer), input_processors=default_processors), 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, wrap_lines=False, input_processors=[GrayExistingText(history_mapping)] + default_processors, lexer=PygmentsLexer(PythonLexer)), 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)), ])
from prompt_toolkit.buffer import Buffer from prompt_toolkit.key_binding import KeyBindings from prompt_toolkit.layout.containers import HSplit, VSplit, Window, WindowAlign from prompt_toolkit.layout.controls import BufferControl, FormattedTextControl from prompt_toolkit.layout.layout import Layout # 3. Create the buffers # ------------------ left_buffer = Buffer() right_buffer = Buffer() # 1. First we create the layout # -------------------------- left_window = Window(BufferControl(buffer=left_buffer)) right_window = Window(BufferControl(buffer=right_buffer)) body = VSplit([ left_window, # A vertical line in the middle. We explicitly specify the width, to make # sure that the layout engine will not try to divide the whole width by # three for all these windows. Window(width=1, char="|", style="class:line"), # Display the Result buffer on the right. right_window, ]) # As a demonstration. Let's add a title bar to the top, displaying "Hello world". # somewhere, because usually the default key bindings include searching. (Press
def create_layout(self, exam_lex, toolbar_lex): """ creates the layout """ lexer, exam_lex, toolbar_lex = get_lexers(self.shell_ctx.lexer, exam_lex, toolbar_lex) if not any(isinstance(processor, DefaultPrompt) for processor in self.input_processors): self.input_processors.append(DefaultPrompt(self.get_prompt_tokens)) layout_lower = ConditionalContainer( HSplit([ get_anyhline(self.shell_ctx.config), get_descriptions(self.shell_ctx.config, exam_lex, lexer), get_examplehline(self.shell_ctx.config), get_example(self.shell_ctx.config, exam_lex), ConditionalContainer( get_hline(), filter=self.show_default | self.show_symbol ), ConditionalContainer( Window( content=BufferControl( buffer_name='default_values', lexer=lexer ) ), filter=self.show_default ), ConditionalContainer( get_hline(), filter=self.show_default & self.show_symbol ), ConditionalContainer( Window( content=BufferControl( buffer_name='symbols', lexer=exam_lex ) ), filter=self.show_symbol ), ConditionalContainer( Window( content=BufferControl( buffer_name='progress', lexer=lexer ) ), filter=self.show_progress ), Window( content=BufferControl( buffer_name='bottom_toolbar', lexer=toolbar_lex ), ), ]), filter=~IsDone() & RendererHeightIsKnown() ) 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))))]), layout_lower ]) return layout_full
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 _up(event: E) -> None: self._selected_index = max(0, self._selected_index - 1) @kb.add("down") def _down(event: E) -> None: self._selected_index = min( len(self.values) - 1, self._selected_index + 1) @kb.add("pageup") def _pageup(event: E) -> None: w = event.app.layout.current_window if w.render_info: self._selected_index = max( 0, self._selected_index - len(w.render_info.displayed_lines)) @kb.add("pagedown") def _pagedown(event: E) -> None: w = event.app.layout.current_window if w.render_info: self._selected_index = min( len(self.values) - 1, self._selected_index + len(w.render_info.displayed_lines), ) @kb.add("enter") @kb.add(" ") def _click(event: E) -> None: self._handle_enter() @kb.add(Keys.Any) def _find(event: E) -> None: # We first check values after the selected value, then all values. values = list(self.values) for value in values[self._selected_index + 1:] + values: text = fragment_list_to_text(to_formatted_text( value[1])).lower() if text.startswith(event.data.lower()): 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=[ ConditionalMargin( margin=ScrollbarMargin(display_arrows=True), filter=Condition(lambda: self.show_scrollbar), ), ], dont_extend_height=True, )
def __init__(self, text: str = '', multiline: FilterOrBool = True, password: FilterOrBool = False, lexer: Optional[Lexer] = None, auto_suggest: Optional[AutoSuggest] = None, completer: Optional[Completer] = None, complete_while_typing: FilterOrBool = True, accept_handler: Optional[BufferAcceptHandler] = None, history: Optional[History] = None, focusable: FilterOrBool = True, focus_on_click: FilterOrBool = False, wrap_lines: FilterOrBool = True, read_only: FilterOrBool = False, width: AnyDimension = None, height: AnyDimension = None, dont_extend_height: FilterOrBool = False, dont_extend_width: FilterOrBool = False, line_numbers: bool = False, get_line_prefix: Optional[GetLinePrefixCallable] = None, scrollbar: bool = False, style: str = '', search_field: Optional[SearchToolbar] = None, preview_search: FilterOrBool = True, prompt: AnyFormattedText = '', input_processors: Optional[List[Processor]] = None) -> None: if search_field is None: search_control = None elif isinstance(search_field, SearchToolbar): search_control = search_field.control if input_processors is None: input_processors = [] # Writeable attributes. self.completer = completer self.complete_while_typing = complete_while_typing self.lexer = lexer self.auto_suggest = auto_suggest self.read_only = read_only self.wrap_lines = wrap_lines self.buffer = Buffer( document=Document(text, 0), multiline=multiline, read_only=Condition(lambda: is_true(self.read_only)), completer=DynamicCompleter(lambda: self.completer), complete_while_typing=Condition( lambda: is_true(self.complete_while_typing)), auto_suggest=DynamicAutoSuggest(lambda: self.auto_suggest), accept_handler=accept_handler, history=history) self.control = BufferControl( buffer=self.buffer, lexer=DynamicLexer(lambda: self.lexer), input_processors=[ ConditionalProcessor(AppendAutoSuggestion(), has_focus(self.buffer) & ~is_done), ConditionalProcessor(processor=PasswordProcessor(), filter=to_filter(password)), BeforeInput(prompt, style='class:text-area.prompt'), ] + input_processors, search_buffer_control=search_control, preview_search=preview_search, focusable=focusable, focus_on_click=focus_on_click) if multiline: if scrollbar: right_margins = [ScrollbarMargin(display_arrows=True)] else: right_margins = [] if line_numbers: left_margins = [NumberedMargin()] else: left_margins = [] else: height = D.exact(1) left_margins = [] right_margins = [] style = 'class:text-area ' + style self.window = Window( height=height, width=width, dont_extend_height=dont_extend_height, dont_extend_width=dont_extend_width, content=self.control, style=style, wrap_lines=Condition(lambda: is_true(self.wrap_lines)), left_margins=left_margins, right_margins=right_margins, get_line_prefix=get_line_prefix)
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 search_buffer = Buffer(name = "sidebarsearchbuffer") search_field = SearchToolbar( search_buffer = search_buffer, ignore_case = True ) def _buffer_pos_changed(buff): """ This callback gets executed after cursor position changes. Most of the time we register a key-press (up / down), we change the selected object and as a result of that the cursor changes. By that time we don't need to updat the selected object (cursor changed as a result of the selected object being updated). The one exception is when searching the sidebar buffer. When this happens the cursor moves ahead of the selected object. When that happens, here we update the selected object to follow suit. """ if buff.document.cursor_position_row != my_app.selected_object_idx[0]: my_app.select(buff.document.cursor_position_row) sidebar_buffer = Buffer( name = "sidebarbuffer", read_only = True, on_cursor_position_changed = _buffer_pos_changed ) class myLexer(Lexer): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._obj_list = [] def add_objects(self, objects: List): self._obj_list = objects def lex_document(self, document: Document) -> Callable[[int], StyleAndTextTuples]: def get_line(lineno: int) -> StyleAndTextTuples: # TODO: raise out-of-range exception return tokenize_obj(self._obj_list[lineno]) return get_line sidebar_lexer = myLexer() class myControl(BufferControl): def move_cursor_down(self): my_app.select_next() # Need to figure out what do do here # AFAICT these 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: # Only traverse the obj_list if it has been expanded / collapsed if not my_app.obj_list_changed: self.buffer.cursor_position = my_app.selected_object_idx[1] return super().create_content(width, height) res = [] obj = my_app.obj_list[0] res.append(obj) while obj.next_object is not my_app.obj_list[0]: res.append(obj.next_object) obj = obj.next_object self.lexer.add_objects(res) self.buffer.set_document(Document( text = "\n".join([a.name for a in res]), cursor_position = my_app.selected_object_idx[1]), True) # Reset obj_list_changed flag, now that we have had a chance to # regenerate the sidebar document content my_app.obj_list_changed = False 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()])
def __init__(self) -> None: self.window = Window(char=Border.HORIZONTAL, style='class:line,horizontal-line', height=1)
all_remaining.text = "\n".join(remaining) all_excess.text = "\n".join(excess) all_overused.text = "\n".join(overused) used = Buffer(on_text_changed=assess) kb = KeyBindings() @kb.add('c-q') def exit_(event): event.app.exit() root_container = HSplit([ Window(height=1, content=FormattedTextControl(text=message)), Window(height=1, char='-'), VSplit([ Window(content=BufferControl(buffer=used)), Window(width=1, char='|'), Window(content=all_remaining), Window(width=1, char='|'), Window(content=all_overused), Window(width=1, char='|'), Window(content=all_excess), ]), Window(height=1, char='-'), Window(height=1, content=FormattedTextControl(text="Ctrl + Q to Quit")) ]) layout = Layout(root_container)
def get_param(lexer): """ parameter description window """ return Window(content=BufferControl(buffer_name="parameter", lexer=lexer))
from prompt_toolkit.layout.controls import FormattedTextControl from prompt_toolkit.layout import Layout, HSplit, VSplit from prompt_toolkit.key_binding import KeyBindings # naformátované zprávy message1 = HTML("<ansired>Hello</ansired>") message2 = HTML("<ansiblue>world!</ansiblue>") message3 = HTML("<ansiyellow>(Esc to quit)</ansiyellow>") # ovládací prvky s naformátovaným textem text1 = FormattedTextControl(text=message1) text2 = FormattedTextControl(text=message2) text3 = FormattedTextControl(text=message3) # okna obsahující jediný ovládací prvek window1 = Window(content=text1) window2 = Window(content=text2) window3 = Window(content=text3) # správce rozvržení vsplit = HSplit([ VSplit([window1, Window(width=1, char='|'), window2]), Window(height=1, char='-'), window3 ]) layout = Layout(vsplit) # napojení na klávesové zkratky key_bindings = KeyBindings() @key_bindings.add('escape')
def get_hline(): """ gets a horiztonal line """ return Window(width=D.exact(1), height=D.exact(1), content=FillControl('-', token=Token.Line))
def run(self, query, data): self.load_config() if data or query is not None: self.format = self.format_stdin self.echo.verbose = False if self.echo.verbose: show_version() if not self.connect(): return if self.client: self.client.settings = self.settings self.client.cli_settings = { 'multiline': self.multiline, 'vi_mode': self.vi_mode, 'format': self.format, 'format_stdin': self.format_stdin, 'show_formatted_query': self.show_formatted_query, 'highlight': self.highlight, 'highlight_output': self.highlight_output, 'refresh_metadata_on_start': self.refresh_metadata_on_start, 'refresh_metadata_on_query': self.refresh_metadata_on_query, } if data and query is None: # cat stuff.sql | clickhouse-cli # clickhouse-cli stuff.sql for subdata in data: self.handle_input(subdata.read(), verbose=False, refresh_metadata=False) return if not data and query is not None: # clickhouse-cli -q 'SELECT 1' return self.handle_query(query, stream=False) if data and query is not None: # cat stuff.csv | clickhouse-cli -q 'INSERT INTO stuff' # clickhouse-cli -q 'INSERT INTO stuff' stuff.csv for subdata in data: compress = 'gzip' if os.path.splitext( subdata.name)[1] == '.gz' else False self.handle_query(query, data=subdata, stream=True, compress=compress) return buffer = CLIBuffer( client=self.client, multiline=self.multiline, metadata=self.metadata, ) root_container = Window(content=BufferControl(buffer=buffer)) layout = Layout(root_container) # layout.focus(root_container) # layout = prompt( # lexer=PygmentsLexer(CHLexer) if self.highlight else None, # # get_prompt_tokens=get_prompt_tokens, # # get_continuation_tokens=get_continuation_tokens, # multiline=self.multiline, # ) hist = FileHistory( filename=os.path.expanduser('~/.clickhouse-cli_history')) self.completer = CHCompleter(self.client, self.metadata) self.session = PromptSession( style=CHStyle if self.highlight else None, lexer=PygmentsLexer(CHLexer) if self.highlight else None, message=get_prompt_tokens()[0][1], prompt_continuation=get_continuation_tokens()[0][1], multiline=is_multiline(self.multiline), vi_mode=self.vi_mode, history=hist, key_bindings=kb, complete_while_typing=self.complete_while_typing, completer=ThreadedCompleter( DynamicCompleter(lambda: self.completer)), ) self.app = Application(layout=layout, # buffer=buffer, ) #self.cli = CommandLineInterface(application=application, eventloop=eventloop) if self.refresh_metadata_on_start: self.app.current_buffer.completer.refresh_metadata() try: while True: try: cli_input = self.session.prompt() self.handle_input(cli_input) except KeyboardInterrupt: # Attempt to terminate queries for query_id in self.query_ids: self.client.kill_query(query_id) self.echo.error("\nQuery was terminated.") finally: self.query_ids = [] except EOFError: self.echo.success("Bye.")