def create_radian_prompt_session(options): history_file = ".radian_history" if options.no_history: history = ModalInMemoryHistory() elif not options.global_history and os.path.exists(history_file): history = ModalFileHistory(os.path.abspath(history_file)) else: history = ModalFileHistory( os.path.join(os.path.expanduser("~"), history_file)) if is_windows(): output = None else: output = CustomVt100Output.from_pty( sys.stdout, term=get_term_environment_variable()) def get_inputhook(): terminal_width = [None] def _(context): while True: if context.input_is_ready(): break try: process_events() except Exception: pass output_width = session.app.output.get_size().columns if output_width and terminal_width[0] != output_width: terminal_width[0] = output_width setoption("width", max(terminal_width[0], 20)) time.sleep(1.0 / 30) return _ session = ModalPromptSession( color_depth=ColorDepth.default(term=os.environ.get("TERM")), history=history, enable_history_search=True, enable_suspend=True, tempfile_suffix=".R", input=CustomVt100Input(sys.stdin) if not is_windows() else None, output=output, inputhook=get_inputhook(), mode_class=RadianMode) load_settings(session) register_modes(session) return session
def reset(self): # Reset position self._cursor_pos = Point(x=0, y=0) # Remember the last screen instance between renderers. This way, # we can create a `diff` between two screens and only output the # difference. It's also to remember the last height. (To show for # instance a toolbar at the bottom position.) self._last_screen = None self._last_size = None self._last_char = None self._last_style = None # When the style changes, we have to do a full # redraw as well. # Remember the last title. Only set the title when it changes. self._last_title = None #: Space from the top of the layout, until the bottom of the terminal. #: We don't know this until a `report_absolute_cursor_row` call. self._min_available_height = 0 # In case of Windown, also make sure to scroll to the current cursor # position. if is_windows(): self.output.scroll_buffer_to_prompt() # Quit alternate screen. if self._in_alternate_screen: self.output.quit_alternate_screen() self.output.flush() self._in_alternate_screen = False
def create_client(socket_name): if is_windows(): from .windows import WindowsClient return WindowsClient(socket_name) else: from .posix import PosixClient return PosixClient(socket_name)
def __init__(self, editing_mode=EditingMode.EMACS, history=None, lexer=None, style=None, completer=None, extra_key_bindings=None, tempfile_suffix=None, input=None, output=None, on_render=None): self.editing_mode = editing_mode self.history = history self.lexer = lexer self.style = None self.completer = completer self.extra_key_bindings = extra_key_bindings self.tempfile_suffix = tempfile_suffix if not is_windows(): self.input = input or CustomVt100Input(sys.stdin) else: self.input = input or get_default_input() self.output = output or get_default_output() self.on_render = on_render self.create_layout() self.create_application()
def create_output(stdout=None, true_color=False, ansi_colors_only=None): """ Return an :class:`~prompt_toolkit.output.Output` instance for the command line. :param true_color: When True, use 24bit colors instead of 256 colors. (`bool` or :class:`~prompt_toolkit.filters.Filter`.) :param ansi_colors_only: When True, restrict to 16 ANSI colors only. (`bool` or :class:`~prompt_toolkit.filters.Filter`.) """ stdout = stdout or sys.__stdout__ true_color = to_filter(true_color) if is_windows(): from .conemu import ConEmuOutput from .win32 import Win32Output from .windows10 import is_win_vt100_enabled, Windows10_Output if is_win_vt100_enabled(): return Windows10_Output(stdout) if is_conemu_ansi(): return ConEmuOutput(stdout) else: return Win32Output(stdout) else: from .vt100 import Vt100_Output term = os.environ.get('TERM', '') if PY2: term = term.decode('utf-8') return Vt100_Output.from_pty(stdout, true_color=true_color, ansi_colors_only=ansi_colors_only, term=term)
def get_title_bar_right_text(): copy_key = "CTRL + SHIFT" if is_windows() else "fn" return [ ("class:title", f"[Double Ctrl + C] QUIT "), ("class:title", f"[Ctrl + S] STATUS "), ("class:title", f"Hold down \"{copy_key}\" for selecting and copying text"), ]
def create_output(stdout=None, true_color=False): """ Return an :class:`~prompt_toolkit.output.Output` instance for the command line. :param true_color: When True, use 24bit colors instead of 256 colors. (`bool` or :class:`~prompt_toolkit.filters.SimpleFilter`.) Notes ----- This method was forked from the mainline prompt-toolkit repo. Copyright (c) 2014, Jonathan Slenders, All rights reserved. This is deprecated and slated for removal after a prompt-toolkit v0.57+ release. """ stdout = stdout or sys.__stdout__ true_color = to_simple_filter(true_color) if is_windows(): if is_conemu_ansi(): return ConEmuOutput(stdout) else: return Win32Output(stdout) else: term = os.environ.get('TERM', '') if PY2: term = term.decode('utf-8') return Vt100_Output.from_pty(stdout, true_color=true_color) #, term=term)
def create_input(stdin: Optional[TextIO] = None, always_prefer_tty: bool = False) -> Input: """ Create the appropriate `Input` object for the current os/environment. :param always_prefer_tty: When set, if `sys.stdin` is connected to a Unix `pipe`, check whether `sys.stdout` or `sys.stderr` are connected to a pseudo terminal. If so, open the tty for reading instead of reading for `sys.stdin`. (We can open `stdout` or `stderr` for reading, this is how a `$PAGER` works.) """ if is_windows(): from .win32 import Win32Input return Win32Input(stdin or sys.stdin) else: from .vt100 import Vt100Input # If no input TextIO is given, use stdin/stdout. if stdin is None: stdin = sys.stdin if always_prefer_tty: for io in [sys.stdin, sys.stdout, sys.stderr]: if io.isatty(): stdin = io break return Vt100Input(stdin)
def _mouse(event: E) -> None: """ Handling of mouse events for Windows. """ assert is_windows() # This key binding should only exist for Windows. # Parse data. pieces = event.data.split(";") event_type = MouseEventType(pieces[0]) x = int(pieces[1]) y = int(pieces[2]) # Make coordinates absolute to the visible part of the terminal. output = event.app.renderer.output from prompt_toolkit.output.win32 import Win32Output if isinstance(output, Win32Output): screen_buffer_info = output.get_win32_screen_buffer_info() rows_above_cursor = ( screen_buffer_info.dwCursorPosition.Y - event.app.renderer._cursor_pos.y ) y -= rows_above_cursor # Call the mouse event handler. handler = event.app.renderer.mouse_handlers.mouse_handlers[x, y] handler(MouseEvent(position=Point(x=x, y=y), event_type=event_type))
def create_output(stdout: Optional[TextIO] = None) -> Output: """ Return an :class:`~prompt_toolkit.output.Output` instance for the command line. :param stdout: The stdout object """ if stdout is None: # By default, render to stdout. If the output is piped somewhere else, # render to stderr. The prompt_toolkit render output is not meant to be # consumed by something other then a terminal, so this is a reasonable # default. if sys.stdout.isatty(): stdout = sys.stdout else: stdout = sys.stderr if is_windows(): from .conemu import ConEmuOutput from .win32 import Win32Output from .windows10 import is_win_vt100_enabled, Windows10_Output if is_win_vt100_enabled(): return cast(Output, Windows10_Output(stdout)) if is_conemu_ansi(): return cast(Output, ConEmuOutput(stdout)) else: return Win32Output(stdout) else: from .vt100 import Vt100_Output return Vt100_Output.from_pty(stdout, term=get_term_environment_variable())
def create_output(stdout=None, true_color=False): """ Return an :class:`~prompt_toolkit.output.Output` instance for the command line. :param true_color: When True, use 24bit colors instead of 256 colors. (`bool` or :class:`~prompt_toolkit.filters.SimpleFilter`.) Notes ----- This method was forked from the mainline prompt-toolkit repo. Copyright (c) 2014, Jonathan Slenders, All rights reserved. This is deprecated and slated for removal after a prompt-toolkit v0.57+ release. """ stdout = stdout or sys.__stdout__ true_color = to_simple_filter(true_color) if is_windows(): if is_conemu_ansi(): return ConEmuOutput(stdout) else: return Win32Output(stdout) else: term = os.environ.get('TERM', '') if PY2: term = term.decode('utf-8') return Vt100_Output.from_pty(stdout, true_color=true_color)#, term=term)
def create_input(stdin: Optional[TextIO] = None) -> Input: """ Create the appropriate `Input` object for the current os/environment. """ if is_windows(): from .win32 import Win32Input return Win32Input(stdin or sys.stdin) else: from .vt100 import Vt100Input # If no input TextIO is given, use stdin/stdout. if stdin is None: # Try stdin first, if it's a TTY. if sys.stdin.isatty(): stdin = sys.stdin # If stdin is not a TTY, it's possible we're piping something into # stdin. Use stdout instead if stdout is a TTY. (We can actually # use stdout to read input from, this is how a $PAGER works.) elif sys.stdout.isatty(): stdin = sys.stdout # If stdout is also not a tty, then use stdin. (This will print a # "Input is not a terminal" warning in `Vt100Input`.) else: stdin = sys.stdin return Vt100Input(stdin)
def generate_layout(input_field: TextArea, output_field: TextArea, log_field: TextArea): copy_key = "CTRL + SHIFT" if is_windows() else "fn" root_container = VSplit([ FloatContainer( HSplit([ output_field, Window(height=1, char='-', style='class:line'), input_field, TextArea(height=1, text=f'Version: {version} [Double Ctrl + C] QUIT ' f'Hold down "{copy_key}" for selecting and copying text', style='class:label'), ]), [ # Completion menus. Float(xcursor=True, ycursor=True, transparent=True, content=CompletionsMenu( max_height=16, scroll_offset=1)), ] ), Window(width=1, char='|', style='class:line'), log_field, ]) return Layout(root_container, focused_element=input_field)
def create_output( stdout: Optional[TextIO] = None, always_prefer_tty: bool = True ) -> Output: """ Return an :class:`~prompt_toolkit.output.Output` instance for the command line. :param stdout: The stdout object :param always_prefer_tty: When set, look for `sys.stderr` if `sys.stdout` is not a TTY. (The prompt_toolkit render output is not meant to be consumed by something other then a terminal, so this is a reasonable default.) """ # Consider TERM and PROMPT_TOOLKIT_COLOR_DEPTH environment variables. # Notice that PROMPT_TOOLKIT_COLOR_DEPTH value is the default that's used # if the Application doesn't override it. term_from_env = get_term_environment_variable() color_depth_from_env = ColorDepth.from_env() if stdout is None: # By default, render to stdout. If the output is piped somewhere else, # render to stderr. stdout = sys.stdout if always_prefer_tty: for io in [sys.stdout, sys.stderr]: if io.isatty(): stdout = io break # If the patch_stdout context manager has been used, then sys.stdout is # replaced by this proxy. For prompt_toolkit applications, we want to use # the real stdout. from prompt_toolkit.patch_stdout import StdoutProxy while isinstance(stdout, StdoutProxy): stdout = stdout.original_stdout if is_windows(): from .conemu import ConEmuOutput from .win32 import Win32Output from .windows10 import Windows10_Output, is_win_vt100_enabled if is_win_vt100_enabled(): return cast( Output, Windows10_Output(stdout, default_color_depth=color_depth_from_env), ) if is_conemu_ansi(): return cast( Output, ConEmuOutput(stdout, default_color_depth=color_depth_from_env) ) else: return Win32Output(stdout, default_color_depth=color_depth_from_env) else: from .vt100 import Vt100_Output return Vt100_Output.from_pty( stdout, term=term_from_env, default_color_depth=color_depth_from_env )
def load_style(config_map=global_config_map): """ Return a dict mapping {ui_style_name -> style_dict}. """ # Load config color_top_pane = config_map.get("top-pane").value color_bottom_pane = config_map.get("bottom-pane").value color_output_pane = config_map.get("output-pane").value color_input_pane = config_map.get("input-pane").value color_logs_pane = config_map.get("logs-pane").value color_terminal_primary = config_map.get("terminal-primary").value if is_windows(): # Load default style style = win32_code_style # Translate HEX to ANSI color_top_pane = hex_to_ansi(color_top_pane) color_bottom_pane = hex_to_ansi(color_bottom_pane) color_output_pane = hex_to_ansi(color_output_pane) color_input_pane = hex_to_ansi(color_input_pane) color_logs_pane = hex_to_ansi(color_logs_pane) color_terminal_primary = hex_to_ansi(color_terminal_primary) # Apply custom configuration style[ "output-field"] = "bg:" + color_output_pane + " " + color_terminal_primary style["input-field"] = "bg:" + color_input_pane + " " + style[ "input-field"].split(' ')[-1] style["log-field"] = "bg:" + color_logs_pane + " " + style[ "log-field"].split(' ')[-1] style["header"] = "bg:" + color_top_pane + " " + style["header"].split( ' ')[-1] style["footer"] = "bg:" + color_bottom_pane + " " + style[ "footer"].split(' ')[-1] style["primary"] = color_terminal_primary style["search"] = color_terminal_primary style["search.current"] = color_terminal_primary return Style.from_dict(style) else: # Load default style style = default_ui_style # Apply custom configuration style[ "output-field"] = "bg:" + color_output_pane + " " + color_terminal_primary style["input-field"] = "bg:" + color_input_pane + " " + style[ "input-field"].split(' ')[-1] style["log-field"] = "bg:" + color_logs_pane + " " + style[ "log-field"].split(' ')[-1] style["header"] = "bg:" + color_top_pane + " " + style["header"].split( ' ')[-1] style["footer"] = "bg:" + color_bottom_pane + " " + style[ "footer"].split(' ')[-1] style["primary"] = color_terminal_primary return Style.from_dict(style)
def list_clients(): if is_windows(): from .windows import list_clients return list_clients() else: from .posix import list_clients return list_clients()
def _get_asyncio_loop_cls(): # Inline import, to make sure the rest doesn't break on Python 2. (Where # asyncio is not available.) if is_windows(): from prompt_toolkit.eventloop.asyncio_win32 import Win32AsyncioEventLoop as AsyncioEventLoop else: from prompt_toolkit.eventloop.asyncio_posix import PosixAsyncioEventLoop as AsyncioEventLoop return AsyncioEventLoop
def load_style(): """ Return a dict mapping {ui_style_name -> style_dict}. """ if is_windows(): return Style.from_dict(win32_code_style) else: return Style.from_dict(default_ui_style)
def height_is_known(self) -> bool: """ True when the height from the cursor until the bottom of the terminal is known. (It's often nicer to draw bottom toolbars only if the height is known, in order to avoid flickering when the CPR response arrives.) """ return self.full_screen or self._min_available_height > 0 or \ is_windows() # On Windows, we don't have to wait for a CPR.
def create_terminal(command, before_exec_func): if is_windows(): from .backends.win32 import Win32Terminal return Win32Terminal() else: from .backends.posix import PosixTerminal return PosixTerminal.from_command(command, before_exec_func=before_exec_func)
def request_absolute_cursor_position(self): """ Get current cursor position. We do this to calculate the minimum available height that we can consume for rendering the prompt. This is the available space below te cursor. For vt100: Do CPR request. (answer will arrive later.) For win32: Do API call. (Answer comes immediately.) """ # Only do this request when the cursor is at the top row. (after a # clear or reset). We will rely on that in `report_absolute_cursor_row`. assert self._cursor_pos.y == 0 # In full-screen mode, always use the total height as min-available-height. if self.full_screen: self._min_available_height = self.output.get_size().rows # For Win32, we have an API call to get the number of rows below the # cursor. elif is_windows(): self._min_available_height = self.output.get_rows_below_cursor_position( ) # Use CPR. else: if self.cpr_support == CPR_Support.NOT_SUPPORTED: return def do_cpr(): # Asks for a cursor position report (CPR). self._waiting_for_cpr_futures.append(Future()) self.output.ask_for_cpr() if self.cpr_support == CPR_Support.SUPPORTED: do_cpr() # If we don't know whether CPR is supported, only do a request if # none is pending, and test it, using a timer. elif self.cpr_support == CPR_Support.UNKNOWN and not self.waiting_for_cpr: do_cpr() def timer(): time.sleep(self.CPR_TIMEOUT) # Not set in the meantime -> not supported. if self.cpr_support == CPR_Support.UNKNOWN: self.cpr_support = CPR_Support.NOT_SUPPORTED if self.cpr_not_supported_callback: # Make sure to call this callback in the main thread. get_event_loop().call_from_executor( self.cpr_not_supported_callback) t = threading.Thread(target=timer) t.daemon = True t.start()
def create_input(stdin: Optional[TextIO] = None) -> Input: stdin = stdin or sys.stdin if is_windows(): from .win32 import Win32Input return Win32Input(stdin) else: from .vt100 import Vt100Input return Vt100Input(stdin)
def select( self, timeout: Optional[float] = None ) -> List[Tuple["SelectorKey", "_EventMask"]]: # If there are tasks in the current event loop, # don't run the input hook. if len(getattr(get_event_loop(), "_ready", [])) > 0: return self.selector.select(timeout=timeout) ready = False result = None # Run selector in other thread. def run_selector() -> None: nonlocal ready, result result = self.selector.select(timeout=timeout) os.write(self._w, b"x") ready = True th = threading.Thread(target=run_selector) th.start() def input_is_ready() -> bool: return ready # Call inputhook. # The inputhook function is supposed to return when our selector # becomes ready. The inputhook can do that by registering the fd in its # own loop, or by checking the `input_is_ready` function regularly. self.inputhook(InputHookContext(self._r, input_is_ready)) # Flush the read end of the pipe. try: # Before calling 'os.read', call select.select. This is required # when the gevent monkey patch has been applied. 'os.read' is never # monkey patched and won't be cooperative, so that would block all # other select() calls otherwise. # See: http://www.gevent.org/gevent.os.html # Note: On Windows, this is apparently not an issue. # However, if we would ever want to add a select call, it # should use `windll.kernel32.WaitForMultipleObjects`, # because `select.select` can't wait for a pipe on Windows. if not is_windows(): select.select([self._r], [], [], None) os.read(self._r, 1024) except OSError: # This happens when the window resizes and a SIGWINCH was received. # We get 'Error: [Errno 4] Interrupted system call' # Just ignore. pass # Wait for the real selector to be done. th.join() assert result is not None return result
def create_input(stdin=None): stdin = stdin or sys.stdin if is_windows(): from .win32 import Win32Input return Win32Input(stdin) else: from .vt100 import Vt100Input return Vt100Input(stdin)
def request_absolute_cursor_position(self): """ Get current cursor position. We do this to calculate the minimum available height that we can consume for rendering the prompt. This is the available space below te cursor. For vt100: Do CPR request. (answer will arrive later.) For win32: Do API call. (Answer comes immediately.) """ # Only do this request when the cursor is at the top row. (after a # clear or reset). We will rely on that in `report_absolute_cursor_row`. assert self._cursor_pos.y == 0 # In full-screen mode, always use the total height as min-available-height. if self.full_screen: self._min_available_height = self.output.get_size().rows # For Win32, we have an API call to get the number of rows below the # cursor. elif is_windows(): self._min_available_height = self.output.get_rows_below_cursor_position() # Use CPR. else: if self.cpr_support == CPR_Support.NOT_SUPPORTED: return def do_cpr(): # Asks for a cursor position report (CPR). self._waiting_for_cpr_futures.append(Future()) self.output.ask_for_cpr() if self.cpr_support == CPR_Support.SUPPORTED: do_cpr() # If we don't know whether CPR is supported, only do a request if # none is pending, and test it, using a timer. elif self.cpr_support == CPR_Support.UNKNOWN and not self.waiting_for_cpr: do_cpr() def timer(): time.sleep(self.CPR_TIMEOUT) # Not set in the meantime -> not supported. if self.cpr_support == CPR_Support.UNKNOWN: self.cpr_support = CPR_Support.NOT_SUPPORTED if self.cpr_not_supported_callback: # Make sure to call this callback in the main thread. get_event_loop().call_from_executor(self.cpr_not_supported_callback) t = threading.Thread(target=timer) t.daemon = True t.start()
def create_write_console_ex(session, stderr_format): output = session.app.output from prompt_toolkit.utils import is_windows write_console_ex = None if is_windows(): from prompt_toolkit.output.win32 import Win32Output if isinstance(output, Win32Output): # we use print_formatted_text to support ANSI sequences in older Windows from prompt_toolkit.formatted_text import ANSI from prompt_toolkit.shortcuts import print_formatted_text def write_console_ex(buf, otype): if otype == 0: if sys.stdout: buf = buf.replace("\r\n", "\n") sbuf = buf.split("\r") for i, b in enumerate(sbuf): print_formatted_text(ANSI(b), end="", output=output) if i < len(sbuf) - 1: output.write("\r") output.flush() TERMINAL_CURSOR_AT_BEGINNING[0] = buf.endswith("\n") else: if sys.stderr: buf = buf.replace("\r\n", "\n") sbuf = buf.split("\r") for i, b in enumerate(sbuf): print_formatted_text(ANSI(stderr_format.format(b)), end="", output=output) if i < len(sbuf) - 1: output.write("\r") output.flush() TERMINAL_CURSOR_AT_BEGINNING[0] = buf.endswith("\n") if not write_console_ex: def write_console_ex(buf, otype): if otype == 0: # although we do not use sys.stdout and sys.stderr directly, we use them to flag # whether we should print to them if sys.stdout: output.write_raw(buf) output.flush() TERMINAL_CURSOR_AT_BEGINNING[0] = buf.endswith("\n") else: if sys.stderr: output.write_raw(stderr_format.format(buf)) output.flush() TERMINAL_CURSOR_AT_BEGINNING[0] = buf.endswith("\n") return write_console_ex
def create_terminal(command, before_exec_func, fake=False): if fake: from .backends.simulated import SimTerminal return SimTerminal() elif is_windows(): from .backends.win32 import Win32Terminal return Win32Terminal() else: from .backends.posix import PosixTerminal return PosixTerminal.from_command(command, before_exec_func=before_exec_func)
def create_write_console_ex(session, stderr_format): app = session.app output = app.output from prompt_toolkit.utils import is_windows write_console_ex = None if is_windows(): from prompt_toolkit.output.win32 import Win32Output if isinstance(output, Win32Output): # we use print_formatted_text to support ANSI sequences in older Windows from prompt_toolkit.formatted_text import ANSI from prompt_toolkit.shortcuts import print_formatted_text def write_console_ex(buf, otype): if otype == 0: if not SUPPRESS_STDOUT: buf = buf.replace("\r\n", "\n") sbuf = buf.split("\r") for i, b in enumerate(sbuf): print_formatted_text(ANSI(b), end="", output=output) if i < len(sbuf) - 1: output.write("\r") output.flush() TERMINAL_CURSOR_AT_BEGINNING[0] = buf.endswith("\n") else: if not SUPPRESS_STDERR: buf = buf.replace("\r\n", "\n") sbuf = buf.split("\r") for i, b in enumerate(sbuf): print_formatted_text(ANSI(stderr_format.format(b)), end="", output=output) if i < len(sbuf) - 1: output.write("\r") output.flush() TERMINAL_CURSOR_AT_BEGINNING[0] = buf.endswith("\n") if not write_console_ex: def write_console_ex(buf, otype): if otype == 0: if not SUPPRESS_STDOUT: output.write_raw(buf) output.flush() TERMINAL_CURSOR_AT_BEGINNING[0] = buf.endswith("\n") else: if not SUPPRESS_STDERR: output.write_raw(stderr_format.format(buf)) output.flush() TERMINAL_CURSOR_AT_BEGINNING[0] = buf.endswith("\n") return write_console_ex
def create_event_loop(recognize_win32_paste=True): """ Create and return an :class:`~prompt_toolkit.eventloop.base.EventLoop` instance. """ if is_windows(): from .win32 import Win32EventLoop return Win32EventLoop(recognize_paste=recognize_win32_paste) else: from .posix import PosixEventLoop return PosixEventLoop()
def create_pipe_input(): """ Create an input pipe. This is mostly useful for unit testing. """ if is_windows(): from .win32_pipe import Win32PipeInput return Win32PipeInput() else: from .posix_pipe import PosixPipeInput return PosixPipeInput()
def build_model_df_data( config_map: ClientConfigAdapter, to_print: Optional[List[str]] = None) -> List[Tuple[str, Any]]: model_data = [] for traversal_item in config_map.traverse(): if to_print is not None and traversal_item.attr not in to_print: continue attr_printout = (" " * (traversal_item.depth - 1) + (u"\u221F " if not is_windows() else " ") + traversal_item.attr ) if traversal_item.depth else traversal_item.attr model_data.append((attr_printout, traversal_item.printable_value)) return model_data
def bind_and_listen_on_socket(socket_name, accept_callback): """ Return socket name. :param accept_callback: Callback is called with a `PipeConnection` as argument. """ if is_windows(): from .win32_server import bind_and_listen_on_win32_socket return bind_and_listen_on_win32_socket(socket_name, accept_callback) else: from .posix import bind_and_listen_on_posix_socket return bind_and_listen_on_posix_socket(socket_name, accept_callback)
def create_pipe_input(responds_to_cpr: bool = True) -> PipeInput: """ Create an input pipe. This is mostly useful for unit testing. """ if is_windows(): from .win32_pipe import Win32PipeInput return Win32PipeInput(responds_to_cpr=responds_to_cpr) else: from .posix_pipe import PosixPipeInput return PosixPipeInput(responds_to_cpr=responds_to_cpr)
def reset(self, _scroll=False, leave_alternate_screen=True): # Reset position self._cursor_pos = Point(x=0, y=0) # Remember the last screen instance between renderers. This way, # we can create a `diff` between two screens and only output the # difference. It's also to remember the last height. (To show for # instance a toolbar at the bottom position.) self._last_screen = None self._last_size = None self._last_char = None # When the style hash changes, we have to do a full redraw as well as # clear the `_attrs_for_token` dictionary. self._last_style_hash = None self._attrs_for_token = None # Default MouseHandlers. (Just empty.) self.mouse_handlers = MouseHandlers() # Remember the last title. Only set the title when it changes. self._last_title = None #: Space from the top of the layout, until the bottom of the terminal. #: We don't know this until a `report_absolute_cursor_row` call. self._min_available_height = 0 # In case of Windown, also make sure to scroll to the current cursor # position. (Only when rendering the first time.) if is_windows() and _scroll: self.output.scroll_buffer_to_prompt() # Quit alternate screen. if self._in_alternate_screen and leave_alternate_screen: self.output.quit_alternate_screen() self._in_alternate_screen = False # Disable mouse support. if self._mouse_support_enabled: self.output.disable_mouse_support() self._mouse_support_enabled = False # Disable bracketed paste. if self._bracketed_paste_enabled: self.output.disable_bracketed_paste() self._bracketed_paste_enabled = False # Flush output. `disable_mouse_support` needs to write to stdout. self.output.flush()
def get_default_shell(): """ return the path to the default shell for the current user. """ if is_windows(): return 'cmd.exe' else: import pwd import getpass if 'SHELL' in os.environ: return os.environ['SHELL'] else: username = getpass.getuser() shell = pwd.getpwnam(username).pw_shell return shell
def _(event: E) -> None: """ Handling of mouse events for Windows. """ assert is_windows() # This key binding should only exist for Windows. # Parse data. event_type, x, y = event.data.split(';') x = int(x) y = int(y) # Make coordinates absolute to the visible part of the terminal. screen_buffer_info = event.app.renderer.output.get_win32_screen_buffer_info() rows_above_cursor = screen_buffer_info.dwCursorPosition.Y - event.app.renderer._cursor_pos.y y -= rows_above_cursor # Call the mouse event handler. handler = event.app.renderer.mouse_handlers.mouse_handlers[x, y] handler(MouseEvent(position=Point(x=x, y=y), event_type=event_type))
def request_absolute_cursor_position(self): """ Get current cursor position. For vt100: Do CPR request. (answer will arrive later.) For win32: Do API call. (Answer comes immediately.) """ # Only do this request when the cursor is at the top row. (after a # clear or reset). We will rely on that in `report_absolute_cursor_row`. assert self._cursor_pos.y == 0 # For Win32, we have an API call to get the number of rows below the # cursor. if is_windows(): self._min_available_height = self.output.get_rows_below_cursor_position() else: if self.use_alternate_screen: self._min_available_height = self.output.get_size().rows else: # Asks for a cursor position report (CPR). self.output.ask_for_cpr()
def default(cls, term: str = '') -> 'ColorDepth': """ If the user doesn't specify a color depth, use this as a default. """ if term in ('linux', 'eterm-color'): return cls.DEPTH_4_BIT # For now, always use 4 bit color on Windows 10 by default, even when # vt100 escape sequences with ENABLE_VIRTUAL_TERMINAL_PROCESSING are # supported. We don't have a reliable way yet to know whether our # console supports true color or only 4-bit. if is_windows() and 'PROMPT_TOOLKIT_COLOR_DEPTH' not in os.environ: return cls.DEPTH_4_BIT # Check the `PROMPT_TOOLKIT_COLOR_DEPTH` environment variable. all_values = [i.value for i in ColorDepth] if os.environ.get('PROMPT_TOOLKIT_COLOR_DEPTH') in all_values: return cls(os.environ['PROMPT_TOOLKIT_COLOR_DEPTH']) return cls.DEPTH_8_BIT
def is_win_vt100_enabled() -> bool: """ Returns True when we're running Windows and VT100 escape sequences are supported. """ if not is_windows(): return False hconsole = windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE) # Get original console mode. original_mode = DWORD(0) windll.kernel32.GetConsoleMode(hconsole, byref(original_mode)) try: # Try to enable VT100 sequences. result = windll.kernel32.SetConsoleMode(hconsole, DWORD( ENABLE_PROCESSED_INPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) return result == 1 finally: windll.kernel32.SetConsoleMode(hconsole, original_mode)
def call_inputhook(self, input_is_ready_func): """ Call the inputhook. (Called by a prompt-toolkit eventloop.) """ self._input_is_ready = input_is_ready_func # Start thread that activates this pipe when there is input to process. def thread(): input_is_ready_func(wait=True) os.write(self._w, b'x') threading.Thread(target=thread).start() # Call inputhook. self.inputhook(self) # Flush the read end of the pipe. try: # Before calling 'os.read', call select.select. This is required # when the gevent monkey patch has been applied. 'os.read' is never # monkey patched and won't be cooperative, so that would block all # other select() calls otherwise. # See: http://www.gevent.org/gevent.os.html # Note: On Windows, this is apparently not an issue. # However, if we would ever want to add a select call, it # should use `windll.kernel32.WaitForMultipleObjects`, # because `select.select` can't wait for a pipe on Windows. if not is_windows(): select_fds([self._r], timeout=None) os.read(self._r, 1024) except OSError: # This happens when the window resizes and a SIGWINCH was received. # We get 'Error: [Errno 4] Interrupted system call' # Just ignore. pass self._input_is_ready = None
def run(): if is_windows(): from prompt_toolkit.eventloop.win32 import Win32EventLoop loop = Win32EventLoop() else: from prompt_toolkit.eventloop.posix import PosixEventLoop from prompt_toolkit.eventloop.select import SelectSelector loop = PosixEventLoop(selector=SelectSelector) set_event_loop(loop) if not sys.stdin.isatty(): pager = Pager.from_pipe() pager.run() else: parser = argparse.ArgumentParser(description='Browse through a text file.') parser.add_argument('filename', metavar='filename', nargs='+', help='The file to be displayed.') parser.add_argument('--vi', help='Prefer Vi key bindings.', action='store_true') parser.add_argument('--emacs', help='Prefer Emacs key bindings.', action='store_true') args = parser.parse_args() # Determine input mode. vi_mode = 'vi' in os.environ.get('EDITOR', '').lower() if args.vi: vi_mode = True if args.emacs: vi_mode = False pager = Pager(vi_mode=vi_mode) # Open files. for filename in args.filename: # When a filename is given, take a lexer from that filename. lexer = PygmentsLexer.from_filename(filename, sync_from_start=False) pager.add_source(FileSource(filename, lexer=lexer)) # Run UI. pager.run()
def create_output(stdout=None): """ Return an :class:`~prompt_toolkit.output.Output` instance for the command line. :param stdout: The stdout object """ stdout = stdout or sys.__stdout__ if is_windows(): from .conemu import ConEmuOutput from .win32 import Win32Output from .windows10 import is_win_vt100_enabled, Windows10_Output if is_win_vt100_enabled(): return Windows10_Output(stdout) if is_conemu_ansi(): return ConEmuOutput(stdout) else: return Win32Output(stdout) else: from .vt100 import Vt100_Output return Vt100_Output.from_pty( stdout, term=get_term_environment_variable())
# Help Window. 'window-border': '#aaaaaa', 'window-title': 'bg:#bbbbbb #000000', # Meta-enter message. 'accept-message': 'bg:#ffff88 #444444', # Exit confirmation. 'exit-confirmation': 'bg:#884444 #ffffff', } # Some changes to get a bit more contrast on Windows consoles. # (They only support 16 colors.) if is_windows() and not is_conemu_ansi() and not is_windows_vt100_supported(): default_ui_style.update({ 'sidebar.title': 'bg:#00ff00 #ffffff', 'exitconfirmation': 'bg:#ff4444 #ffffff', 'toolbar.validation': 'bg:#ff4444 #ffffff', 'menu.completions.completion': 'bg:#ffffff #000000', 'menu.completions.completion.current': 'bg:#aaaaaa #000000', }) blue_ui_style = {} blue_ui_style.update(default_ui_style) #blue_ui_style.update({ # # Line numbers. # Token.LineNumber: '#aa6666',
return b''.join(self._data) def flush(self): pass def isatty(self): return True def fileno(self): # File descriptor is not used for printing formatted text. # (It is only needed for getting the terminal size.) return -1 @pytest.mark.skipif( is_windows(), reason="Doesn't run on Windows yet.") def test_print_formatted_text(): f = _Capture() pt_print([('', 'hello'), ('', 'world')], file=f) assert b'hello' in f.data assert b'world' in f.data @pytest.mark.skipif( is_windows(), reason="Doesn't run on Windows yet.") def test_with_style(): f = _Capture() style = Style.from_dict({ 'hello': '#ff0066', 'world': '#44ff44 italic', })
def __init__(self, get_globals=None, get_locals=None, history_filename=None, vi_mode=False, input=None, output=None, color_depth=None, # For internal use. extra_key_bindings=None, _completer=None, _validator=None, _lexer=None, _extra_buffer_processors=None, _extra_layout_body=None, _extra_toolbars=None, _input_buffer_height=None): self.get_globals = get_globals or (lambda: {}) self.get_locals = get_locals or self.get_globals self._completer = _completer or PythonCompleter(self.get_globals, self.get_locals) self._validator = _validator or PythonValidator(self.get_compiler_flags) self._lexer = _lexer or PygmentsLexer(PythonLexer) if history_filename: self.history = ThreadedHistory(FileHistory(history_filename)) else: self.history = InMemoryHistory() self._input_buffer_height = _input_buffer_height self._extra_layout_body = _extra_layout_body or [] self._extra_toolbars = _extra_toolbars or [] self._extra_buffer_processors = _extra_buffer_processors or [] self.extra_key_bindings = extra_key_bindings or KeyBindings() # Settings. self.show_signature = False self.show_docstring = False self.show_meta_enter_message = True self.completion_visualisation = CompletionVisualisation.MULTI_COLUMN self.completion_menu_scroll_offset = 1 self.show_line_numbers = False self.show_status_bar = True self.wrap_lines = True self.complete_while_typing = True self.paste_mode = False # When True, don't insert whitespace after newline. self.confirm_exit = True # Ask for confirmation when Control-D is pressed. self.accept_input_on_enter = 2 # Accept when pressing Enter 'n' times. # 'None' means that meta-enter is always required. self.enable_open_in_editor = True self.enable_system_bindings = True self.enable_input_validation = True self.enable_auto_suggest = False self.enable_mouse_support = False self.enable_history_search = False # When True, like readline, going # back in history will filter the # history on the records starting # with the current input. self.enable_syntax_highlighting = True self.swap_light_and_dark = False self.highlight_matching_parenthesis = False self.show_sidebar = False # Currently show the sidebar. self.show_sidebar_help = True # When the sidebar is visible, also show the help text. self.show_exit_confirmation = False # Currently show 'Do you really want to exit?' self.terminal_title = None # The title to be displayed in the terminal. (None or string.) self.exit_message = 'Do you really want to exit?' self.insert_blank_line_after_output = True # (For the REPL.) # The buffers. self.default_buffer = self._create_buffer() self.search_buffer = Buffer() self.docstring_buffer = Buffer(read_only=True) # Tokens to be shown at the prompt. self.prompt_style = 'classic' # The currently active style. self.all_prompt_styles = { # Styles selectable from the menu. 'ipython': IPythonPrompt(self), 'classic': ClassicPrompt(), } self.get_input_prompt = lambda: \ self.all_prompt_styles[self.prompt_style].in_prompt() self.get_output_prompt = lambda: \ self.all_prompt_styles[self.prompt_style].out_prompt() #: Load styles. self.code_styles = get_all_code_styles() self.ui_styles = get_all_ui_styles() self._current_code_style_name = 'default' self._current_ui_style_name = 'default' if is_windows(): self._current_code_style_name = 'win32' self._current_style = self._generate_style() self.color_depth = color_depth or ColorDepth.default() self.max_brightness = 1.0 self.min_brightness = 0.0 # Options to be configurable from the sidebar. self.options = self._create_options() self.selected_option_index = 0 #: Incremeting integer counting the current statement. self.current_statement_index = 1 # Code signatures. (This is set asynchronously after a timeout.) self.signatures = [] # Boolean indicating whether we have a signatures thread running. # (Never run more than one at the same time.) self._get_signatures_thread_running = False self.output = output or create_output() self.input = input or create_input(sys.stdin) self.style_transformation = merge_style_transformations([ ConditionalStyleTransformation( SwapLightAndDarkStyleTransformation(), filter=Condition(lambda: self.swap_light_and_dark)), AdjustBrightnessStyleTransformation( lambda: self.min_brightness, lambda: self.max_brightness), ]) self.ptpython_layout = PtPythonLayout( self, lexer=DynamicLexer( lambda: self._lexer if self.enable_syntax_highlighting else SimpleLexer()), input_buffer_height=self._input_buffer_height, extra_buffer_processors=self._extra_buffer_processors, extra_body=self._extra_layout_body, extra_toolbars=self._extra_toolbars) self.app = self._create_application() if vi_mode: self.app.editing_mode = EditingMode.VI
def __init__(self, get_globals=None, get_locals=None, history_filename=None, vi_mode=False, # For internal use. _completer=None, _validator=None, _python_prompt_control=None, _lexer=None, _extra_buffers=None, _extra_buffer_processors=None, _on_start=None, _extra_layout_body=None, _extra_toolbars=None, _input_buffer_height=None, _accept_action=AcceptAction.RETURN_DOCUMENT, _on_exit=AbortAction.RAISE_EXCEPTION): self.get_globals = get_globals or (lambda: {}) self.get_locals = get_locals or self.get_globals self._completer = _completer or PythonCompleter(self.get_globals, self.get_locals) self._validator = _validator or PythonValidator(self.get_compiler_flags) self._history = FileHistory(history_filename) if history_filename else InMemoryHistory() self._lexer = _lexer or PygmentsLexer(PythonLexer) self._extra_buffers = _extra_buffers self._accept_action = _accept_action self._on_exit = _on_exit self._on_start = _on_start self._input_buffer_height = _input_buffer_height self._extra_layout_body = _extra_layout_body or [] self._extra_toolbars = _extra_toolbars or [] self._extra_buffer_processors = _extra_buffer_processors or [] self._python_prompt_control = _python_prompt_control or PythonPrompt(self) # Settings. self.show_signature = True self.show_docstring = False self.completion_visualisation = CompletionVisualisation.MULTI_COLUMN self.completion_menu_scroll_offset = 1 self.show_line_numbers = True self.show_status_bar = True self.complete_while_typing = True self.vi_mode = vi_mode self.paste_mode = False # When True, don't insert whitespace after newline. self.confirm_exit = True # Ask for confirmation when Control-D is pressed. self.accept_input_on_enter = 2 # Accept when pressing Enter 'n' times. # 'None' means that meta-enter is always required. self.enable_open_in_editor = True self.enable_system_bindings = True self.enable_input_validation = True self.enable_history_search = False # When True, like readline, going # back in history will filter the # history on the records starting # with the current input. self.show_sidebar = False # Currently show the sidebar. self.show_sidebar_help = True # When the sidebar is visible, also show the help text. self.show_exit_confirmation = False # Currently show 'Do you really want to exit?' self.terminal_title = None # The title to be displayed in the terminal. (None or string.) self.exit_message = 'Do you really want to exit?' #: Load styles. self.code_styles = get_all_code_styles() self.ui_styles = get_all_ui_styles() self._current_code_style_name = 'default' self._current_ui_style_name = 'default' if is_windows(): self._current_code_style_name = 'win32' self._current_style = self._generate_style() # Options to be configurable from the sidebar. self.options = self._create_options() self.selected_option_index = 0 #: Incremeting integer counting the current statement. self.current_statement_index = 1 # Code signatures. (This is set asynchronously after a timeout.) self.signatures = [] # Use a KeyBindingManager for loading the key bindings. self.key_bindings_manager = KeyBindingManager( enable_vi_mode=Condition(lambda cli: self.vi_mode), enable_open_in_editor=Condition(lambda cli: self.enable_open_in_editor), enable_system_bindings=Condition(lambda cli: self.enable_system_bindings), # Disable all default key bindings when the sidebar or the exit confirmation # are shown. enable_all=Condition(lambda cli: not (self.show_sidebar or self.show_exit_confirmation))) load_python_bindings(self.key_bindings_manager, self) load_sidebar_bindings(self.key_bindings_manager, self) load_confirm_exit_bindings(self.key_bindings_manager, self) # Boolean indicating whether we have a signatures thread running. # (Never run more than one at the same time.) self._get_signatures_thread_running = False
from __future__ import unicode_literals # noinspection PyUnresolvedReferences import plenum.cli.ensure_logging_not_setup from typing import Dict import re from prompt_toolkit.utils import is_windows, is_conemu_ansi from plenum.client.signer import SimpleSigner if is_windows(): from prompt_toolkit.terminal.win32_output import Win32Output from prompt_toolkit.terminal.conemu_output import ConEmuOutput else: from prompt_toolkit.terminal.vt100_output import Vt100_Output import configparser import os from configparser import ConfigParser import time import ast from functools import reduce, partial import logging import sys from collections import defaultdict from prompt_toolkit.history import FileHistory
# Help Window. Token.Window.Border: '#bbbbbb', Token.Window.Title: 'bg:#bbbbbb #000000', # Meta-enter message. Token.AcceptMessage: 'bg:#ffff88 #444444', # Exit confirmation. Token.ExitConfirmation: 'bg:#884444 #ffffff', } # Some changes to get a bit more contrast on Windows consoles. # (They only support 16 colors.) if is_windows() and not is_conemu_ansi(): default_ui_style.update({ Token.Sidebar.Title: 'bg:#00ff00 #ffffff', Token.ExitConfirmation: 'bg:#ff4444 #ffffff', Token.Toolbar.Validation: 'bg:#ff4444 #ffffff', Token.Menu.Completions.Completion: 'bg:#ffffff #000000', Token.Menu.Completions.Completion.Current: 'bg:#aaaaaa #000000', }) blue_ui_style = {} blue_ui_style.update(default_ui_style) blue_ui_style.update({ # Line numbers. Token.LineNumber: '#aa6666',
def __init__(self, get_globals=None, get_locals=None, history_filename=None, vi_mode=False, # For internal use. _completer=None, _validator=None, _lexer=None, _extra_buffers=None, _extra_buffer_processors=None, _on_start=None, _extra_layout_body=None, _extra_toolbars=None, _input_buffer_height=None, _accept_action=AcceptAction.RETURN_DOCUMENT, _on_exit=AbortAction.RAISE_EXCEPTION): self.get_globals = get_globals or (lambda: {}) self.get_locals = get_locals or self.get_globals self._completer = _completer or PythonCompleter(self.get_globals, self.get_locals) self._validator = _validator or PythonValidator(self.get_compiler_flags) self.history = FileHistory(history_filename) if history_filename else InMemoryHistory() self._lexer = _lexer or PygmentsLexer(PythonLexer) self._extra_buffers = _extra_buffers self._accept_action = _accept_action self._on_exit = _on_exit self._on_start = _on_start self._input_buffer_height = _input_buffer_height self._extra_layout_body = _extra_layout_body or [] self._extra_toolbars = _extra_toolbars or [] self._extra_buffer_processors = _extra_buffer_processors or [] # Settings. self.settings = Settings({ 'show_signature': True, 'show_docstring': False, 'show_meta_enter_message': True, 'completion_visualisation': 'CompletionVisualisation.MULTI_COLUMN', 'completion_menu_scroll_offset': 1, 'show_line_numbers': False, 'show_status_bar': True, 'wrap_lines': True, 'complete_while_typing': True, 'vi_mode': vi_mode, 'paste_mode': False, # When True, don't insert whitespace after newline. 'confirm_exit': True, # Ask for confirmation when Control-D is pressed. 'accept_input_on_enter': 2, # Accept when pressing Enter 'n' times. # 'None' means that meta-enter is always required. 'enable_open_in_editor': True, 'enable_system_bindings': True, 'enable_input_validation': True, 'enable_auto_suggest': False, 'enable_mouse_support': False, 'enable_history_search': False, # When True, like readline, going # back in history will filter the # history on the records starting # with the current input. 'highlight_matching_parenthesis': True, 'show_sidebar': False, # Currently show the sidebar. 'show_sidebar_help': True, # When the sidebar is visible, also show the help text. 'terminal_title': None, # The title to be displayed in the terminal. (None or string.) 'exit_message': 'Do you really want to exit?', # Tokens to be shown at the prompt. 'prompt_style': 'classic' # The currently active style. }) self.show_exit_confirmation = False self.all_prompt_styles = { # Styles selectable from the menu. 'ipython': IPythonPrompt(self), 'classic': ClassicPrompt(), } self.get_input_prompt_tokens = lambda cli: \ self.all_prompt_styles[self.settings.prompt_style].in_tokens(cli) self.get_output_prompt_tokens = lambda cli: \ self.all_prompt_styles[self.settings.prompt_style].out_tokens(cli) #: Load styles. self.code_styles = get_all_code_styles() self.ui_styles = get_all_ui_styles() self._current_code_style_name = 'default' self._current_ui_style_name = 'default' if is_windows(): self._current_code_style_name = 'win32' self._current_style = self._generate_style() # Options to be configurable from the sidebar. self.options = self._create_options() self.selected_option_index = 0 #: Incremeting integer counting the current statement. self.current_statement_index = 1 # Code signatures. (This is set asynchronously after a timeout.) self.signatures = [] # Use a KeyBindingManager for loading the key bindings. self.key_bindings_manager = KeyBindingManager( enable_abort_and_exit_bindings=True, enable_search=True, enable_vi_mode=Condition(lambda cli: self.settings.vi_mode), enable_open_in_editor=Condition(lambda cli: self.settings.enable_open_in_editor), enable_system_bindings=Condition(lambda cli: self.settings.enable_system_bindings), enable_auto_suggest_bindings=Condition(lambda cli: self.settings.enable_auto_suggest), # Disable all default key bindings when the sidebar or the exit confirmation # are shown. enable_all=Condition(lambda cli: not (self.settings.show_sidebar or self.show_exit_confirmation))) load_python_bindings(self.key_bindings_manager, self) load_sidebar_bindings(self.key_bindings_manager, self) load_confirm_exit_bindings(self.key_bindings_manager, self) # Boolean indicating whether we have a signatures thread running. # (Never run more than one at the same time.) self._get_signatures_thread_running = False
def __init__(self, looper, basedirpath, nodeReg, cliNodeReg, output=None, debug=False, logFileName=None): self.curClientPort = None logging.root.addHandler(CliHandler(self.out)) self.looper = looper self.basedirpath = basedirpath self.nodeReg = nodeReg self.cliNodeReg = cliNodeReg # Used to store created clients self.clients = {} # clientName -> Client # To store the created requests self.requests = {} # To store the nodes created self.nodes = {} self.externalClientKeys = {} # type: Dict[str,str] self.cliCmds = {'status', 'new'} self.nodeCmds = self.cliCmds | {'keyshare'} self.helpablesCommands = self.cliCmds | self.nodeCmds self.simpleCmds = {'status', 'exit', 'quit', 'license'} self.commands = {'list', 'help'} | self.simpleCmds self.cliActions = {'send', 'show'} self.commands.update(self.cliCmds) self.commands.update(self.nodeCmds) self.node_or_cli = ['node', 'client'] self.nodeNames = list(self.nodeReg.keys()) + ["all"] self.debug = debug self.plugins = {} ''' examples: status new node Alpha new node all new client Joe client Joe send <msg> client Joe show 1 ''' psep = re.escape(os.path.sep) self.utilGrams = [ "(\s* (?P<simple>{}) \s*) |".format(self.relist(self.simpleCmds)), "(\s* (?P<load>load) \s+ (?P<file_name>[.a-zA-z0-9{}]+) \s*) |".format(psep), "(\s* (?P<command>help) (\s+ (?P<helpable>[a-zA-Z0-9]+) )? (\s+ (?P<node_or_cli>{}) )?\s*) |".format(self.relist(self.node_or_cli)), "(\s* (?P<command>list) \s*)" ] self.nodeGrams = [ "(\s* (?P<node_command>{}) \s+ (?P<node_or_cli>nodes?) \s+ (?P<node_name>[a-zA-Z0-9]+)\s*) |".format(self.relist(self.nodeCmds)), "(\s* (?P<load_plugins>load\s+plugins\s+from) \s+ (?P<plugin_dir>[a-zA-Z0-9-:{}]+) \s*)".format(psep), ] self.clientGrams = [ "(\s* (?P<client_command>{}) \s+ (?P<node_or_cli>clients?) \s+ (?P<client_name>[a-zA-Z0-9]+) \s*) |".format(self.relist(self.cliCmds)), "(\s* (?P<client>client) \s+ (?P<client_name>[a-zA-Z0-9]+) \s+ (?P<cli_action>send) \s+ (?P<msg>\{\s*.*\}) \s*) |", "(\s* (?P<client>client) \s+ (?P<client_name>[a-zA-Z0-9]+) \s+ (?P<cli_action>show) \s+ (?P<req_id>[0-9]+) \s*) |", "(\s* (?P<add_key>add\s+key) \s+ (?P<verkey>[a-fA-F0-9]+) \s+ (?P<for_client>for\s+client) \s+ (?P<identifier>[a-zA-Z0-9]+) \s*)", ] self.lexers = { 'node_command': SimpleLexer(Token.Keyword), 'command': SimpleLexer(Token.Keyword), 'helpable': SimpleLexer(Token.Keyword), 'load_plugins': SimpleLexer(Token.Keyword), 'load': SimpleLexer(Token.Keyword), 'node_or_cli': SimpleLexer(Token.Keyword), 'arg1': SimpleLexer(Token.Name), 'node_name': SimpleLexer(Token.Name), 'more_nodes': SimpleLexer(Token.Name), 'simple': SimpleLexer(Token.Keyword), 'client_command': SimpleLexer(Token.Keyword), 'add_key': SimpleLexer(Token.Keyword), 'verkey': SimpleLexer(Token.Literal), 'for_client': SimpleLexer(Token.Keyword), 'identifier': SimpleLexer(Token.Name), } self.clientWC = WordCompleter([]) self.completers = { 'node_command': WordCompleter(self.nodeCmds), 'client_command': WordCompleter(self.cliCmds), 'client': WordCompleter(['client']), 'command': WordCompleter(self.commands), 'node_or_cli': WordCompleter(self.node_or_cli), 'node_name': WordCompleter(self.nodeNames), 'more_nodes': WordCompleter(self.nodeNames), 'helpable': WordCompleter(self.helpablesCommands), 'load_plugins': WordCompleter(['load plugins from']), 'client_name': self.clientWC, 'cli_action': WordCompleter(self.cliActions), 'simple': WordCompleter(self.simpleCmds), 'add_key': WordCompleter(['add key']), 'for_client': WordCompleter(['for client']), } self.initializeGrammar() self.initializeGrammarLexer() self.initializeGrammarCompleter() self.style = PygmentsStyle.from_defaults({ Token.Operator: '#33aa33 bold', Token.Number: '#aa3333 bold', Token.Name: '#ffff00 bold', Token.Heading: 'bold', Token.TrailingInput: 'bg:#662222 #ffffff', Token.BoldGreen: '#33aa33 bold', Token.BoldOrange: '#ff4f2f bold', Token.BoldBlue: '#095cab bold'}) self.functionMappings = self.createFunctionMappings() self.voidMsg = "<none>" # Create an asyncio `EventLoop` object. This is a wrapper around the # asyncio loop that can be passed into prompt_toolkit. eventloop = create_asyncio_eventloop(looper.loop) pers_hist = FileHistory('.{}-cli-history'.format(self.name)) # Create interface. app = create_prompt_application('{}> '.format(self.name), lexer=self.grammarLexer, completer=self.grammarCompleter, style=self.style, history=pers_hist) if output: out = output else: if is_windows(): if is_conemu_ansi(): out = ConEmuOutput(sys.__stdout__) else: out = Win32Output(sys.__stdout__) else: out = CustomOutput.from_pty(sys.__stdout__, true_color=True) self.cli = CommandLineInterface( application=app, eventloop=eventloop, output=out) # Patch stdout in something that will always print *above* the prompt # when something is written to stdout. sys.stdout = self.cli.stdout_proxy() setupLogging(TRACE_LOG_LEVEL, Console.Wordage.mute, filename=logFileName) self.logger = getlogger("cli") self.print("\n{}-CLI (c) 2016 Evernym, Inc.".format(self.properName)) self.print("Node registry loaded.") self.print("None of these are created or running yet.") self.showNodeRegistry() self.print("Type 'help' for more information.")