def connected(self): # prompt_toolkit internally checks if it's on windows during output rendering but # we need to force that we use Vt100_Output not Win32_Output from prompt_toolkit import renderer renderer.is_windows = lambda: False def get_size(): return self._size self._cli = CommandLineInterface( application=create_prompt_application(self._shell.prompt), eventloop=UnstoppableEventLoop(create_asyncio_eventloop( self._loop)), input=PatchedStdinInput(sys.stdin), output=Vt100_Output(self, get_size)) self._cb = self._cli.create_eventloop_callbacks() self._inputstream = InputStream(self._cb.feed_key) # Taken from prompt_toolkit telnet server # https://github.com/jonathanslenders/python-prompt-toolkit/blob/99fa7fae61c9b4ed9767ead3b4f9b1318cfa875d/prompt_toolkit/contrib/telnet/server.py#L165 self._cli._is_running = True if self._shell.welcome_message is not None: self.send(self._shell.welcome_message.encode()) self._cli._redraw()
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_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 attach(self, detach_other_clients=False, true_color=False): """ Attach client user interface. """ assert isinstance(detach_other_clients, bool) assert isinstance(true_color, bool) self._send_size() self._send_packet( { "cmd": "start-gui", "detach-others": detach_other_clients, "true-color": true_color, "term": os.environ.get("TERM", ""), "data": "", } ) with raw_mode(sys.stdin.fileno()): data_buffer = b"" stdin_fd = sys.stdin.fileno() socket_fd = self.socket.fileno() current_timeout = INPUT_TIMEOUT # Timeout, used to flush escape sequences. with call_on_sigwinch(self._send_size): while True: r, w, x = _select([stdin_fd, socket_fd], [], [], current_timeout) if socket_fd in r: # Received packet from server. data = self.socket.recv(1024) if data == b"": # End of file. Connection closed. # Reset terminal o = Vt100_Output.from_pty(sys.stdout) o.quit_alternate_screen() o.disable_mouse_support() o.disable_bracketed_paste() o.reset_attributes() o.flush() return else: data_buffer += data while b"\0" in data_buffer: pos = data_buffer.index(b"\0") self._process(data_buffer[:pos]) data_buffer = data_buffer[pos + 1 :] elif stdin_fd in r: # Got user input. self._process_stdin() current_timeout = INPUT_TIMEOUT else: # Timeout. (Tell the server to flush the vt100 Escape.) self._send_packet({"cmd": "flush-input"}) current_timeout = None
def attach(self, detach_other_clients=False, ansi_colors_only=False, true_color=False): """ Attach client user interface. """ assert isinstance(detach_other_clients, bool) assert isinstance(ansi_colors_only, bool) assert isinstance(true_color, bool) self._send_size() self._send_packet({ 'cmd': 'start-gui', 'detach-others': detach_other_clients, 'ansi-colors-only': ansi_colors_only, 'true-color': true_color, 'term': os.environ.get('TERM', ''), 'data': '' }) with raw_mode(sys.stdin.fileno()): data_buffer = b'' stdin_fd = sys.stdin.fileno() socket_fd = self.socket.fileno() current_timeout = INPUT_TIMEOUT # Timeout, used to flush escape sequences. with call_on_sigwinch(self._send_size): while True: r = select_fds([stdin_fd, socket_fd], current_timeout) if socket_fd in r: # Received packet from server. data = self.socket.recv(1024) if data == b'': # End of file. Connection closed. # Reset terminal o = Vt100_Output.from_pty(sys.stdout) o.quit_alternate_screen() o.disable_mouse_support() o.disable_bracketed_paste() o.reset_attributes() o.flush() return else: data_buffer += data while b'\0' in data_buffer: pos = data_buffer.index(b'\0') self._process(data_buffer[:pos]) data_buffer = data_buffer[pos + 1:] elif stdin_fd in r: # Got user input. self._process_stdin() current_timeout = INPUT_TIMEOUT else: # Timeout. (Tell the server to flush the vt100 Escape.) self._send_packet({'cmd': 'flush-input'}) current_timeout = None
def attach(self, detach_other_clients=False, true_color=False): """ Attach client user interface. """ assert isinstance(detach_other_clients, bool) assert isinstance(true_color, bool) self._send_size() self._send_packet({ 'cmd': 'start-gui', 'detach-others': detach_other_clients, 'true-color': true_color, 'term': os.environ.get('TERM', ''), 'data': '' }) with raw_mode(sys.stdin.fileno()): data_buffer = b'' stdin_fd = sys.stdin.fileno() socket_fd = self.socket.fileno() current_timeout = INPUT_TIMEOUT # Timeout, used to flush escape sequences. with call_on_sigwinch(self._send_size): while True: r, w, x = _select([stdin_fd, socket_fd], [], [], current_timeout) if socket_fd in r: # Received packet from server. data = self.socket.recv(1024) if data == b'': # End of file. Connection closed. # Reset terminal o = Vt100_Output.from_pty(sys.stdout) o.quit_alternate_screen() o.disable_mouse_support() o.disable_bracketed_paste() o.reset_attributes() o.flush() return else: data_buffer += data while b'\0' in data_buffer: pos = data_buffer.index(b'\0') self._process(data_buffer[:pos]) data_buffer = data_buffer[pos + 1:] elif stdin_fd in r: # Got user input. self._process_stdin() current_timeout = INPUT_TIMEOUT else: # Timeout. (Tell the server to flush the vt100 Escape.) self._send_packet({'cmd': 'flush-input'}) current_timeout = None
def _create_cli(self, true_color=False): """ Create CommandLineInterface for this client. Called when the client wants to attach the UI to the server. """ output = Vt100_Output(_SocketStdout(self._send_packet), lambda: self.size, true_color=true_color) input = _ClientInput(self._send_packet) self.cli = self.pymux.create_cli(self, output, input)
def run_standalone(self, true_color=False): """ Run pymux standalone, rather than using a client/server architecture. This is mainly useful for debugging. """ self._runs_standalone = True cli = self.create_cli(connection=None, output=Vt100_Output.from_pty( sys.stdout, true_color=true_color)) cli._is_running = False cli.run()
def run_standalone(self, true_color=False): """ Run pymux standalone, rather than using a client/server architecture. This is mainly useful for debugging. """ self._runs_standalone = True cli = self.create_cli( connection=None, output=Vt100_Output.from_pty(sys.stdout, true_color=true_color)) cli._is_running = False cli.run()
def __init__(self, get_globals, get_locals=None): assert callable(get_globals) assert get_locals is None or callable(get_locals) self._chan = None def _globals(): data = get_globals() data.setdefault('print', self._print) return data repl = PythonRepl(get_globals=_globals, get_locals=get_locals or _globals) # Disable open-in-editor and system prompt. Because it would run and # display these commands on the server side, rather than in the SSH # client. repl.enable_open_in_editor = False repl.enable_system_bindings = False # PipInput object, for sending input in the CLI. # (This is something that we can use in the prompt_toolkit event loop, # but still write date in manually.) self._input_pipe = PipeInput() # Output object. Don't render to the real stdout, but write everything # in the SSH channel. class Stdout(object): def write(s, data): if self._chan is not None: self._chan.write(data.replace('\n', '\r\n')) def flush(s): pass # Create command line interface. self.cli = CommandLineInterface(application=repl.create_application(), eventloop=create_asyncio_eventloop(), input=self._input_pipe, output=Vt100_Output( Stdout(), self._get_size)) self._callbacks = self.cli.create_eventloop_callbacks()
def __init__(self, conn, addr, application, server, encoding): assert isinstance(addr, tuple) # (addr, port) tuple assert isinstance(application, TelnetApplication) assert isinstance(server, TelnetServer) assert isinstance(encoding, text_type) # e.g. 'utf-8' self.conn = conn self.addr = addr self.application = application self.closed = False self.handling_command = True self.server = server self.encoding = encoding self.callback = None # Function that handles the CLI result. # Create "Output" object. self.size = Size(rows=40, columns=79) # Initialize. _initialize_telnet(conn) # Create output. def get_size(): return self.size self.stdout = _ConnectionStdout(conn, encoding=encoding) self.vt100_output = Vt100_Output(self.stdout, get_size, write_binary=False) # Create an eventloop (adaptor) for the CommandLineInterface. self.eventloop = _TelnetEventLoopInterface(server) # Set default CommandLineInterface. self.set_application(create_prompt_application()) # Call client_connected application.client_connected(self) # Draw for the first time. self.handling_command = False self.cli._redraw()