def get_prompt() -> HTML: """ Build the prompt dynamically every time its rendered. """ left_part = HTML("<left-part>" " <username>root</username> " " abc " "<path>~/.oh-my-zsh/themes</path>" "</left-part>") right_part = HTML( "<right-part> " "<branch> master<exclamation-mark>!</exclamation-mark> </branch> " " <env> py36 </env> " " <time>%s</time> " "</right-part>") % (datetime.datetime.now().isoformat(), ) used_width = sum([ fragment_list_width(to_formatted_text(left_part)), fragment_list_width(to_formatted_text(right_part)), ]) total_width = get_app().output.get_size().columns padding_size = total_width - used_width padding = HTML("<padding>%s</padding>") % (" " * padding_size, ) return merge_formatted_text([left_part, padding, right_part, "\n", "# "])
def get_prompt(app: Flask) -> HTML: """ Build the prompt dynamically every time its rendered. """ left_part = HTML("<left-part>" " <import_name>%s</import_name> " "<path>%s</path>" "</left-part>") % (app.import_name, app.root_path) right_part = HTML("<right-part> " " <env>%s</env> " " <time>%s</time> " "</right-part>") % ( os.environ["ZEMFROG_ENV"], datetime.datetime.now().isoformat(), ) used_width = sum([ fragment_list_width(to_formatted_text(left_part)), fragment_list_width(to_formatted_text(right_part)), ]) total_width = get_app().output.get_size().columns padding_size = total_width - used_width padding = HTML("<padding>%s</padding>") % (" " * padding_size, ) return merge_formatted_text([left_part, padding, right_part, "\n", "$ "])
def _trim_formatted_text(formatted_text: StyleAndTextTuples, max_width: int) -> Tuple[StyleAndTextTuples, int]: """ Trim the text to `max_width`, append dots when the text is too long. Returns (text, width) tuple. """ width = fragment_list_width(formatted_text) # When the text is too wide, trim it. if width > max_width: result = [] # Text fragments. remaining_width = max_width - 3 for style_and_ch in explode_text_fragments(formatted_text): ch_width = get_cwidth(style_and_ch[1]) if ch_width <= remaining_width: result.append(style_and_ch) remaining_width -= ch_width else: break result.append(("", "...")) return result, max_width - remaining_width else: return formatted_text, width
def _trim_formatted_text(formatted_text, max_width): """ Trim the text to `max_width`, append dots when the text is too long. Returns (text, width) tuple. """ width = fragment_list_width(formatted_text) # When the text is too wide, trim it. if width > max_width: result = [] # Text fragments. remaining_width = max_width - 3 for style_and_ch in explode_text_fragments(formatted_text): ch_width = get_cwidth(style_and_ch[1]) if ch_width <= remaining_width: result.append(style_and_ch) remaining_width -= ch_width else: break result.append(('', '...')) return result, max_width - remaining_width else: return formatted_text, width
def show_sidebar_button_info(my_app: "sqlApp") -> Container: """ Create `Layout` for the information in the right-bottom corner. (The right part of the status bar.) """ @if_mousedown def toggle_sidebar(mouse_event: MouseEvent) -> None: " Click handler for the menu. " my_app.show_sidebar = not my_app.show_sidebar # TO DO: app version rather than python version = sys.version_info tokens: StyleAndTextTuples = [ ("class:status-toolbar.key", "[C-t]", toggle_sidebar), ("class:status-toolbar", " Object Browser", toggle_sidebar), ("class:status-toolbar", " - "), ("class:status-toolbar.cli-version", "odbcli %s" % __version__), ("class:status-toolbar", " "), ] width = fragment_list_width(tokens) def get_text_fragments() -> StyleAndTextTuples: # Python version return tokens return ConditionalContainer( content=Window( FormattedTextControl(get_text_fragments), style="class:status-toolbar", height=Dimension.exact(1), width=Dimension.exact(width), ), filter=~is_done & Condition(lambda: not my_app.show_exit_confirmation) & renderer_height_is_known)
def show_sidebar_button_info(python_input): """ Create `Layout` for the information in the right-bottom corner. (The right part of the status bar.) """ @if_mousedown def toggle_sidebar(mouse_event): " Click handler for the menu. " python_input.show_sidebar = not python_input.show_sidebar version = sys.version_info tokens = [ ('class:status-toolbar.key', '[F2]', toggle_sidebar), ('class:status-toolbar', ' Menu', toggle_sidebar), ('class:status-toolbar', ' - '), ('class:status-toolbar.python-version', '%s %i.%i.%i' % (platform.python_implementation(), version[0], version[1], version[2])), ('class:status-toolbar', ' '), ] width = fragment_list_width(tokens) def get_text_fragments(): # Python version return tokens return ConditionalContainer( content=Window(FormattedTextControl(get_text_fragments), style='class:status-toolbar', height=Dimension.exact(1), width=Dimension.exact(width)), filter=~is_done & renderer_height_is_known & Condition(lambda: python_input.show_status_bar and not python_input. show_exit_confirmation))
def show_sidebar_button_info(python_input): """ Create `Layout` for the information in the right-bottom corner. (The right part of the status bar.) """ @if_mousedown def toggle_sidebar(mouse_event): " Click handler for the menu. " python_input.show_sidebar = not python_input.show_sidebar version = sys.version_info tokens = [ ('class:status-toolbar.key', '[F2]', toggle_sidebar), ('class:status-toolbar', ' Menu', toggle_sidebar), ('class:status-toolbar', ' - '), ('class:status-toolbar.python-version', '%s %i.%i.%i' % (platform.python_implementation(), version[0], version[1], version[2])), ('class:status-toolbar', ' '), ] width = fragment_list_width(tokens) def get_text_fragments(): # Python version return tokens return ConditionalContainer( content=Window( FormattedTextControl(get_text_fragments), style='class:status-toolbar', height=Dimension.exact(1), width=Dimension.exact(width)), filter=~is_done & renderer_height_is_known & Condition(lambda: python_input.show_status_bar and not python_input.show_exit_confirmation))
def trim_pad(formatted_text, width, align): text_width = fragment_list_width(formatted_text) if text_width == width: return formatted_text if text_width < width: left_pad = width - text_width if align == 'r' else 0 right_pad = width - text_width if align == 'l' else 0 return [('', ' ' * left_pad)] + formatted_text + [('', ' ' * right_pad) ] trimmed = [] width -= 3 while fragment_list_width(trimmed) < width: trimmed.append(formatted_text.pop(0)) if fragment_list_width(trimmed) > width: trimmed[-1] = ( trimmed[-1][0], trimmed[-1][1][:-(fragment_list_width(trimmed) - width)]) return trimmed + [('', '...')]
def show_result(self, result: object) -> None: """ Show __repr__ for an `eval` result. """ out_prompt = to_formatted_text(self.get_output_prompt()) # If the repr is valid Python code, use the Pygments lexer. result_repr = repr(result) try: compile(result_repr, "", "eval") except SyntaxError: formatted_result_repr = to_formatted_text(result_repr) else: formatted_result_repr = to_formatted_text( PygmentsTokens(list(_lex_python_result(result_repr)))) # If __pt_repr__ is present, take this. This can return # prompt_toolkit formatted text. if hasattr(result, "__pt_repr__"): try: formatted_result_repr = to_formatted_text( getattr(result, "__pt_repr__")()) if isinstance(formatted_result_repr, list): formatted_result_repr = FormattedText( formatted_result_repr) except: pass # Align every line to the prompt. line_sep = "\n" + " " * fragment_list_width(out_prompt) indented_repr: StyleAndTextTuples = [] lines = list(split_lines(formatted_result_repr)) for i, fragment in enumerate(lines): indented_repr.extend(fragment) # Add indentation separator between lines, not after the last line. if i != len(lines) - 1: indented_repr.append(("", line_sep)) # Write output tokens. if self.enable_syntax_highlighting: formatted_output = merge_formatted_text( [out_prompt, indented_repr]) else: formatted_output = FormattedText(out_prompt + [( "", fragment_list_to_text(formatted_result_repr))]) print_formatted_text( formatted_output, style=self._current_style, style_transformation=self.style_transformation, include_default_pygments_style=False, output=self.app.output, ) self.app.output.flush()
def get_info_app(app: Flask): left_part = HTML("<left-part>" " <import_name>%s</import_name> " "<path>%s</path>" "</left-part>") % (app.import_name, app.root_path) right_part = HTML("<right-part> " " <env>%s</env> " " <time>%s</time> " "</right-part>") % (os.environ["ZEMFROG_ENV"], datetime.datetime.now().isoformat()) used_width = sum([ fragment_list_width(to_formatted_text(left_part)), fragment_list_width(to_formatted_text(right_part)), ]) total_width = get_app().output.get_size().columns padding_size = total_width - used_width padding = HTML("<padding>%s</padding>") % (" " * padding_size, ) return left_part, padding, right_part, "\n"
def show_result(self, result: object) -> None: if hasattr(result, "__pt_repr__"): out_prompt = to_formatted_text(self.get_output_prompt()) try: formatted_result_repr = to_formatted_text( getattr(result, "__pt_repr__")()) if isinstance(formatted_result_repr, list): formatted_result_repr = FormattedText( formatted_result_repr) except: pass line_sep = "\n" + " " * fragment_list_width(out_prompt) indented_repr: StyleAndTextTuples = [] lines = list(split_lines(formatted_result_repr)) for i, fragment in enumerate(lines): indented_repr.extend(fragment) # Add indentation separator between lines, not after the last line. if i != len(lines) - 1: indented_repr.append(("", line_sep)) # Write output tokens. if self.enable_syntax_highlighting: formatted_output = merge_formatted_text( [out_prompt, indented_repr]) else: formatted_output = FormattedText(out_prompt + [( "", fragment_list_to_text(formatted_result_repr))]) if self.enable_pager: self.print_paginated_formatted_text( to_formatted_text(formatted_output)) else: self.print_formatted_text(to_formatted_text(formatted_output)) self.app.output.flush() if self.insert_blank_line_after_output: self.app.output.write("\n") else: if self._formatter: result = self._formatter(result) self.console.print(result)
def show_sidebar_button_info(python_input: "PythonInput") -> Container: """ Create `Layout` for the information in the right-bottom corner. (The right part of the status bar.) """ @if_mousedown def toggle_sidebar(mouse_event: MouseEvent) -> None: " Click handler for the menu. " python_input.show_sidebar = not python_input.show_sidebar version = sys.version_info tokens: StyleAndTextTuples = [ ("class:status-toolbar.key", "[F2]", toggle_sidebar), ("class:status-toolbar", " Menu", toggle_sidebar), ("class:status-toolbar", " - "), ( "class:status-toolbar.python-version", "%s %i.%i.%i" % (platform.python_implementation(), version[0], version[1], version[2]), ), ("class:status-toolbar", " "), ] width = fragment_list_width(tokens) def get_text_fragments() -> StyleAndTextTuples: # Python version return tokens return ConditionalContainer( content=Window( FormattedTextControl(get_text_fragments), style="class:status-toolbar", height=Dimension.exact(1), width=Dimension.exact(width), ), filter=~is_done & renderer_height_is_known & Condition( lambda: python_input.show_status_bar and not python_input.show_exit_confirmation ), )
def draw_table(columns, data): column_widths = [0 for _ in columns] data = [[to_formatted_text(cell) for cell in row] for row in data] for row in data: for i, cell in enumerate(row): column_widths[i] = max(column_widths[i], fragment_list_width(cell)) row_output = [] for i, column in enumerate(columns): column_widths[i] = max(column_widths[i], len(column.header)) column_widths[i] = min(column_widths[i], column.max_width) row_output += trim_pad( to_formatted_text(HTML(f'<b>{column.header}</b>')), column_widths[i], 'l') + [('', ' ')] print(FormattedText(row_output)) for row in data: row_output = [] for i, cell in enumerate(row): row_output += trim_pad(cell, column_widths[i], columns[i].align) + \ [('', ' ')] print(FormattedText(row_output))
def _execute(self, line: str) -> None: """ Evaluate the line and print the result. """ output = self.app.output # WORKAROUND: Due to a bug in Jedi, the current directory is removed # from sys.path. See: https://github.com/davidhalter/jedi/issues/1148 if "" not in sys.path: sys.path.insert(0, "") def compile_with_flags(code: str, mode: str): " Compile code with the right compiler flags. " return compile( code, "<stdin>", mode, flags=self.get_compiler_flags(), dont_inherit=True, ) if line.lstrip().startswith("\x1a"): # When the input starts with Ctrl-Z, quit the REPL. self.app.exit() elif line.lstrip().startswith("!"): # Run as shell command os.system(line[1:]) else: # Try eval first try: code = compile_with_flags(line, "eval") result = eval(code, self.get_globals(), self.get_locals()) locals: Dict[str, Any] = self.get_locals() locals["_"] = locals["_%i" % self.current_statement_index] = result if result is not None: out_prompt = to_formatted_text(self.get_output_prompt()) try: result_str = "%r\n" % (result,) except UnicodeDecodeError: # In Python 2: `__repr__` should return a bytestring, # so to put it in a unicode context could raise an # exception that the 'ascii' codec can't decode certain # characters. Decode as utf-8 in that case. result_str = "%s\n" % repr(result).decode( # type: ignore "utf-8" ) # Align every line to the first one. line_sep = "\n" + " " * fragment_list_width(out_prompt) result_str = line_sep.join(result_str.splitlines()) + "\n" # Write output tokens. if self.enable_syntax_highlighting: formatted_output = merge_formatted_text( [ out_prompt, PygmentsTokens(list(_lex_python_result(result_str))), ] ) else: formatted_output = FormattedText( out_prompt + [("", result_str)] ) print_formatted_text( formatted_output, style=self._current_style, style_transformation=self.style_transformation, include_default_pygments_style=False, output=output, ) # If not a valid `eval` expression, run using `exec` instead. except SyntaxError: code = compile_with_flags(line, "exec") exec(code, self.get_globals(), self.get_locals()) output.flush()
def _width(self): return fragment_list_width(self.in_prompt_tokens())
def show_result(self, result: object) -> None: """ Show __repr__ for an `eval` result. Note: this can raise `KeyboardInterrupt` if either calling `__repr__`, `__pt_repr__` or formatting the output with "Black" takes to long and the user presses Control-C. """ out_prompt = to_formatted_text(self.get_output_prompt()) # If the repr is valid Python code, use the Pygments lexer. try: result_repr = repr(result) except KeyboardInterrupt: raise # Don't catch here. except BaseException as e: # Calling repr failed. self._handle_exception(e) return try: compile(result_repr, "", "eval") except SyntaxError: formatted_result_repr = to_formatted_text(result_repr) else: # Syntactically correct. Format with black and syntax highlight. if self.enable_output_formatting: # Inline import. Slightly speed up start-up time if black is # not used. import black result_repr = black.format_str( result_repr, mode=black.FileMode( line_length=self.app.output.get_size().columns), ) formatted_result_repr = to_formatted_text( PygmentsTokens(list(_lex_python_result(result_repr)))) # If __pt_repr__ is present, take this. This can return prompt_toolkit # formatted text. try: if hasattr(result, "__pt_repr__"): formatted_result_repr = to_formatted_text( getattr(result, "__pt_repr__")()) if isinstance(formatted_result_repr, list): formatted_result_repr = FormattedText( formatted_result_repr) except KeyboardInterrupt: raise # Don't catch here. except: # For bad code, `__getattr__` can raise something that's not an # `AttributeError`. This happens already when calling `hasattr()`. pass # Align every line to the prompt. line_sep = "\n" + " " * fragment_list_width(out_prompt) indented_repr: StyleAndTextTuples = [] lines = list(split_lines(formatted_result_repr)) for i, fragment in enumerate(lines): indented_repr.extend(fragment) # Add indentation separator between lines, not after the last line. if i != len(lines) - 1: indented_repr.append(("", line_sep)) # Write output tokens. if self.enable_syntax_highlighting: formatted_output = merge_formatted_text( [out_prompt, indented_repr]) else: formatted_output = FormattedText(out_prompt + [( "", fragment_list_to_text(formatted_result_repr))]) if self.enable_pager: self.print_paginated_formatted_text( to_formatted_text(formatted_output)) else: self.print_formatted_text(to_formatted_text(formatted_output)) self.app.output.flush() if self.insert_blank_line_after_output: self.app.output.write("\n")
def _width(self): return fragment_list_width(self.in_prompt_tokens())