Beispiel #1
0
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()
Beispiel #2
0
def main():
    def done():
        application.exit()

    application = Application(
        layout=Layout(container=Terminal(done_callback=done)),
        full_screen=True,
    )
    application.run()
Beispiel #3
0
    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)
Beispiel #4
0
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()
Beispiel #5
0
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()
Beispiel #6
0
    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
Beispiel #7
0
    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
Beispiel #8
0
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)