def main(): # vytvoření aplikace s textovým uživatelským rozhraním application = Application(full_screen=True) # spuštění aplikace application.run()
def run_cli(self): sqlexecute = self.sqlexecute logger = self.logger self.configure_pager() self.refresh_completions() project_root = os.path.dirname(PACKAGE_ROOT) author_file = os.path.join(project_root, 'AUTHORS') sponsor_file = os.path.join(project_root, 'SPONSORS') key_binding_manager = mycli_bindings() if not self.less_chatty: print('Version:', __version__) print('Chat: https://gitter.im/dbcli/mycli') print('Mail: https://groups.google.com/forum/#!forum/mycli-users') print('Home: http://mycli.net') print('Thanks to the contributor -', thanks_picker([author_file, sponsor_file])) def prompt_tokens(cli): return [(Token.Prompt, self.get_prompt(self.prompt_format))] def get_continuation_tokens(cli, width): continuation_prompt = self.get_prompt( self.prompt_continuation_format) return [(Token.Continuation, ' ' * (width - len(continuation_prompt)) + continuation_prompt)] get_toolbar_tokens = create_toolbar_tokens_func( self.completion_refresher.is_refreshing) layout = create_prompt_layout( lexer=MyCliLexer, multiline=True, get_prompt_tokens=prompt_tokens, get_continuation_tokens=get_continuation_tokens, get_bottom_toolbar_tokens=get_toolbar_tokens, display_completions_in_columns=self.wider_completion_menu, extra_input_processors=[ ConditionalProcessor( processor=HighlightMatchingBracketProcessor( chars='[](){}'), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone()), ]) with self._completer_lock: buf = CLIBuffer(always_multiline=self.multi_line, completer=self.completer, history=FileHistory( os.path.expanduser( os.environ.get('MYCLI_HISTFILE', '~/.mycli-history'))), complete_while_typing=Always(), accept_action=AcceptAction.RETURN_DOCUMENT) if self.key_bindings == 'vi': editing_mode = EditingMode.VI else: editing_mode = EditingMode.EMACS application = Application( style=style_factory(self.syntax_style, self.cli_style), layout=layout, buffer=buf, key_bindings_registry=key_binding_manager.registry, on_exit=AbortAction.RAISE_EXCEPTION, on_abort=AbortAction.RETRY, editing_mode=editing_mode, ignore_case=True) self.cli = CommandLineInterface(application=application, eventloop=create_eventloop()) try: while True: document = self.cli.run(reset_current_buffer=True) special.set_expanded_output(False) # The reason we check here instead of inside the sqlexecute is # because we want to raise the Exit exception which will be # caught by the try/except block that wraps the # sqlexecute.run() statement. if quit_command(document.text): raise EOFError try: document = self.handle_editor_command(self.cli, document) except RuntimeError as e: logger.error("sql: %r, error: %r", document.text, e) logger.error("traceback: %r", traceback.format_exc()) self.output(str(e), err=True, fg='red') continue if self.destructive_warning: destroy = confirm_destructive_query(document.text) if destroy is None: pass # Query was not destructive. Nothing to do here. elif destroy is True: self.output('Your call!') else: self.output('Wise choice!') continue # Keep track of whether or not the query is mutating. In case # of a multi-statement query, the overall query is considered # mutating if any one of the component statements is mutating mutating = False try: logger.debug('sql: %r', document.text) if self.logfile: self.logfile.write('\n# %s\n' % datetime.now()) self.logfile.write(document.text) self.logfile.write('\n') successful = False start = time() res = sqlexecute.run(document.text) successful = True output = [] total = 0 for title, cur, headers, status in res: logger.debug("headers: %r", headers) logger.debug("rows: %r", cur) logger.debug("status: %r", status) threshold = 1000 if (is_select(status) and cur and cur.rowcount > threshold): self.output( 'The result set has more than %s rows.' % threshold, fg='red') if not click.confirm('Do you want to continue?'): self.output("Aborted!", err=True, fg='red') break if self.auto_vertical_output: max_width = self.cli.output.get_size().columns else: max_width = None formatted = format_output(title, cur, headers, status, self.table_format, special.is_expanded_output(), max_width) output.extend(formatted) end = time() total += end - start mutating = mutating or is_mutating(status) except UnicodeDecodeError as e: import pymysql if pymysql.VERSION < (0, 6, 7): message = ( 'You are running an older version of pymysql.\n' 'Please upgrade to 0.6.7 or above to view binary data.\n' 'Try \'pip install -U pymysql\'.') self.output(message) else: raise e except KeyboardInterrupt: # Restart connection to the database sqlexecute.connect() logger.debug("cancelled query, sql: %r", document.text) self.output("cancelled query", err=True, fg='red') except NotImplementedError: self.output('Not Yet Implemented.', fg="yellow") except OperationalError as e: logger.debug("Exception: %r", e) reconnect = True if (e.args[0] in (2003, 2006, 2013)): reconnect = click.prompt( 'Connection reset. Reconnect (Y/n)', show_default=False, type=bool, default=True) if reconnect: logger.debug('Attempting to reconnect.') try: sqlexecute.connect() logger.debug('Reconnected successfully.') self.output( 'Reconnected!\nTry the command again.', fg='green') except OperationalError as e: logger.debug('Reconnect failed. e: %r', e) self.output(str(e), err=True, fg='red') continue # If reconnection failed, don't proceed further. else: # If user chooses not to reconnect, don't proceed further. continue else: logger.error("sql: %r, error: %r", document.text, e) logger.error("traceback: %r", traceback.format_exc()) self.output(str(e), err=True, fg='red') except Exception as e: logger.error("sql: %r, error: %r", document.text, e) logger.error("traceback: %r", traceback.format_exc()) self.output(str(e), err=True, fg='red') else: try: if special.is_pager_enabled(): self.output_via_pager('\n'.join(output)) else: self.output('\n'.join(output)) except KeyboardInterrupt: pass if special.is_timing_enabled(): self.output('Time: %0.03fs' % total) # Refresh the table names and column names if necessary. if need_completion_refresh(document.text): self.refresh_completions( reset=need_completion_reset(document.text)) finally: if self.logfile is False: self.output("Warning: This query was not logged.", err=True, fg='red') query = Query(document.text, successful, mutating) self.query_history.append(query) except EOFError: if not self.less_chatty: self.output('Goodbye!')
def create_content(self): # 文本编辑器 text_editor = self.create_text_editor() # 播放列表属性编辑器 property_editor = self.create_property_editor() body = HSplit([ HSplit( [ property_editor, Label(' '), Window(height=1, char="-", style="class:line"), text_editor, ], height=D(), ), ConditionalContainer( content=VSplit( [ Window(FormattedTextControl(self.get_statusbar_text), style="class:status"), Window( FormattedTextControl( self.get_statusbar_right_text), style="class:status.right", width=9, align=WindowAlign.RIGHT, ), ], height=1, ), filter=Condition(lambda: self.is_show_status_bar()), ), ]) self.create_key_bindings() root_container = MenuContainer( body=body, menu_items=[ MenuItem( "File", children=[ MenuItem("Exit", handler=self.exit), ], ), ], floats=[ Float( xcursor=True, ycursor=True, content=CompletionsMenu(max_height=16, scroll_offset=1), ), ], key_bindings=self.key_bindings, ) style = Style.from_dict({ "status": "reverse", "shadow": "bg:#440044", }) self.layout = Layout(root_container, focused_element=self.text_field) self.application = Application( layout=self.layout, enable_page_navigation_bindings=True, style=style, mouse_support=True, full_screen=True, )
def run_cli(self): pgexecute = self.pgexecute logger = self.logger original_less_opts = self.adjust_less_opts() completer = self.completer self.refresh_completions() def set_vi_mode(value): self.vi_mode = value key_binding_manager = pgcli_bindings( get_vi_mode_enabled=lambda: self.vi_mode, set_vi_mode_enabled=set_vi_mode) print('Version:', __version__) print('Chat: https://gitter.im/dbcli/pgcli') print('Mail: https://groups.google.com/forum/#!forum/pgcli') print('Home: http://pgcli.com') def prompt_tokens(cli): return [(Token.Prompt, '%s> ' % pgexecute.dbname)] get_toolbar_tokens = create_toolbar_tokens_func(lambda: self.vi_mode) layout = create_default_layout( lexer=PostgresLexer, reserve_space_for_menu=True, get_prompt_tokens=prompt_tokens, get_bottom_toolbar_tokens=get_toolbar_tokens, extra_input_processors=[ # Highlight matching brackets while editing. ConditionalProcessor( processor=HighlightMatchingBracketProcessor( chars='[](){}'), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone()), ]) history_file = self.config['main']['history_file'] buf = PGBuffer(always_multiline=self.multi_line, completer=completer, history=FileHistory(os.path.expanduser(history_file)), complete_while_typing=Always()) application = Application( style=style_factory(self.syntax_style), layout=layout, buffer=buf, key_bindings_registry=key_binding_manager.registry, on_exit=AbortAction.RAISE_EXCEPTION) cli = CommandLineInterface(application=application, eventloop=create_eventloop()) try: while True: document = cli.run() # The reason we check here instead of inside the pgexecute is # because we want to raise the Exit exception which will be # caught by the try/except block that wraps the pgexecute.run() # statement. if quit_command(document.text): raise EOFError try: document = self.handle_editor_command(cli, document) except RuntimeError as e: logger.error("sql: %r, error: %r", document.text, e) logger.error("traceback: %r", traceback.format_exc()) click.secho(str(e), err=True, fg='red') continue # Keep track of whether or not the query is mutating. In case # of a multi-statement query, the overall query is considered # mutating if any one of the component statements is mutating mutating = False try: logger.debug('sql: %r', document.text) successful = False # Initialized to [] because res might never get initialized # if an exception occurs in pgexecute.run(). Which causes # finally clause to fail. res = [] start = time() # Run the query. res = pgexecute.run(document.text, self.pgspecial) duration = time() - start successful = True output = [] total = 0 for title, cur, headers, status in res: logger.debug("headers: %r", headers) logger.debug("rows: %r", cur) logger.debug("status: %r", status) start = time() threshold = 1000 if (is_select(status) and cur and cur.rowcount > threshold): click.secho( 'The result set has more than %s rows.' % threshold, fg='red') if not click.confirm('Do you want to continue?'): click.secho("Aborted!", err=True, fg='red') break formatted = format_output( title, cur, headers, status, self.table_format, self.pgspecial.expanded_output) output.extend(formatted) end = time() total += end - start mutating = mutating or is_mutating(status) except KeyboardInterrupt: # Restart connection to the database pgexecute.connect() logger.debug("cancelled query, sql: %r", document.text) click.secho("cancelled query", err=True, fg='red') except NotImplementedError: click.secho('Not Yet Implemented.', fg="yellow") except OperationalError as e: reconnect = True if ('server closed the connection' in utf8tounicode(e.args[0])): reconnect = click.prompt( 'Connection reset. Reconnect (Y/n)', show_default=False, type=bool, default=True) if reconnect: try: pgexecute.connect() click.secho( 'Reconnected!\nTry the command again.', fg='green') except OperationalError as e: click.secho(str(e), err=True, fg='red') else: logger.error("sql: %r, error: %r", document.text, e) logger.error("traceback: %r", traceback.format_exc()) click.secho(str(e), err=True, fg='red') except Exception as e: logger.error("sql: %r, error: %r", document.text, e) logger.error("traceback: %r", traceback.format_exc()) click.secho(str(e), err=True, fg='red') else: click.echo_via_pager('\n'.join(output)) if self.pgspecial.timing_enabled: print('Command Time: %0.03fs' % duration) print('Format Time: %0.03fs' % total) # Refresh the table names and column names if necessary. if need_completion_refresh(document.text): self.refresh_completions() # Refresh search_path to set default schema. if need_search_path_refresh(document.text): logger.debug('Refreshing search path') completer.set_search_path(pgexecute.search_path()) logger.debug('Search path: %r', completer.search_path) query = Query(document.text, successful, mutating) self.query_history.append(query) except EOFError: print('Goodbye!') finally: # Reset the less opts back to original. logger.debug('Restoring env var LESS to %r.', original_less_opts) os.environ['LESS'] = original_less_opts
# -*- coding: utf-8 -*- """Main module.""" from prompt_toolkit import Application from http_cli_lib.layout.main_layout import layout from logging.config import dictConfig from http_cli_lib.logger import logging_config from http_cli_lib.key_bindins.kbs import global_kb as kb from prompt_toolkit.enums import EditingMode dictConfig(logging_config) app = Application(full_screen=True, layout=layout, key_bindings=kb, editing_mode=EditingMode.VI)
def run_cli(self): sqlexecute = self.sqlexecute logger = self.logger original_less_opts = self.adjust_less_opts() self.set_pager_from_config() self.initialize_completions() completer = self.completer def set_key_bindings(value): if value not in ('emacs', 'vi'): value = 'emacs' self.key_bindings = value project_root = os.path.dirname(PACKAGE_ROOT) author_file = os.path.join(project_root, 'AUTHORS') sponsor_file = os.path.join(project_root, 'SPONSORS') key_binding_manager = mycli_bindings( get_key_bindings=lambda: self.key_bindings, set_key_bindings=set_key_bindings) print('Version:', __version__) print('Chat: https://gitter.im/dbcli/mycli') print('Mail: https://groups.google.com/forum/#!forum/mycli-users') print('Home: http://mycli.net') print('Thanks to the contributor -', thanks_picker([author_file, sponsor_file])) def prompt_tokens(cli): return [(Token.Prompt, self.get_prompt(self.prompt_format))] get_toolbar_tokens = create_toolbar_tokens_func( lambda: self.key_bindings) layout = create_default_layout( lexer=MyCliLexer, reserve_space_for_menu=True, multiline=True, get_prompt_tokens=prompt_tokens, get_bottom_toolbar_tokens=get_toolbar_tokens, display_completions_in_columns=self.wider_completion_menu, extra_input_processors=[ ConditionalProcessor( processor=HighlightMatchingBracketProcessor( chars='[](){}'), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone()), ]) buf = CLIBuffer(always_multiline=self.multi_line, completer=completer, history=FileHistory( os.path.expanduser('~/.mycli-history')), complete_while_typing=Always()) application = Application( style=style_factory(self.syntax_style, self.cli_style), layout=layout, buffer=buf, key_bindings_registry=key_binding_manager.registry, on_exit=AbortAction.RAISE_EXCEPTION, ignore_case=True) cli = CommandLineInterface(application=application, eventloop=create_eventloop()) try: while True: document = cli.run() special.set_expanded_output(False) # The reason we check here instead of inside the sqlexecute is # because we want to raise the Exit exception which will be # caught by the try/except block that wraps the # sqlexecute.run() statement. if quit_command(document.text): raise EOFError try: document = self.handle_editor_command(cli, document) except RuntimeError as e: logger.error("sql: %r, error: %r", document.text, e) logger.error("traceback: %r", traceback.format_exc()) self.output(str(e), err=True, fg='red') continue if self.destructive_warning: destroy = confirm_destructive_query(document.text) if destroy is None: pass # Query was not destructive. Nothing to do here. elif destroy is True: self.output('Your call!') else: self.output('Wise choice!') continue # Keep track of whether or not the query is mutating. In case # of a multi-statement query, the overall query is considered # mutating if any one of the component statements is mutating mutating = False try: logger.debug('sql: %r', document.text) if self.logfile: self.logfile.write('\n# %s\n' % datetime.now()) self.logfile.write(document.text) self.logfile.write('\n') successful = False start = time() res = sqlexecute.run(document.text) duration = time() - start successful = True output = [] total = 0 for title, cur, headers, status in res: logger.debug("headers: %r", headers) logger.debug("rows: %r", cur) logger.debug("status: %r", status) start = time() threshold = 1000 if (is_select(status) and cur and cur.rowcount > threshold): self.output( 'The result set has more than %s rows.' % threshold, fg='red') if not click.confirm('Do you want to continue?'): self.output("Aborted!", err=True, fg='red') break output.extend( format_output(title, cur, headers, status, self.table_format)) end = time() total += end - start mutating = mutating or is_mutating(status) except KeyboardInterrupt: # Restart connection to the database sqlexecute.connect() logger.debug("cancelled query, sql: %r", document.text) self.output("cancelled query", err=True, fg='red') except NotImplementedError: self.output('Not Yet Implemented.', fg="yellow") except OperationalError as e: logger.debug("Exception: %r", e) reconnect = True if (e.args[0] in (2003, 2006, 2013)): reconnect = click.prompt( 'Connection reset. Reconnect (Y/n)', show_default=False, type=bool, default=True) if reconnect: logger.debug('Attempting to reconnect.') try: sqlexecute.connect() logger.debug('Reconnected successfully.') self.output( 'Reconnected!\nTry the command again.', fg='green') except OperationalError as e: logger.debug('Reconnect failed. e: %r', e) self.output(str(e), err=True, fg='red') continue # If reconnection failed, don't proceed further. else: # If user chooses not to reconnect, don't proceed further. continue else: logger.error("sql: %r, error: %r", document.text, e) logger.error("traceback: %r", traceback.format_exc()) self.output(str(e), err=True, fg='red') except Exception as e: logger.error("sql: %r, error: %r", document.text, e) logger.error("traceback: %r", traceback.format_exc()) self.output(str(e), err=True, fg='red') else: try: self.output_via_pager('\n'.join(output)) except KeyboardInterrupt: pass if special.is_timing_enabled(): self.output('Command Time: %0.03fs' % duration) self.output('Format Time: %0.03fs' % total) # Refresh the table names and column names if necessary. if need_completion_refresh(document.text): self.refresh_dynamic_completions() query = Query(document.text, successful, mutating) self.query_history.append(query) except EOFError: self.output('Goodbye!') finally: # Reset the less opts back to original. logger.debug('Restoring env var LESS to %r.', original_less_opts) os.environ['LESS'] = original_less_opts os.environ['PAGER'] = special.get_original_pager()
class UI(Client): def __init__(self, username: str, password: str): super().__init__(username, password, handle_data=DataFormat.ANSI) self.commands = [] self.output_buffer = Buffer_() self.cursor_pos = 0 self.chat_buffer = Buffer_() self.output = BufferControl(self.output_buffer, input_processors=[FormatText()], include_default_input_processors=True) self.chat = BufferControl(self.chat_buffer, input_processors=[FormatText()], include_default_input_processors=True) self.hide_ip = "--hide-ip" in sys.argv self.suggest = AutoSuggestFromLogs([ CommandSuggest(), ]) self.input = TextArea(height=1, prompt=" >> ", multiline=False, wrap_lines=False, accept_handler=self.accept, auto_suggest=self.suggest, dont_extend_width=True) self.host_ip = FormattedTextControl(ANSI("")) self.chat_float = Float(Frame(Window(self.chat, wrap_lines=True)), right=1, top=0, width=40, height=12, hide_when_covering_content=True) self.text = "" self.chat_text = "" def set_frame_size(fn): def inner(*args): size = self.app.output.get_size() self.chat_float.width = size.columns // 3 self.chat_float.height = size.rows // 2 return fn(*args) return inner self.out_window = Window(self.output, wrap_lines=True) kb = KeyBindings() @kb.add('c-c') @kb.add('c-q') def _(_): self.app.exit() self._loop = False self.run_again = False @kb.add('c-i', filter=has_focus(self.input)) def __(_): fut = self.suggest.get_suggestion_future(self.input.buffer, self.input.document) text = self.input.text def set_input(fut_2): res = fut_2.result() if res is not None: self.input.text = text + res.text self.input.document = Document(self.input.text, cursor_position=len( self.input.text)) fut.add_done_callback(set_input) @kb.add(Keys.ScrollUp) def sup(_): self.output_buffer.cursor_up(1) self.out_window._scroll_up() # pylint: disable=protected-access @kb.add(Keys.ScrollDown) def sdown(_): self.output_buffer.cursor_down(1) self.out_window._scroll_down() # pylint: disable=protected-access self.app = Application( layout=Layout( container=HSplit([ Frame( FloatContainer(self.out_window, floats=[self.chat_float])), Frame( VSplit([ self.input, Window(self.host_ip, align=WindowAlign.RIGHT, dont_extend_width=True) ])) ]), focused_element=self.input, ), full_screen=True, mouse_support=True, enable_page_navigation_bindings=True, key_bindings=merge_key_bindings([kb]), paste_mode=True, ) self.app._on_resize = set_frame_size(self.app._on_resize) # pylint: disable=protected-access self.run_again = True self.loop = get_event_loop() self._loop = False self.own_pass = "" self.own_ip = "" self.current_ip = "" # patch_stdout() @classmethod def create(cls) -> 'UI': user = prompt("Username: "******"Password: "******"{Fore.BLUE}[BROADCAST]{Fore.RESET} {converted_color_codes(e.msg)}" ) else: self.set_output(converted_color_codes(e.msg)) def event_error(self, e: ErrorEvent): self.err(e.error) @staticmethod def sanitize(arg: str) -> ANSI: return to_formatted_text(ANSI(arg)) def err(self, message: str): self.set_output( f"{Fore.RED}{converted_color_codes(message)}{Fore.RESET}") def set_chat_output(self, text: str): new_text = (self.chat_text + "\n" + text).strip() self.chat_buffer.set_text(new_text) self.chat_text = new_text.replace("\t", " ") def set_output(self, text: str): new_text = (self.text + "\n" + text).strip() self.output_buffer.set_text(new_text) self.text = new_text.replace("\t", " ") self.cursor_pos = len(self.text) def clear_chat(self): self.chat_buffer.set_text("") self.chat_text = "" def clear(self): self.output_buffer.set_text("") self.text = "" def accept(self, _): if self.input.text.strip(): self.set_output(f"\n>> {self.input.text}") self.commands.append(self.input.text) self.suggest.last_command(self.input.text) self.input.text = "" async def get_host_data(self): data = await self.command("pass see -l") self.own_pass = data.msg sys_info = await self.command('specs -l') self.current_ip = self.own_ip = re.search( r"(?P<ip>\d{1,3}(\.\d{1,3}){3,4})", sys_info.msg).group("ip") def launch(self): colorama.init() use_asyncio_event_loop() patch_stdout() while self.run_again: self.run_again = False self._loop = True self.loop.create_task(self.start()) try: self.loop.run_until_complete( self.app.run_async().to_asyncio_future()) except KeyboardInterrupt: if self.current_ip != self.own_ip: self.loop.run_until_complete(self.command("dc")) async def event_ready(self): o_text = self.output_buffer.text await self.get_host_data() text = (( f"{Fore.YELLOW}{self.own_ip} - {self.own_pass}{Fore.RESET} " if self.own_ip == self.current_ip else f"{Fore.YELLOW}{self.current_ip} / {self.own_ip} - {self.own_pass}{Fore.RESET} " ) if not self.hide_ip else "") self.host_ip.text = self.sanitize(text) self.clear() self.set_output(o_text) macros = MacroHolder() while self._loop: # TODO: Update these when they change macros.macros["self"] = self.own_ip macros.macros["pass"] = self.own_pass while not self.commands: await asyncio.sleep(0.1) try: line = self.commands.pop(0).strip() line = macros.parse(line) command, *args = line.split() if command == "chats": if len(args) == 1 and args[0] == "clear": self.clear_chat() else: await self.command(" ".join([command, *args])) elif command == "macro": if args and args[0] in ("add", "remove", "list"): sub = args.pop(0) if sub == "add": if len(args) >= 2: macros += args[0], " ".join(args[1:]) else: self.set_output( "Usage: macro add <name> <value>") elif sub == "remove": if args: macros -= args[0] else: self.set_output("Usage: macro remove <name>") else: self.set_output("Macros:") for key in sorted(list(macros)): self.set_output(f"${key} -> {macros[key]}") else: self.set_output("Usage: macro [add/remove/list] ...") elif command == "clear": self.clear() elif command == "quit": self._loop = False self.run_again = False self.stop() self.app.exit() else: await self.command(" ".join([command, *args])) except Exception as e: # pylint: disable=broad-except self.err(repr(e))
def _build_cli(self, history): key_binding_manager = cli_bindings() def prompt_tokens(cli): prompt = self.get_prompt(self.prompt) if len(prompt) > self.MAX_LEN_PROMPT: prompt = self.get_prompt('\\r:\\d> ') return [(Token.Prompt, prompt)] def get_continuation_tokens(cli, width): prompt = self.get_prompt(self.prompt_continuation_format) token = (Token.Continuation, ' ' * (width - len(prompt)) + prompt) return [token] def show_suggestion_tip(): return self.iterations < 2 get_toolbar_tokens = create_toolbar_tokens_func( self.completion_refresher.is_refreshing, show_suggestion_tip) layout = create_prompt_layout( lexer=Lexer, multiline=True, get_prompt_tokens=prompt_tokens, get_continuation_tokens=get_continuation_tokens, get_bottom_toolbar_tokens=get_toolbar_tokens, display_completions_in_columns=False, extra_input_processors=[ ConditionalProcessor( processor=HighlightMatchingBracketProcessor( chars='[](){}'), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone()) ], reserve_space_for_menu=self.get_reserved_space()) with self._completer_lock: buf = CLIBuffer(always_multiline=self.multi_line, completer=self.completer, history=history, auto_suggest=AutoSuggestFromHistory(), complete_while_typing=Always(), accept_action=AcceptAction.RETURN_DOCUMENT) if self.key_bindings == 'vi': editing_mode = EditingMode.VI else: editing_mode = EditingMode.EMACS application = Application( style=style_from_pygments(style_cls=self.output_style), layout=layout, buffer=buf, key_bindings_registry=key_binding_manager.registry, on_exit=AbortAction.RAISE_EXCEPTION, on_abort=AbortAction.RETRY, editing_mode=editing_mode, ignore_case=True) cli = CommandLineInterface(application=application, eventloop=create_eventloop()) return cli
def run(): app = Application(full_screen=True, mouse_support=True, key_bindings=kb, layout=main_layout) app.run()
buf.text = new_text @kb.add('c-e') def edit_http(event): if layout.has_focus(request_buffer): request_buffer.open_in_editor() if layout.has_focus(response_buffer): response_buffer.open_in_editor() response_buffer.tempfile_suffix = get_extention(ApplicationState.response_history[-1]) @kb.add('c-@') def send_request(event): response = send_raw_request(request_buffer.text) response_buffer.text = format_raw_response(response) ApplicationState.response_history.append(response) @kb.add('c-c') def exit_for_real(event): event.app.exit() class ApplicationState: response_history = [] app = Application(layout=layout, full_screen=True, key_bindings=kb, editing_mode=EditingMode.VI, mouse_support=True) app.run()
Window(height=4, content=BufferControl(buffer=buffer1))], key_bindings=kb_search, ), floats=[ Float( xcursor=True, ycursor=True, content=CompletionsMenu(max_height=3, scroll_offset=1), ) ], ) # Put it all together root_container = HSplit([searchbar, output, infoFrame]) layout = Layout(root_container) app = Application(layout=layout, full_screen=True, key_bindings=kb) # These are app-wide stateful variables; not sure how to structure things. app.ads_q = None # either None or ads.SearchQuery app.ads_page = 0 # current page app.ads_item_idx = 0 # current item index within page app.NITEMS = 5 # number of items per page app.pages = None # chunked list of articles (list of lists) tidy_author = lambda x: [] if x is None else x tidy_title = lambda x: ["NO TITLE AVAILABLE"] if x is None else x def format_article_info(article): """Format current article's info for infoFrame""" return HTML(f"<b>{html.escape(tidy_title(article.title)[0])}</b>\n"
def __init__(self, filepath): self.db = Database(filepath) cursor = FormattedTextControl(focusable=True, text=[("", CURSOR)], show_cursor=False) sep = Window(width=len(SEPARATOR), char=SEPARATOR, style="class:line") self.ids = Column("ID") self.names = Column("Name") self.sources = Column("Source") self.tags = Column("Tags") self.urls = Column("URL") table_header = VSplit([ Label(text="", width=len(CURSOR)), sep, Label(self.ids.title, width=self.ids.width, style="bold"), sep, Label(self.names.title, width=self.names.width, style="bold"), sep, Label(self.tags.title, width=self.tags.width, style="bold"), sep, Label(self.sources.title, width=self.sources.width, style="bold"), sep, Label(self.urls.title, width=self.urls.width, style="bold"), ]) self.selection = Window(cursor, width=len(CURSOR), style="class:selector") table_body = VSplit([ self.selection, sep, Window(self.ids.col, width=self.ids.width), sep, Window(self.names.col, width=self.names.width), sep, Window(self.tags.col, width=self.tags.width), sep, Window(self.sources.col, width=self.sources.width), sep, Window(self.urls.col, width=self.urls.width), ]) self.prompt = TextArea( multiline=False, focusable=True, accept_handler=self._do_search, get_line_prefix=self._get_prompt, ) table = HSplit([table_header, table_body]) layout = HSplit([table, self.prompt]) kb = KeyBindings() @kb.add("c-c", eager=True) @kb.add("q", filter=has_focus(self.selection)) def close(event): event.app.exit() @kb.add("s", filter=has_focus(self.selection)) def start_search(event): event.app.layout.focus(self.prompt) @kb.add("o", filter=has_focus(self.selection)) @kb.add(Keys.Enter, filter=has_focus(self.selection)) def open_link(event): cursor = self.selection.content.text idx = len(cursor) selected = self.ids.col.text[idx - 1] link_id = int(selected[1]) Link.open(self.db, link_id) @kb.add(Keys.Down, filter=has_focus(self.selection)) def next_item(event): cursor = self.selection.content.text idx = len(cursor) max_idx = len(self.ids.col.text) if idx + 1 > max_idx: return cursor.insert(0, ("", "\n")) @kb.add(Keys.Up, filter=has_focus(self.selection)) def prev_item(event): cursor = self.selection.content.text idx = len(cursor) if idx == 1: return cursor.pop(0) self.app = Application(layout=Layout(layout), key_bindings=kb)
class LinkTable: def __init__(self, filepath): self.db = Database(filepath) cursor = FormattedTextControl(focusable=True, text=[("", CURSOR)], show_cursor=False) sep = Window(width=len(SEPARATOR), char=SEPARATOR, style="class:line") self.ids = Column("ID") self.names = Column("Name") self.sources = Column("Source") self.tags = Column("Tags") self.urls = Column("URL") table_header = VSplit([ Label(text="", width=len(CURSOR)), sep, Label(self.ids.title, width=self.ids.width, style="bold"), sep, Label(self.names.title, width=self.names.width, style="bold"), sep, Label(self.tags.title, width=self.tags.width, style="bold"), sep, Label(self.sources.title, width=self.sources.width, style="bold"), sep, Label(self.urls.title, width=self.urls.width, style="bold"), ]) self.selection = Window(cursor, width=len(CURSOR), style="class:selector") table_body = VSplit([ self.selection, sep, Window(self.ids.col, width=self.ids.width), sep, Window(self.names.col, width=self.names.width), sep, Window(self.tags.col, width=self.tags.width), sep, Window(self.sources.col, width=self.sources.width), sep, Window(self.urls.col, width=self.urls.width), ]) self.prompt = TextArea( multiline=False, focusable=True, accept_handler=self._do_search, get_line_prefix=self._get_prompt, ) table = HSplit([table_header, table_body]) layout = HSplit([table, self.prompt]) kb = KeyBindings() @kb.add("c-c", eager=True) @kb.add("q", filter=has_focus(self.selection)) def close(event): event.app.exit() @kb.add("s", filter=has_focus(self.selection)) def start_search(event): event.app.layout.focus(self.prompt) @kb.add("o", filter=has_focus(self.selection)) @kb.add(Keys.Enter, filter=has_focus(self.selection)) def open_link(event): cursor = self.selection.content.text idx = len(cursor) selected = self.ids.col.text[idx - 1] link_id = int(selected[1]) Link.open(self.db, link_id) @kb.add(Keys.Down, filter=has_focus(self.selection)) def next_item(event): cursor = self.selection.content.text idx = len(cursor) max_idx = len(self.ids.col.text) if idx + 1 > max_idx: return cursor.insert(0, ("", "\n")) @kb.add(Keys.Up, filter=has_focus(self.selection)) def prev_item(event): cursor = self.selection.content.text idx = len(cursor) if idx == 1: return cursor.pop(0) self.app = Application(layout=Layout(layout), key_bindings=kb) def run(self): self._do_search() self.app.run() def _do_search(self, inpt: Buffer = None): self.selection.content.text = [("", CURSOR)] self.ids.clear() self.names.clear() self.tags.clear() self.sources.clear() self.urls.clear() name = None tags = None if inpt is not None and len(inpt.text) > 0: terms = inpt.text.split(" ") tags = [t.replace("#", "") for t in terms if t.startswith("#")] name = " ".join(n for n in terms if not n.startswith("#")) links = Link.search(self.db, name=name, top=10, tags=tags, sort="visits") for idx, link in enumerate(links): newline = "\n" if idx < len(links) - 1 else "" self.ids.col.text.append(("", f"{link.id}{newline}")) self.names.col.text.append(("", f"{link.name}{newline}")) self.urls.col.text.append(("", f"{link.url_expanded}{newline}")) tags = ", ".join(f"#{t.name}" for t in link.tags) self.tags.col.text.append(("", f"{tags}{newline}")) source = "" if not link.source else link.source.name self.sources.col.text.append(("", f"{source}{newline}")) self.app.layout.focus(self.selection) def _get_prompt(self, line_no, other): if has_focus(self.prompt)(): return "Search: " return "[s]earch | [o]pen | [q]uit"
def create_app(self): app = Application(key_bindings=self.kb,layout=self.layout, full_screen=True) app.before_render = self return app
async def init(): global root global chat_container global app global log_buf global log_win global input_buf global input_win global convos global status_bar global status_label global client global convo_stack global websocket global app global uri global websocket global ws_handler uri = "ws://localhost:15555" ws_handler = handler(uri) await ws_handler.connect() # message area log_buf = Buffer(document=Document()) log_win = Window(BufferControl(log_buf), wrap_lines=True) # input area input_buf = Buffer(document=Document()) input_win = Window(BufferControl(input_buf), height=1, wrap_lines=True) # status bar status_bar = FormattedTextToolbar( text=HTML("<b>Chatting with: Loading </b>"), style="bg:ansired fg:ansiblack") status_label = Label(text="[ 00:29 ] ", width=10) # call backs input_buf.accept_handler = accept_message input_buf.on_text_changed += resize_input log_buf.on_text_changed += auto_scroll convos = convo_list_widget() chat_container = HSplit( [log_win, status_bar, VSplit([status_label, input_win])]) root = VSplit([ convos, chat_container, ]) style = Style.from_dict( {"select-box cursor-line": "nounderline bg:ansired fg:ansiwhite"}) app = Application(editing_mode=EditingMode.VI, key_bindings=kb, layout=Layout(chat_container), full_screen=True, style=style) app.invalidate() app.layout.focus(input_buf) ViState._input_mode = InputMode.INSERT ViState.input_mode = property(get_input_mode, set_input_mode) asyncio.ensure_future(ws_handler.listen()) asyncio.ensure_future(ws_handler.command(('get_convo', 'all'))) auto_scroll(log_buf) await app.run_async()
height=4) root_container = HSplit([ content_container, # HorizontalLine(), #Window(height=1, char='-'), commandWindowFrame ]) layout = Layout(root_container) #call 'before render'-function only when app is started the first time #=> sets content to pod window started = False def before_render(application): global started if started == False: updateState() started = True if args.no_help == False: executeCommand("help") app = Application(layout=layout, key_bindings=kb, full_screen=True, mouse_support=enableMouseSupport, before_render=before_render) app.run()
def loop(cmd, history_file): def session_toolbar(cli): return _get_toolbar_tokens(cmd.is_conn_available, cmd.username, cmd.connection.client.active_servers) key_binding_manager = KeyBindingManager( enable_search=True, enable_abort_and_exit_bindings=True, enable_system_bindings=True, enable_open_in_editor=True) bind_keys(key_binding_manager.registry) layout = create_layout( message='cr> ', multiline=True, lexer=SqlLexer, extra_input_processors=[ ConditionalProcessor( processor=HighlightMatchingBracketProcessor(chars='[](){}'), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone()) ], get_bottom_toolbar_tokens=session_toolbar) application = Application( layout=layout, buffer=create_buffer(cmd, history_file), style=PygmentsStyle.from_defaults(pygments_style_cls=CrateStyle), key_bindings_registry=key_binding_manager.registry, editing_mode=_get_editing_mode(), on_exit=AbortAction.RAISE_EXCEPTION, on_abort=AbortAction.RETRY, ) eventloop = create_eventloop() output = create_output() cli = CommandLineInterface(application=application, eventloop=eventloop, output=output) def get_num_columns_override(): return output.get_size().columns cmd.get_num_columns = get_num_columns_override while True: try: doc = cli.run(reset_current_buffer=True) if doc: cmd.process(doc.text) except ProgrammingError as e: if '401' in e.message: username = cmd.username password = cmd.password cmd.username = input('Username: '******'Bye!') return
class PybreakGui(Bdb): def __init__(self): super().__init__() self.paused = True self.app_thread = threading.Thread(target=self.start_gui, args=(asyncio.get_event_loop(),)) self.frame_history = FrameHistory() self.search_toolbar = SearchToolbar( text_if_not_searching=[("class:not-searching", "Press '/' to start searching.")] ) def get_view_file(): if len(self.frame_history.history) > 0: return self.frame_history.hist_frame.filename return ".py" self.text_area = TextArea( lexer=DynamicLexer( lambda: PygmentsLexer.from_filename( get_view_file(), sync_from_start=False ) ), search_field=self.search_toolbar, scrollbar=True, line_numbers=True, ) self.container = HSplit( [ self.text_area, self.search_toolbar, ] ) kb = KeyBindings() @kb.add("c-q") def _(event: KeyPressEvent): self.paused = False self._quit() @kb.add("c-n") def _(event): self.set_next(self.frame_history.exec_frame.raw_frame) self.paused = False # allow another frame to be processed self.app = Application( full_screen=True, layout=Layout(container=self.container), key_bindings=kb, ) self.app.loop = asyncio.get_event_loop() def start_gui(self, loop): asyncio.set_event_loop(loop) self.app.run() self.text_area.buffer.insert_text("HELLO WORLD") def start(self, frame): self.app_thread.start() super().set_trace(frame) def _quit(self): sys.settrace(None) self.quitting = True self.app.exit() def user_call(self, frame: types.FrameType, argument_list): # if self.stop_here(frame): # self.frame_history.append(frame) pass def user_line(self, frame: types.FrameType): """ This method is called from dispatch_line() when either stop_here() or break_here() yields True. i.e. when we stop OR break at this line. * stop_here() yields true if the frame lies below the frame where debugging started on the call stack. i.e. it will be called for every line after we start debugging. * break_here() yields true only if there's a breakpoint for this line """ self.text_area.buffer.insert_text(f"FRAME = {frame.f_code.co_filename}:{frame.f_lineno}") if self.stop_here(frame): self.text_area.buffer.insert_text(str(frame.f_code.co_filename) + str(frame.f_lineno) + "\n") self.frame_history.append(frame) while self.paused: time.sleep(.1) self.paused = True
Float( xcursor=True, ycursor=True, content=CompletionsMenu(max_height=16, scroll_offset=1), ), ], key_bindings=kb, ) layout = Layout(root_container) app: Application = Application( layout=layout, full_screen=True, mouse_support=True, style=style, enable_page_navigation_bindings=True, color_depth=ColorDepth.DEPTH_8_BIT, ) def start(argv=None): global current_file global isort_config argv = sys.argv if argv is None else argv if len(sys.argv) > 2: sys.exit("Usage: qpython [filename]") elif len(sys.argv) == 2: current_file = Path(sys.argv[1]).resolve() isort_config = isort.Config(settings_path=current_file.parent)
def run(self): labels = self.neo4j.get_labels() relationship_types = self.neo4j.get_relationship_types() properties = self.neo4j.get_property_keys() if self.filename: queries = self.filename.read() queries = queries.split(";")[:-1] for query in queries: query += ";" query = query.strip() print("> " + query) self.handle_query(query) print() return click.secho(" ______ __ __ ______ __ __ ", fg="red") click.secho("/\ ___\ /\ \_\ \ /\ ___\ /\ \ /\ \ ", fg="yellow") click.secho("\ \ \____ \ \____ \ \ \ \____ \ \ \____ \ \ \ ", fg="green") click.secho(" \ \_____\ \/\_____\ \ \_____\ \ \_____\ \ \_\ ", fg="blue") click.secho(" \/_____/ \/_____/ \/_____/ \/_____/ \/_/ ", fg="magenta") msg = "\nUsing Bolt." if self.neo4j.graph.address.bolt else "" print(msg) print("Version: {}".format(__version__)) print("Bug reports: https://github.com/nicolewhite/cycli/issues\n") completer = CypherCompleter(labels, relationship_types, properties) layout = create_prompt_layout( lexer=CypherLexer, get_prompt_tokens=get_tokens, reserve_space_for_menu=8, ) buff = CypherBuffer( accept_action=AcceptAction.RETURN_DOCUMENT, history=FileHistory( filename=os.path.expanduser('~/.cycli_history')), completer=completer, complete_while_typing=True, ) application = Application(style=PygmentsStyle(CypherStyle), buffer=buff, layout=layout, on_exit=AbortAction.RAISE_EXCEPTION, key_bindings_registry=CypherBinder.registry) cli = CommandLineInterface(application=application, eventloop=create_eventloop()) try: while True: document = cli.run() query = document.text self.handle_query(query) except UserWantsOut: print("Goodbye!") except Exception as e: print(e)
def __init__(self, username: str, password: str): super().__init__(username, password, handle_data=DataFormat.ANSI) self.commands = [] self.output_buffer = Buffer_() self.cursor_pos = 0 self.chat_buffer = Buffer_() self.output = BufferControl(self.output_buffer, input_processors=[FormatText()], include_default_input_processors=True) self.chat = BufferControl(self.chat_buffer, input_processors=[FormatText()], include_default_input_processors=True) self.hide_ip = "--hide-ip" in sys.argv self.suggest = AutoSuggestFromLogs([ CommandSuggest(), ]) self.input = TextArea(height=1, prompt=" >> ", multiline=False, wrap_lines=False, accept_handler=self.accept, auto_suggest=self.suggest, dont_extend_width=True) self.host_ip = FormattedTextControl(ANSI("")) self.chat_float = Float(Frame(Window(self.chat, wrap_lines=True)), right=1, top=0, width=40, height=12, hide_when_covering_content=True) self.text = "" self.chat_text = "" def set_frame_size(fn): def inner(*args): size = self.app.output.get_size() self.chat_float.width = size.columns // 3 self.chat_float.height = size.rows // 2 return fn(*args) return inner self.out_window = Window(self.output, wrap_lines=True) kb = KeyBindings() @kb.add('c-c') @kb.add('c-q') def _(_): self.app.exit() self._loop = False self.run_again = False @kb.add('c-i', filter=has_focus(self.input)) def __(_): fut = self.suggest.get_suggestion_future(self.input.buffer, self.input.document) text = self.input.text def set_input(fut_2): res = fut_2.result() if res is not None: self.input.text = text + res.text self.input.document = Document(self.input.text, cursor_position=len( self.input.text)) fut.add_done_callback(set_input) @kb.add(Keys.ScrollUp) def sup(_): self.output_buffer.cursor_up(1) self.out_window._scroll_up() # pylint: disable=protected-access @kb.add(Keys.ScrollDown) def sdown(_): self.output_buffer.cursor_down(1) self.out_window._scroll_down() # pylint: disable=protected-access self.app = Application( layout=Layout( container=HSplit([ Frame( FloatContainer(self.out_window, floats=[self.chat_float])), Frame( VSplit([ self.input, Window(self.host_ip, align=WindowAlign.RIGHT, dont_extend_width=True) ])) ]), focused_element=self.input, ), full_screen=True, mouse_support=True, enable_page_navigation_bindings=True, key_bindings=merge_key_bindings([kb]), paste_mode=True, ) self.app._on_resize = set_frame_size(self.app._on_resize) # pylint: disable=protected-access self.run_again = True self.loop = get_event_loop() self._loop = False self.own_pass = "" self.own_ip = "" self.current_ip = ""
class Client: def __init__(self, url: str = "127.0.0.1", port: int = "9999"): self.communicator = Communicator(url, port) self.CMDIN = CommandInput(title="DLNest Command Line(F1)", onAccept=self.onCommandAccept) self.w1 = self.CMDIN.getWindow() self.DLOutput = ResultsOutput(routineTask=self.routineTaskDLOutput, title="DLNest Output (F2)", style="class:dlnest_output") self.w2 = self.DLOutput.getWindow() self.ANOutput = AnalyzeOutput(routineTask=self.routineTaskANOutput, title="Analyzer Output (F3)", style="class:analyzer_output") self.w3 = self.ANOutput.getWindow() self.analyzeTaskID = "" self.TaskInfo = TaskInfoShower(routineTask=self.routineTaskInfo, title="Tasks (F4)") self.w4 = self.TaskInfo.getWindow() self.DevicesInfo = DevicesInfoShower( routineTask=self.routineTaskDevices, title="Devices (F5)") self.w5 = self.DevicesInfo.getWindow() self.container_fat = HSplit( [self.w1, VSplit([self.w2, self.w3]), VSplit([self.w4, self.w5])]) self.container_tall = HSplit( [self.w1, self.w2, self.w3, self.w4, self.w5]) self.kb = KeyBindings() @self.kb.add('c-c') def exit_(event): event.app.exit() @self.kb.add('f1') def focus1(event): event.app.layout.focus(self.w1) @self.kb.add('f2') def focus2(event): event.app.layout.focus(self.w2) @self.kb.add('f3') def focus3(event): event.app.layout.focus(self.w3) @self.kb.add('f4') def focus4(event): event.app.layout.focus(self.w4) @self.kb.add('f5') def focus5(event): event.app.layout.focus(self.w5) self.style = Style.from_dict({ "frame.border": "fg:#ffb6c1", "frame.title": "fg:#1ef0ff", "command_frame": "bg:#008b8b", "dlnest_output": "bg:#451a4a", "analyzer_output": "bg:#451a4a", "analyzer_info_label": "bg:#da70d6", "analyzer_info_text1": "bg:#3f3f00", "analyzer_info_text2": "bg:#ff00ff", "running_task_status": "bg:#a01010 bold", "running_task_id": "bg:#303030", "running_task_gpu": "bg:#556b2f", "running_task_des": "bg:#c71585", "running_task_time": "bg:#2e3b37", "pending_task_status": "bg:#1010a0 bold", "pending_task_id": "bg:#303030", "pending_task_gpu": "bg:#556b2f", "pending_task_des": "bg:#c71585", "pending_task_time": "bg:#2e3b37", "suspend_task_status": "bg:#10a010 bold", "suspend_task_id": "bg:#303030", "suspend_task_gpu": "bg:#556b2f", "suspend_task_des": "bg:#c71585", "suspend_task_time": "bg:#2e3b37", "task_info_shower": "bg:#008bc0", "devices_info_shower": "bg:#008bc0", "devices_id": "bg:#303030", "devices_status_valid": "bg:#3cb371 bold", "devices_status_break": "bg:#a01010 bold", "devices_free_memory": "bg:#556b2f", "devices_tasks": "bg:#c71585" }) self.layout = Layout(self.container_fat, focused_element=self.w1) self.app = Application(key_bindings=self.kb, layout=self.layout, full_screen=True, style=self.style) self.app._on_resize = self.on_resize def on_resize(self): cols, rows = os.get_terminal_size(0) focused_element = self.layout.current_window if cols >= 2 * rows: # fat self.app.layout = Layout(self.container_fat, focused_element=focused_element) else: # tall self.app.layout = Layout(self.container_tall, focused_element=focused_element) self.app.renderer.erase(leave_alternate_screen=False) self.app._request_absolute_cursor_position() self.app._redraw() def getApp(self): return self.app def onCommandAccept(self, s: str): commandWordList = s.split(" ") while "" in commandWordList: commandWordList.remove("") if commandWordList[0] == "watch": self.analyzeTaskID = commandWordList[1] elif commandWordList[0] == "withdraw": self.analyzeTaskID = "" if commandWordList[0] == "runExp": if len(commandWordList) != 3: if self.analyzeTaskID != "": commandWordList = [ commandWordList[0], self.analyzeTaskID, commandWordList[1] ] else: return ret = self.communicator.giveACommand(commandWordList) if commandWordList[0] == "del": if ret["status"] == "success" and commandWordList[ 1] == self.analyzeTaskID: self.analyzeTaskID = "" if "exit" in ret: self.app.exit() def routineTaskDLOutput(self, obj): #for buffer fresh if not hasattr(obj, "_count_"): obj._count_ = 0 outStyledDict = self.communicator.giveACommand(["showDL", "-s"]) outPlainDict = self.communicator.giveACommand(["showDL"]) if "text" in outStyledDict and "text" in outPlainDict: try: obj.lexer.styled_text = outStyledDict["text"] obj.shower.text = outPlainDict["text"] except Exception as e: pass def routineTaskANOutput(self, obj): #for buffer fresh if not hasattr(obj, "_count_"): obj._count_ = 0 if self.analyzeTaskID == "": obj.lexer.styled_text = [] obj.shower.text = "" obj.infoText.text = [("", "No valid analyzer task is running")] obj.infoWindow.width = 33 return outStyledDict = self.communicator.giveACommand( ["showAN", "-t", self.analyzeTaskID, "-s"]) outPlainDict = self.communicator.giveACommand( ["showAN", "-t", self.analyzeTaskID]) if "text" in outStyledDict and "text" in outPlainDict: try: obj.lexer.styled_text = outStyledDict["text"] obj.shower.text = outPlainDict["text"] obj.infoText.text = [("class:analyzer_info_text1", self.analyzeTaskID)] obj.infoWindow.width = len(self.analyzeTaskID) except Exception as e: pass else: self.analyzeTaskID = "" def routineTaskInfo(self, obj): # for buffer fresh if not hasattr(obj, "_count_"): obj._count_ = 0 r = self.communicator.giveACommand(["showTask"]) if r["status"] != "success": obj.lexer.taskInfo = [] obj.shower.text = obj.lexer.get_text() return taskInfo = r["info"] try: obj.lexer.taskInfo = taskInfo obj.shower.text = obj.lexer.get_text() except Exception as e: pass def routineTaskDevices(self, obj): # for buffer fresh if not hasattr(obj, "_count_"): obj._count_ = 0 r = self.communicator.giveACommand(["showDevice"]) if r["status"] != "success": obj.lexer.devicesInfo = [] obj.shower.text = obj.lexer.get_text() return obj.lexer.devicesInfo = r["info"] try: obj.shower.text = obj.lexer.get_text() except Exception as e: pass
def _build_cli(self, history): def set_vi_mode(value): self.vi_mode = value key_binding_manager = pgcli_bindings( get_vi_mode_enabled=lambda: self.vi_mode, set_vi_mode_enabled=set_vi_mode) def prompt_tokens(_): if self.dsn_alias and self.prompt_dsn_format is not None: prompt_format = self.prompt_dsn_format else: prompt_format = self.prompt_format prompt = self.get_prompt(prompt_format) if (prompt_format == self.default_prompt and len(prompt) > self.max_len_prompt): prompt = self.get_prompt('\\d> ') return [(Token.Prompt, prompt)] def get_continuation_tokens(cli, width): continuation=self.multiline_continuation_char * (width - 1) + ' ' return [(Token.Continuation, continuation)] get_toolbar_tokens = create_toolbar_tokens_func( lambda: self.vi_mode, self.completion_refresher.is_refreshing, self.pgexecute.failed_transaction, self.pgexecute.valid_transaction) layout = create_prompt_layout( lexer=PygmentsLexer(PostgresLexer), reserve_space_for_menu=self.min_num_menu_lines, get_prompt_tokens=prompt_tokens, get_continuation_tokens=get_continuation_tokens, get_bottom_toolbar_tokens=get_toolbar_tokens, display_completions_in_columns=self.wider_completion_menu, multiline=True, extra_input_processors=[ # Highlight matching brackets while editing. ConditionalProcessor( processor=HighlightMatchingBracketProcessor(chars='[](){}'), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone()), ]) with self._completer_lock: buf = PGBuffer( auto_suggest=AutoSuggestFromHistory(), always_multiline=self.multi_line, multiline_mode=self.multiline_mode, completer=self.completer, history=history, complete_while_typing=Always(), accept_action=AcceptAction.RETURN_DOCUMENT) editing_mode = EditingMode.VI if self.vi_mode else EditingMode.EMACS application = Application( style=style_factory(self.syntax_style, self.cli_style), layout=layout, buffer=buf, key_bindings_registry=key_binding_manager.registry, on_exit=AbortAction.RAISE_EXCEPTION, on_abort=AbortAction.RETRY, ignore_case=True, editing_mode=editing_mode) cli = CommandLineInterface(application=application, eventloop=self.eventloop) return cli
def __init__(self, url: str = "127.0.0.1", port: int = "9999"): self.communicator = Communicator(url, port) self.CMDIN = CommandInput(title="DLNest Command Line(F1)", onAccept=self.onCommandAccept) self.w1 = self.CMDIN.getWindow() self.DLOutput = ResultsOutput(routineTask=self.routineTaskDLOutput, title="DLNest Output (F2)", style="class:dlnest_output") self.w2 = self.DLOutput.getWindow() self.ANOutput = AnalyzeOutput(routineTask=self.routineTaskANOutput, title="Analyzer Output (F3)", style="class:analyzer_output") self.w3 = self.ANOutput.getWindow() self.analyzeTaskID = "" self.TaskInfo = TaskInfoShower(routineTask=self.routineTaskInfo, title="Tasks (F4)") self.w4 = self.TaskInfo.getWindow() self.DevicesInfo = DevicesInfoShower( routineTask=self.routineTaskDevices, title="Devices (F5)") self.w5 = self.DevicesInfo.getWindow() self.container_fat = HSplit( [self.w1, VSplit([self.w2, self.w3]), VSplit([self.w4, self.w5])]) self.container_tall = HSplit( [self.w1, self.w2, self.w3, self.w4, self.w5]) self.kb = KeyBindings() @self.kb.add('c-c') def exit_(event): event.app.exit() @self.kb.add('f1') def focus1(event): event.app.layout.focus(self.w1) @self.kb.add('f2') def focus2(event): event.app.layout.focus(self.w2) @self.kb.add('f3') def focus3(event): event.app.layout.focus(self.w3) @self.kb.add('f4') def focus4(event): event.app.layout.focus(self.w4) @self.kb.add('f5') def focus5(event): event.app.layout.focus(self.w5) self.style = Style.from_dict({ "frame.border": "fg:#ffb6c1", "frame.title": "fg:#1ef0ff", "command_frame": "bg:#008b8b", "dlnest_output": "bg:#451a4a", "analyzer_output": "bg:#451a4a", "analyzer_info_label": "bg:#da70d6", "analyzer_info_text1": "bg:#3f3f00", "analyzer_info_text2": "bg:#ff00ff", "running_task_status": "bg:#a01010 bold", "running_task_id": "bg:#303030", "running_task_gpu": "bg:#556b2f", "running_task_des": "bg:#c71585", "running_task_time": "bg:#2e3b37", "pending_task_status": "bg:#1010a0 bold", "pending_task_id": "bg:#303030", "pending_task_gpu": "bg:#556b2f", "pending_task_des": "bg:#c71585", "pending_task_time": "bg:#2e3b37", "suspend_task_status": "bg:#10a010 bold", "suspend_task_id": "bg:#303030", "suspend_task_gpu": "bg:#556b2f", "suspend_task_des": "bg:#c71585", "suspend_task_time": "bg:#2e3b37", "task_info_shower": "bg:#008bc0", "devices_info_shower": "bg:#008bc0", "devices_id": "bg:#303030", "devices_status_valid": "bg:#3cb371 bold", "devices_status_break": "bg:#a01010 bold", "devices_free_memory": "bg:#556b2f", "devices_tasks": "bg:#c71585" }) self.layout = Layout(self.container_fat, focused_element=self.w1) self.app = Application(key_bindings=self.kb, layout=self.layout, full_screen=True, style=self.style) self.app._on_resize = self.on_resize
def run_cli(self): iterations = 0 sqlexecute = self.sqlexecute logger = self.logger self.configure_pager() if self.smart_completion: self.refresh_completions() author_file = os.path.join(PACKAGE_ROOT, 'AUTHORS') sponsor_file = os.path.join(PACKAGE_ROOT, 'SPONSORS') key_binding_manager = mycli_bindings() if not self.less_chatty: print('Version:', __version__) print('Chat: https://gitter.im/dbcli/mycli') print('Mail: https://groups.google.com/forum/#!forum/mycli-users') print('Home: http://mycli.net') print('Thanks to the contributor -', thanks_picker([author_file, sponsor_file])) def prompt_tokens(cli): prompt = self.get_prompt(self.prompt_format) if self.prompt_format == self.default_prompt and len(prompt) > self.max_len_prompt: prompt = self.get_prompt('\\d> ') return [(Token.Prompt, prompt)] def get_continuation_tokens(cli, width): continuation_prompt = self.get_prompt(self.prompt_continuation_format) return [(Token.Continuation, ' ' * (width - len(continuation_prompt)) + continuation_prompt)] def show_suggestion_tip(): return iterations < 2 def one_iteration(document=None): if document is None: document = self.cli.run() special.set_expanded_output(False) try: document = self.handle_editor_command(self.cli, document) except RuntimeError as e: logger.error("sql: %r, error: %r", document.text, e) logger.error("traceback: %r", traceback.format_exc()) self.echo(str(e), err=True, fg='red') return if not document.text.strip(): return if self.destructive_warning: destroy = confirm_destructive_query(document.text) if destroy is None: pass # Query was not destructive. Nothing to do here. elif destroy is True: self.echo('Your call!') else: self.echo('Wise choice!') return # Keep track of whether or not the query is mutating. In case # of a multi-statement query, the overall query is considered # mutating if any one of the component statements is mutating mutating = False try: logger.debug('sql: %r', document.text) special.write_tee(self.get_prompt(self.prompt_format) + document.text) if self.logfile: self.logfile.write('\n# %s\n' % datetime.now()) self.logfile.write(document.text) self.logfile.write('\n') successful = False start = time() res = sqlexecute.run(document.text) successful = True result_count = 0 for title, cur, headers, status in res: logger.debug("headers: %r", headers) logger.debug("rows: %r", cur) logger.debug("status: %r", status) threshold = 1000 if (is_select(status) and cur and cur.rowcount > threshold): self.echo('The result set has more than {} rows.'.format( threshold), fg='red') if not click.confirm('Do you want to continue?'): self.echo("Aborted!", err=True, fg='red') break if self.auto_vertical_output: max_width = self.cli.output.get_size().columns else: max_width = None formatted = self.format_output( title, cur, headers, special.is_expanded_output(), max_width) t = time() - start try: if result_count > 0: self.echo('') try: self.output(formatted, status) except KeyboardInterrupt: pass if special.is_timing_enabled(): self.echo('Time: %0.03fs' % t) except KeyboardInterrupt: pass start = time() result_count += 1 mutating = mutating or is_mutating(status) special.unset_once_if_written() except EOFError as e: raise e except KeyboardInterrupt: # get last connection id connection_id_to_kill = sqlexecute.connection_id logger.debug("connection id to kill: %r", connection_id_to_kill) # Restart connection to the database sqlexecute.connect() try: for title, cur, headers, status in sqlexecute.run('kill %s' % connection_id_to_kill): status_str = str(status).lower() if status_str.find('ok') > -1: logger.debug("cancelled query, connection id: %r, sql: %r", connection_id_to_kill, document.text) self.echo("cancelled query", err=True, fg='red') except Exception as e: self.echo('Encountered error while cancelling query: {}'.format(e), err=True, fg='red') except NotImplementedError: self.echo('Not Yet Implemented.', fg="yellow") except OperationalError as e: logger.debug("Exception: %r", e) if (e.args[0] in (2003, 2006, 2013)): logger.debug('Attempting to reconnect.') self.echo('Reconnecting...', fg='yellow') try: sqlexecute.connect() logger.debug('Reconnected successfully.') one_iteration(document) return # OK to just return, cuz the recursion call runs to the end. except OperationalError as e: logger.debug('Reconnect failed. e: %r', e) self.echo(str(e), err=True, fg='red') # If reconnection failed, don't proceed further. return else: logger.error("sql: %r, error: %r", document.text, e) logger.error("traceback: %r", traceback.format_exc()) self.echo(str(e), err=True, fg='red') except Exception as e: logger.error("sql: %r, error: %r", document.text, e) logger.error("traceback: %r", traceback.format_exc()) self.echo(str(e), err=True, fg='red') else: if is_dropping_database(document.text, self.sqlexecute.dbname): self.sqlexecute.dbname = None self.sqlexecute.connect() # Refresh the table names and column names if necessary. if need_completion_refresh(document.text): self.refresh_completions( reset=need_completion_reset(document.text)) finally: if self.logfile is False: self.echo("Warning: This query was not logged.", err=True, fg='red') query = Query(document.text, successful, mutating) self.query_history.append(query) get_toolbar_tokens = create_toolbar_tokens_func( self.completion_refresher.is_refreshing, show_suggestion_tip) layout = create_prompt_layout( lexer=MyCliLexer, multiline=True, get_prompt_tokens=prompt_tokens, get_continuation_tokens=get_continuation_tokens, get_bottom_toolbar_tokens=get_toolbar_tokens, display_completions_in_columns=self.wider_completion_menu, extra_input_processors=[ConditionalProcessor( processor=HighlightMatchingBracketProcessor(chars='[](){}'), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() )], reserve_space_for_menu=self.get_reserved_space() ) with self._completer_lock: buf = CLIBuffer(always_multiline=self.multi_line, completer=self.completer, history=FileHistory(os.path.expanduser( os.environ.get('MYCLI_HISTFILE', '~/.mycli-history'))), auto_suggest=AutoSuggestFromHistory(), complete_while_typing=Always(), accept_action=AcceptAction.RETURN_DOCUMENT) if self.key_bindings == 'vi': editing_mode = EditingMode.VI else: editing_mode = EditingMode.EMACS application = Application( style=style_from_pygments(style_cls=self.output_style), layout=layout, buffer=buf, key_bindings_registry=key_binding_manager.registry, on_exit=AbortAction.RAISE_EXCEPTION, on_abort=AbortAction.RETRY, editing_mode=editing_mode, ignore_case=True) self.cli = CommandLineInterface(application=application, eventloop=create_eventloop()) try: while True: one_iteration() iterations += 1 except EOFError: special.close_tee() if not self.less_chatty: self.echo('Goodbye!')
#!/usr/bin/env python """ An empty full screen application without layout. """ from prompt_toolkit import Application Application(full_screen=True).run()
class PlayListEditor: def __init__(self, playlist: LocalFilePlaylist, editable=False) -> None: self.playlist: LocalFilePlaylist = playlist self.editable = False self.text_field = None self.application = None self.key_bindings = None self.layout = None self.play_info_dialog = None self.skip_info_dialog = None self.show_status_bar = True self.focus_index = 0 def run(self): if self.application is not None: self.application.run() def is_show_status_bar(self): return self.show_status_bar def create_key_bindings(self): kb = KeyBindings() @kb.add('c-q') def _(event): self.exit() kb.add("tab")(focus_next) self.key_bindings = kb def create_content(self): # 文本编辑器 text_editor = self.create_text_editor() # 播放列表属性编辑器 property_editor = self.create_property_editor() body = HSplit([ HSplit( [ property_editor, Label(' '), Window(height=1, char="-", style="class:line"), text_editor, ], height=D(), ), ConditionalContainer( content=VSplit( [ Window(FormattedTextControl(self.get_statusbar_text), style="class:status"), Window( FormattedTextControl( self.get_statusbar_right_text), style="class:status.right", width=9, align=WindowAlign.RIGHT, ), ], height=1, ), filter=Condition(lambda: self.is_show_status_bar()), ), ]) self.create_key_bindings() root_container = MenuContainer( body=body, menu_items=[ MenuItem( "File", children=[ MenuItem("Exit", handler=self.exit), ], ), ], floats=[ Float( xcursor=True, ycursor=True, content=CompletionsMenu(max_height=16, scroll_offset=1), ), ], key_bindings=self.key_bindings, ) style = Style.from_dict({ "status": "reverse", "shadow": "bg:#440044", }) self.layout = Layout(root_container, focused_element=self.text_field) self.application = Application( layout=self.layout, enable_page_navigation_bindings=True, style=style, mouse_support=True, full_screen=True, ) def create_property_editor(self): current_file_path = self.playlist.media_list[ self.playlist.current_index] _, current_file_name = os.path.split(current_file_path) self.play_info_dialog = Dialog( modal=False, title="播放记录", body=HSplit([ Label(''), Label(' 播放文件'), Button(f'{current_file_name}', ), Label(' 播放位置'), Button(f'{self.playlist.current_pos}', ), Label(''), ], width=38, padding=1)) self.skip_info_dialog = Dialog( modal=False, title="设置", body=HSplit([ Label(''), Label(' 跳过片头'), Button(f'{self.playlist.skip_head}', ), Label(' 跳过片尾'), Button(f'{self.playlist.skip_tail}', ), Label(''), ], width=38, padding=1)) left_window = VSplit([ self.play_info_dialog, self.skip_info_dialog, ], width=40, padding=2) return left_window def create_text_editor(self): search_toolbar = SearchToolbar() text = '' for file_path in self.playlist.media_list: text += file_path + '\n' self.text_field = TextArea( text=text, read_only=True, #lexer=DynamicLexer( # lambda: PygmentsLexer.from_filename( # ApplicationState.current_path or ".txt", sync_from_start=False # ) #), scrollbar=True, line_numbers=True, search_field=search_toolbar, ) text_editor = HSplit([self.text_field, search_toolbar]) return text_editor def exit(self): if self.application.is_running: self.application.exit() def get_statusbar_text(self): return " Press ctrl-q to exit. " def get_statusbar_right_text(self): return " {}:{} ".format( self.text_field.document.cursor_position_row + 1, self.text_field.document.cursor_position_col + 1, )
show_window = Window(content=BufferControl(buffer=show_buffer, focus_on_click=True), ) control_window = Window(content=BufferControl(buffer=control_buffer, focus_on_click=True), height=5) root_container = HSplit([ # Display the text 'Hello world' on the right. show_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. The window will simply fill its # content by repeating this character. Window(char='─', height=1), # One window that holds the BufferControl with the default buffer on # the left. control_window, ]) t = '' for i in range(99): t += '<style bg="blue" fg="white">' + str(i) + '</style>' + '\n' show_buffer.reset(Document(HTML(t, ))) layout = Layout(root_container) app = Application(layout=layout, full_screen=True, key_bindings=kb) app.run()
class FullNodeUI: """ Full node UI instance. Displays node state, blocks, and connections. Calls parent_close_cb when the full node is closed. Uses the RPC client to fetch data from a full node and to display relevant information. The UI is updated periodically. """ def __init__(self, parent_close_cb: Callable, rpc_client: RpcClient): self.rpc_client = rpc_client self.app: Optional[Application] = None self.data_initialized = False self.block = None self.closed: bool = False self.num_blocks: int = 10 self.num_top_block_pools: int = 10 self.top_winners: List[Tuple[uint64, bytes32]] = [] self.our_winners: List[Tuple[uint64, bytes32]] = [] self.prev_route: str = "home/" self.route: str = "home/" self.focused: bool = False self.parent_close_cb = parent_close_cb self.kb = self.setup_keybindings() self.style = Style([("error", "#ff0044")]) self.pool_pks: List[PublicKey] = [] key_config_filename = os.path.join(ROOT_DIR, "config", "keys.yaml") if os.path.isfile(key_config_filename): config = safe_load(open(key_config_filename, "r")) self.pool_pks = [ PrivateKey.from_bytes(bytes.fromhex(ce)).get_public_key() for ce in config["pool_sks"] ] self.draw_initial() self.app = Application( style=self.style, layout=self.layout, full_screen=True, key_bindings=self.kb, mouse_support=True, ) self.closed = False self.update_ui_task = asyncio.get_running_loop().create_task( self.update_ui()) self.update_data_task = asyncio.get_running_loop().create_task( self.update_data()) def close(self): # Closes this instance of the UI if not self.closed: self.closed = True self.route = "home/" if self.app: self.app.exit(0) def stop(self): # Closes this instance of the UI, and call parent close, which closes # all other instances, and shuts down the full node. self.close() self.parent_close_cb(True) def setup_keybindings(self) -> KeyBindings: kb = KeyBindings() kb.add("tab")(focus_next) kb.add("s-tab")(focus_previous) kb.add("down")(focus_next) kb.add("up")(focus_previous) kb.add("right")(focus_next) kb.add("left")(focus_previous) @kb.add("c-c") def exit_(event): self.close() return kb def draw_initial(self): search_field = SearchToolbar() self.empty_row = TextArea(focusable=False, height=1) # home/ self.loading_msg = Label(text=f"Initializing UI....") self.syncing = TextArea(focusable=False, height=1) self.current_heads_label = TextArea(focusable=False, height=1) self.lca_label = TextArea(focusable=False, height=1) self.difficulty_label = TextArea(focusable=False, height=1) self.ips_label = TextArea(focusable=False, height=1) self.total_iters_label = TextArea(focusable=False, height=2) self.con_rows = [] self.displayed_cons = set() self.latest_blocks: List[HeaderBlock] = [] self.connections_msg = Label(text=f"Connections") self.connection_rows_vsplit = Window() self.add_connection_msg = Label(text=f"Add a connection ip:port") self.add_connection_field = TextArea( height=1, prompt=">>> ", style="class:input-field", multiline=False, wrap_lines=False, search_field=search_field, ) self.add_connection_field.accept_handler = self.async_to_sync( self.add_connection) self.latest_blocks_msg = Label(text=f"Latest blocks") self.latest_blocks_labels = [ Button(text="block") for _ in range(self.num_blocks) ] self.search_block_msg = Label(text=f"Search block by hash") self.search_block_field = TextArea( height=1, prompt=">>> ", style="class:input-field", multiline=False, wrap_lines=False, search_field=search_field, ) self.search_block_field.accept_handler = self.async_to_sync( self.search_block) self.top_block_pools_msg = Label(text=f"Top block pools") self.top_block_pools_labels = [ Label(text="Top block pool") for _ in range(self.num_top_block_pools) ] self.our_pools_msg = Label(text=f"Our pool winnings") self.our_pools_labels = [ Label(text="Our winnings") for _ in range(len(self.pool_pks)) ] self.close_ui_button = Button("Close UI", handler=self.close) self.quit_button = Button("Stop node and close UI", handler=self.stop) self.error_msg = Label(style="class:error", text=f"") # block/ self.block_msg = Label(text=f"Block") self.block_label = TextArea(focusable=True, scrollbar=True, focus_on_click=True) self.back_button = Button(text="Back", handler=self.change_route_handler("home/")) self.challenge_msg = Label(text=f"Block Header") self.challenge = TextArea(focusable=False) body = HSplit([self.loading_msg], height=D(), width=D()) self.content = Frame(title="Chia Full Node", body=body) self.layout = Layout(VSplit([self.content], height=D(), width=D())) def change_route_handler(self, route): def change_route(): self.prev_route = self.route self.route = route self.focused = False self.error_msg.text = "" return change_route def async_to_sync(self, coroutine): def inner(buff=None): if buff is None: asyncio.get_running_loop().create_task(coroutine()) else: asyncio.get_running_loop().create_task(coroutine(buff.text)) return inner async def search_block(self, text: str): try: block = await self.rpc_client.get_block(bytes.fromhex(text)) except ValueError: self.error_msg.text = "Enter a valid hex block hash" return if block is not None: self.change_route_handler(f"block/{text}")() else: self.error_msg.text = "Block not found" async def add_connection(self, text: str): if ":" not in text: self.error_msg.text = ( "Enter a valid IP and port in the following format: 10.5.4.3:8000" ) return else: ip, port = ":".join(text.split(":")[:-1]), text.split(":")[-1] log.info(f"Want to connect to {ip}, {port}") try: await self.rpc_client.open_connection(ip, int(port)) except BaseException: # TODO: catch right exception self.error_msg.text = f"Failed to connect to {ip}:{port}" async def get_latest_blocks( self, heads: List[SmallHeaderBlock]) -> List[SmallHeaderBlock]: added_blocks: List[SmallHeaderBlock] = [] while len(added_blocks) < self.num_blocks and len(heads) > 0: heads = sorted(heads, key=lambda b: b.height, reverse=True) max_block = heads[0] if max_block not in added_blocks: added_blocks.append(max_block) heads.remove(max_block) prev: Optional[ SmallHeaderBlock] = await self.rpc_client.get_header( max_block.prev_header_hash) if prev is not None: heads.append(prev) return added_blocks async def draw_home(self): connections: List[Dict] = [c for c in self.connections] if set([con["node_id"] for con in connections]) != self.displayed_cons: new_con_rows = [] for con in connections: con_str = ( f"{NodeType(con['type']).name} {con['peer_host']} {con['peer_port']}/{con['peer_server_port']}" f" {con['node_id'].hex()[:10]}...") con_label = Label(text=con_str) def disconnect(c): async def inner(): await self.rpc_client.close_connection(c["node_id"]) self.layout.focus(self.quit_button) return inner disconnect_button = Button("Disconnect", handler=self.async_to_sync( disconnect(con))) row = VSplit([con_label, disconnect_button]) new_con_rows.append(row) self.displayed_cons = set([con["node_id"] for con in connections]) self.con_rows = new_con_rows if len(self.con_rows) > 0: self.layout.focus(self.con_rows[0]) else: self.layout.focus(self.quit_button) if len(self.con_rows): new_con_rows = HSplit(self.con_rows) else: new_con_rows = Window(width=D(), height=0) if self.sync_mode: if self.max_height >= 0: self.syncing.text = f"Syncing up to {self.max_height}" else: self.syncing.text = f"Syncing" else: self.syncing.text = "Not syncing" total_iters = self.lca_block.challenge.total_iters new_block_labels = [] for i, b in enumerate(self.latest_blocks): self.latest_blocks_labels[i].text = ( f"{b.height}:{b.header_hash}" f" {'LCA' if b.header_hash == self.lca_block.header_hash else ''}" f" {'TIP' if b.header_hash in [h.header_hash for h in self.tips] else ''}" ) self.latest_blocks_labels[i].handler = self.change_route_handler( f"block/{b.header_hash}") new_block_labels.append(self.latest_blocks_labels[i]) top_block_pools_labels = self.top_block_pools_labels if len(self.top_winners) > 0: new_top_block_pools_labels = [] for i, (winnings, pk) in enumerate(self.top_winners): self.top_block_pools_labels[ i].text = f"Public key {pk.hex()}: {winnings/1000000000000} chias." new_top_block_pools_labels.append( self.top_block_pools_labels[i]) top_block_pools_labels = new_top_block_pools_labels our_pools_labels = self.our_pools_labels if len(self.our_winners) > 0: new_our_pools_labels = [] for i, (winnings, pk) in enumerate(self.our_winners): self.our_pools_labels[ i].text = f"Public key {pk.hex()}: {winnings/(1000000000000)} chias." new_our_pools_labels.append(self.our_pools_labels[i]) our_pools_labels = new_our_pools_labels self.lca_label.text = ( f"Current least common ancestor {self.lca_block.header_hash}" f" height {self.lca_block.height}") self.current_heads_label.text = "Heights of tips: " + str( [h.height for h in self.tips]) self.difficulty_label.text = f"Current difficulty: {self.difficulty}" self.ips_label.text = f"Current VDF iterations per second: {self.ips}" self.total_iters_label.text = f"Total iterations since genesis: {total_iters}" try: if not self.focused: self.layout.focus(self.close_ui_button) self.focused = True except ValueError: # Not yet in layout pass return HSplit( [ self.syncing, self.lca_label, self.current_heads_label, self.difficulty_label, self.ips_label, self.total_iters_label, Window(height=1, char="-", style="class:line"), self.connections_msg, new_con_rows, Window(height=1, char="-", style="class:line"), self.add_connection_msg, self.add_connection_field, Window(height=1, char="-", style="class:line"), self.latest_blocks_msg, *new_block_labels, Window(height=1, char="-", style="class:line"), self.search_block_msg, self.search_block_field, Window(height=1, char="-", style="class:line"), self.top_block_pools_msg, *top_block_pools_labels, Window(height=1, char="-", style="class:line"), self.our_pools_msg, *our_pools_labels, Window(height=1, char="-", style="class:line"), self.close_ui_button, self.quit_button, self.error_msg, ], width=D(), height=D(), ) async def draw_block(self): block_hash: str = self.route.split("block/")[1] if self.block is None or self.block.header_hash != bytes32( bytes.fromhex(block_hash)): self.block: Optional[FullBlock] = await self.rpc_client.get_block( bytes32(bytes.fromhex(block_hash))) if self.block is not None: self.block_msg.text = f"Block {str(self.block.header_hash)}" if self.block_label.text != str(self.block): self.block_label.text = str(self.block) else: self.block_label.text = f"Block hash {block_hash} not found" try: if not self.focused: self.layout.focus(self.back_button) self.focused = True except ValueError: # Not yet in layout pass return HSplit([self.block_msg, self.block_label, self.back_button], width=D(), height=D()) async def update_ui(self): try: while not self.closed: if self.data_initialized: if self.route.startswith("home/"): self.content.body = await self.draw_home() elif self.route.startswith("block/"): self.content.body = await self.draw_block() if self.app and not self.app.invalidated: self.app.invalidate() await asyncio.sleep(0.5) except Exception as e: log.error(f"Exception in UI update_ui {type(e)}: {e}") raise e async def update_data(self): self.data_initialized = False counter = 0 try: while not self.closed: try: blockchain_state = await self.rpc_client.get_blockchain_state( ) self.lca_block = blockchain_state["lca"] self.tips = blockchain_state["tips"] self.difficulty = blockchain_state["difficulty"] self.ips = blockchain_state["ips"] self.sync_mode = blockchain_state["sync_mode"] self.connections = await self.rpc_client.get_connections() if self.sync_mode: max_block = await self.rpc_client.get_heaviest_block_seen( ) self.max_height = max_block.height self.latest_blocks = await self.get_latest_blocks(self.tips ) self.data_initialized = True if counter % 20 == 0: # Only request balances periodically, since it's an expensive operation coin_balances: Dict[ bytes, uint64] = await self.rpc_client.get_pool_balances( ) self.top_winners = sorted( [(rewards, key) for key, rewards in coin_balances.items()], reverse=True, )[:self.num_top_block_pools] self.our_winners = [ (coin_balances[bytes(pk)], bytes(pk)) if bytes(pk) in coin_balances else (0, bytes(pk)) for pk in self.pool_pks ] counter += 1 await asyncio.sleep(5) except ( aiohttp.client_exceptions.ClientConnectorError, aiohttp.client_exceptions.ServerConnectionError, ) as e: log.warning( f"Could not connect to full node. Is it running? {e}") await asyncio.sleep(5) except Exception as e: log.error(f"Exception in UI update_data {type(e)}: {e}") raise e async def await_closed(self): await self.update_ui_task await self.update_data_task
def __init__( self, entries, preview_callback=None, input_callback=None, input_completions=None, ): if not entries or len(entries) == 0: raise RuntimeError("Entries cannot be empty.") self.entries = entries self.input_callback = input_callback self.preview_callback = preview_callback self.ansi_escape_8bit = re.compile( r"(?:\x1B[@-Z\\-_]|[\x80-\x9A\x9C-\x9F]|(?:\x1B\[|\x9B)[0-?]*[ -/]*[@-~])" ) self.current_lineno = 1 self.max_entry_width = min( max( map( lambda x: len(x) + 1, self.ansi_escape_8bit.sub("", entries).split("\n") ) ), 48, ) entries_text = ANSI(self.entries) entries_formatted_text = to_formatted_text(entries_text) entries_plain_text = fragment_list_to_text(entries_formatted_text) self.entries_control = FormattedBufferControl( buffer=Buffer( document=Document(entries_plain_text, 0), name="entries", on_cursor_position_changed=self.update_entries, read_only=True, ), focusable=True, formatted_text=entries_formatted_text, include_default_input_processors=False, input_processors=[FormatTextProcessor(), HighlightSelectionProcessor()], ) if self.preview_callback: self.preview_text = ANSI(self.preview_callback(self.current_lineno)) formatted_text = to_formatted_text(self.preview_text) plain_text = fragment_list_to_text(formatted_text) self.preview_control = FormattedBufferControl( buffer=Buffer( document=Document(plain_text, 0), name="preview", on_cursor_position_changed=self.update_preview, read_only=True, ), focusable=True, formatted_text=formatted_text, include_default_input_processors=False, input_processors=[FormatTextProcessor(), HighlightSelectionProcessor()], ) # Alternative (not scrollable): # self.preview_control = FormattedTextControl( # focusable=True, # show_cursor=True, # text=ANSI(self.preview_callback(self.current_lineno)), # ) entries_container = VSplit( [ Window( content=self.entries_control, width=self.max_entry_width, wrap_lines=True, ), Window(width=3, char=" | "), Window(content=self.preview_control, wrap_lines=True), ] ) else: entries_container = Window( content=self.entries_control, width=self.max_entry_width, wrap_lines=True, ) if self.input_callback: self.search_field = SearchToolbar() self.input_field = TextArea( accept_handler=self.input_accept, completer=FuzzyWordCompleter(list(input_completions)), complete_while_typing=True, height=1, multiline=False, prompt="> ", search_field=self.search_field, wrap_lines=False, ) self.root_container = FloatContainer( content=HSplit( [entries_container, Window(height=1, char="-"), self.input_field,] ), floats=[ Float( content=CompletionsMenu(max_height=16, scroll_offset=1), xcursor=True, ycursor=True, ) ], ) else: self.root_container = entries_container self.layout = Layout(self.root_container) self.app = Application(full_screen=True, key_bindings=kb, layout=self.layout)
content=controls.BufferControl(buffer=buffer), height=1 ), containers.Window(height=1, char="-", style="class:line"), containers.Window(content=display), ] ), floats=[ containers.Float( xcursor=True, ycursor=True, content=menus.CompletionsMenu(max_height=12, scroll_offset=1), ) ], ), ] ) ) kb = KeyBindings() @kb.add("c-g") @kb.add("c-c") def exit_(event): event.app.exit() app = Application(layout=layout, full_screen=True, key_bindings=kb) app.run()
def cli(ctx, email, password, token, graphql, **kwargs): '''Music player''' ctx.obj.u = lambda: user.User.new(email=email, password=password, token=token, graphql=graphql) mf = mfilter.Filter(**kwargs) p = ctx.obj.u().do_filter(mf) if not p: logger.warning('Empty playlist') return instance = vlc.Instance() songs = [song['path'] for song in p] player = instance.media_list_player_new() media_list = instance.media_list_new(songs) player.set_media_list(media_list) bindings = KeyBindings() @bindings.add('p') def _play_binding(event): def play(): """Play song""" player.play() run_in_terminal(play) @bindings.add('q') def _quit_binding(event): player.pause() event.app.exit() @bindings.add('s') def _pause_binding(event): player.pause() @bindings.add('l') def _playlist_binding(event): def playlist(): """List songs""" for s in songs: print(s) run_in_terminal(playlist) @bindings.add('right') def _next_binding(event): player.next() @bindings.add('left') def _previous_binding(event): player.previous() def bottom_toolbar(): media_player = player.get_media_player() media = media_player.get_media() media.parse() media_time = seconds_to_human(round(media_player.get_time() / 1000)) media_length = seconds_to_human(round(media_player.get_length() / 1000)) artist = media.get_meta(vlc.Meta.Artist) album = media.get_meta(vlc.Meta.Album) title = media.get_meta(vlc.Meta.Title) current = '({} / {}) {} - {} - {}'.format(media_time, media_length, artist, album, title) get_app().invalidate() return HTML('Current song: {}'.format(current)) player.play() print(HTML('Bindings: q = quit | p = play | s = pause/continue | right = next song | left = previous song | l = playlist')) root_container = HSplit( [Window(FormattedTextControl(lambda: bottom_toolbar, style='class:bottom-toolbar.text'), style='class:bottom-toolbar')] ) layout = Layout(root_container) app = Application(layout=layout, key_bindings=bindings) app.run()