def main(): style = Style([ ('terminal not-focused', '#888888'), ('title', 'bg:#000044 #ffffff underline'), ]) done_count = [0] # nonlocal. def done(): done_count[0] += 1 if done_count[0] == 2: application.exit() else: switch_focus() term1 = Terminal(width=D(preferred=80), height=D(preferred=40), style='class:terminal', done_callback=done) term2 = Terminal(width=D(preferred=80), height=D(preferred=40), style='class:terminal', done_callback=done) kb = KeyBindings() @kb.add('c-w') def _(event): switch_focus() def switch_focus(): " Change focus when Control-W is pressed." if application.layout.has_focus(term1): application.layout.focus(term2) else: application.layout.focus(term1) application = Application( layout=Layout(container=HSplit([ Window( height=1, style='class:title', content=FormattedTextControl( HTML( ' Press <u fg="#ff8888"><b>Control-W</b></u> to <b>switch focus</b>.' ))), VSplit([ term1, Window(style='bg:#aaaaff', width=1), term2, ]), ]), focused_element=term1), style=style, key_bindings=kb, full_screen=True, mouse_support=True, ) application.run()
def main(): def done(): application.exit() application = Application( layout=Layout(container=Terminal(done_callback=done)), full_screen=True, ) application.run()
def __init__(self, app, height=Dimension(preferred=20), width=Dimension(preferred=20), callback=None): self.app = app gdb = self._get_gdb_path() self._create_pipes() self._update_pythonpath() gdbw_dir = self._get_gdbw_dir() source_cmd = 'source %s/gdbwhelper.py' % (gdbw_dir) gdb_run_cmd = [gdb, '-iex', source_cmd] + argv[1:] self.console = Terminal(gdb_run_cmd, done_callback=self._done, height=height, width=width) self.info = InfoLine(text='', width=240) self.window = HSplit([self.info.get_ui(), self.console]) self.update_info() self.in_pipe.begin_reading(callback)
def main(): style = Style([ ('terminal focused', 'bg:#aaaaaa'), ('title', 'bg:#000044 #ffffff underline'), ]) term1 = Terminal() text_area = TextArea(text='Press Control-W to switch focus.\n' 'Then you can edit this text area.\n' 'Press Control-X to exit') kb = KeyBindings() @kb.add('c-w') def _(event): switch_focus() @kb.add('c-x', eager=True) def _(event): event.app.exit() def switch_focus(): " Change focus when Control-W is pressed." if application.layout.has_focus(term1): application.layout.focus(text_area) else: application.layout.focus(term1) application = Application( layout=Layout(container=HSplit([ Window(height=1, style='class:title', content=FormattedTextControl( ' Press Control-W to switch focus.')), VSplit([ term1, Window(style='bg:#aaaaff', width=1), text_area, ]), ]), focused_element=term1), style=style, key_bindings=merge_key_bindings([ load_key_bindings(), kb, ]), full_screen=True, mouse_support=True, ) application.run()
def main(): def done(): application.exit() term = Terminal( width=D(preferred=60), height=D(preferred=25), done_callback=done) application = Application( layout=Layout( container=Dialog( title='Terminal demo', body=term, with_background=True ), focused_element=term ), full_screen=True, mouse_support=True, ) application.run()
def _create_pane(self, window=None, command=None, start_directory=None): """ Create a new :class:`pymux.arrangement.Pane` instance. (Don't put it in a window yet.) :param window: If a window is given, take the CWD of the current process of that window as the start path for this pane. :param command: If given, run this command instead of `self.default_shell`. :param start_directory: If given, use this as the CWD. """ assert window is None or isinstance(window, Window) assert command is None or isinstance(command, six.text_type) assert start_directory is None or isinstance(start_directory, six.text_type) def done_callback(): " When the process finishes. " if not self.remain_on_exit: # Remove pane from layout. self.arrangement.remove_pane(pane) # No panes left? -> Quit. if not self.arrangement.has_panes: self.stop() # Make sure the right pane is focused for each client. for client_state in self._client_states.values(): client_state.sync_focus() self.invalidate() def bell(): " Sound bell on all clients. " if self.enable_bell: for c in self.apps: c.output.bell() # Start directory. if start_directory: path = start_directory elif window and window.active_process: # When the path of the active process is known, # start the new process at the same location. path = window.active_process.get_cwd() else: path = None def before_exec(): " Called in the process fork (in the child process). " # Go to this directory. try: os.chdir(path or self.original_cwd) except OSError: pass # No such file or directory. # Set terminal variable. (We emulate xterm.) os.environ['TERM'] = self.default_terminal # Make sure to set the PYMUX environment variable. if self.socket_name: os.environ['PYMUX'] = '%s,%i' % (self.socket_name, pane.pane_id) if command: command = command.split() else: command = [self.default_shell] # Create new pane and terminal. terminal = Terminal(done_callback=done_callback, bell_func=bell, before_exec_func=before_exec) pane = Pane(terminal) # Keep track of panes. This is a WeakKeyDictionary, we only add, but # don't remove. self.panes_by_id[pane.pane_id] = pane logger.info('Created process %r.', command) return pane
def __init__(self, loop: AbstractEventLoop, command_handler: CommandRoot = None): self.LOOP: AbstractEventLoop = loop self.TASKS: List[Task] = [] self.first = True self.kb = keys(self) # noinspection PyTypeChecker mode = cycle(Mode) self.state: Mode = next(mode) self._style: Alert = Alert.NORM @self.kb.add("s-tab") def nextmode(*_) -> None: self.state = next(mode) @self.kb.add("pageup") def hist_first(*_) -> None: self.command_buffer.go_to_history(0) @self.kb.add("pagedown") def hist_last(*_) -> None: self.command_buffer.go_to_history( len(self.command_buffer.history.get_strings()) ) @self.kb.add("c-c") def interrupt(*_): """Ctrl-C: Interrupt running Job.""" self.print("^C") if self.current_job and not self.current_job.done(): self.current_job.cancel() self.current_job = None # Create a Prompt Object with initial values. self.prompt = Prompt( cfg["interface/initial/user", "nobody"], cfg["interface/initial/host", "local"], cfg["interface/initial/wdir", "~"], ) # Build the UI. self.header_bar = FormattedTextControl( lambda: FormattedText( [ ( "", f"{self.console_header():^{int(T.width / 2)}}│<⇧TAB> / ", ), *( ("reverse" if self.state is m else "", f" {m.value} ") for m in Mode ), ] ) ) # self.header_bar = FormattedTextControl( # lambda: "{left:{pad}^{half}}│{right:{pad}^{half}}".format( # left=self.console_header(), # right=f"Panel Display: {self.state.value} [Shift-Tab]", # half=int(T.width / 2), # pad="", # ) # ) self.command_buffer = Buffer( accept_handler=self.enter, complete_while_typing=True, completer=command_handler, multiline=False, on_text_changed=command_handler.change, read_only=Condition(self.busy), ) self.terminal = Terminal(sim_prompt=True) self.console_backend = self.terminal.terminal_control.process.terminal self.console_header = lambda: "" self.floating_elems = [] self.procs: List[Processor] = [ self.prompt.processor, HighlightMatchingBracketProcessor(), ] self.scope_topdown = FormattedTextControl(text="TopDown") self.scope_horizon = FormattedTextControl(text="Horizon") self.scans = TelemetryDisplay() self.orders = OrdersDisplay() # Register the Command Handler. self.handler = command_handler self.current_job: Optional[Task] = None self._app: Optional[Application] = None
class ConsoleWindow: def __init__(self, app, height=Dimension(preferred=20), width=Dimension(preferred=20), callback=None): self.app = app gdb = self._get_gdb_path() self._create_pipes() self._update_pythonpath() gdbw_dir = self._get_gdbw_dir() source_cmd = 'source %s/gdbwhelper.py' % (gdbw_dir) gdb_run_cmd = [gdb, '-iex', source_cmd] + argv[1:] self.console = Terminal(gdb_run_cmd, done_callback=self._done, height=height, width=width) self.info = InfoLine(text='', width=240) self.window = HSplit([self.info.get_ui(), self.console]) self.update_info() self.in_pipe.begin_reading(callback) def get_ui(self): return self.window def enter_copy_mode(self): self.console.enter_copy_mode() def exit_copy_mode(self): self.console.exit_copy_mode() def log(self, msg): if self.gdbw_log_pipe: self.gdbw_log_pipe.write(str(msg) + '\n') def _get_gdbw_dir(self): return dirname(abspath(__file__)) def _get_gdb_path(self): gdbscript_path = self._get_gdbw_dir() + '/gdb' gdb_paths = check_output(['which', '-a', 'gdb']) gdb_paths = gdb_paths.decode('utf-8').strip().split('\n') for g in gdb_paths: g = check_output(['readlink', '-f', g]).decode('utf-8').strip() if g != gdbscript_path: return g print('Could not find gdb. Aborting.') exit(1) def _done(self): self.in_pipe.close() self.out_pipe.close() if self.log_pipe: self.log_pipe.close() if self.gdbw_log_pipe: self.gdbw_log_pipe.close() get_app().exit() def _create_pipes(self): pid = getpid() self.out_pipe = NamedPipe('/tmp/gdbh_in_pipe_%d' % (pid)) self.in_pipe = NamedPipe('/tmp/gdbh_out_pipe_%d' % (pid)) pipes_str = '%s\n%s' % (self.out_pipe.path, self.in_pipe.path) # Create logging pipes self.gdbw_log_pipe = None self.log_pipe = None try: if int(environ['GDBW_ENABLE_LOGGING']): self.gdbw_log_pipe = NamedPipe('/tmp/gdbw_log_%d' % (pid)) self.log_pipe = NamedPipe('/tmp/gdbh_log_%d' % (pid)) pipes_str += '\n' + self.log_pipe.path except: pass environ['GDBW_PIPES'] = pipes_str def _update_pythonpath(self): pp = 'PYTHONPATH' ppv = environ[pp] if pp in environ else '' gdbw_dir = self._get_gdbw_dir() environ[pp] = '%s:%s' % (ppv, gdbw_dir) def update_info(self): self.info.set_info('[ gdbw console / style:%s ]' % self.app.style_name)