Ejemplo n.º 1
0
 def __init__(self,
              argv,
              rows=25,
              columns=80,
              scrollback=100,
              cell_width=10,
              cell_height=20,
              cwd=None,
              env=None):
     if isinstance(argv, str):
         argv = shlex.split(argv)
     pid, self.master_fd = fork()
     self.is_child = pid == CHILD
     self.write_buf = b''
     if self.is_child:
         while read_screen_size().width != columns * cell_width:
             time.sleep(0.01)
         if cwd:
             os.chdir(cwd)
         os.execvpe(argv[0], argv, env or os.environ)
     os.set_blocking(self.master_fd, False)
     self.cell_width = cell_width
     self.cell_height = cell_height
     self.set_window_size(rows=rows, columns=columns)
     self.callbacks = Callbacks(self)
     self.screen = Screen(self.callbacks, rows, columns, scrollback,
                          cell_width, cell_height, 0, self.callbacks)
     self.received_bytes = b''
Ejemplo n.º 2
0
def _draw_right_status(screen: Screen, is_last: bool) -> int:
    if not is_last:
        return 0

    draw_attributed_string(Formatter.reset, screen)
    date = datetime.datetime.now().strftime(" %H:%M")
    utc_date = datetime.datetime.now(
        datetime.timezone.utc).strftime(" (UTC %H:%M)")

    right_status_length = calc_draw_spaces(date + " " + utc_date + " ")

    draw_spaces = screen.columns - screen.cursor.x - right_status_length
    if draw_spaces > 0:
        screen.draw(" " * draw_spaces)

    cells = [
        (Color(135, 192, 149), date),
        (Color(113, 115, 116), utc_date),
    ]

    screen.cursor.fg = 0
    for color, status in cells:
        screen.cursor.fg = as_rgb(color_as_int(color))
        screen.draw(status)
    screen.cursor.bg = 0

    if screen.columns - screen.cursor.x > right_status_length:
        screen.cursor.x = screen.columns - right_status_length

    return screen.cursor.x
Ejemplo n.º 3
0
def shape_string(
    text: str = "abcd", family: str = 'monospace', size: float = 11.0, dpi: float = 96.0, path: Optional[str] = None
) -> List[Tuple[int, int, int, Tuple[int, ...]]]:
    with setup_for_testing(family, size, dpi) as (sprites, cell_width, cell_height):
        s = Screen(None, 1, len(text)*2)
        line = s.line(0)
        s.draw(text)
        return test_shape(line, path)
Ejemplo n.º 4
0
def shape_string(text="abcd", family='monospace', size=11.0, dpi=96.0, path=None):
    try:
        sprites, cell_width, cell_height = setup_for_testing(family, size, dpi)
        s = Screen(None, 1, len(text)*2)
        line = s.line(0)
        s.draw(text)
        return test_shape(line, path)
    finally:
        set_send_sprite_to_gpu(None)
Ejemplo n.º 5
0
def _draw_left_icon(screen: Screen, draw_data: DrawData) -> int:
    orig_fg, orig_bg = screen.cursor.fg, screen.cursor.bg

    screen.cursor.fg = orig_bg
    screen.cursor.bg = draw_data.default_bg
    screen.draw('')
    screen.cursor.fg, screen.cursor.bg = orig_fg, orig_bg

    screen.cursor.x = 1
    return screen.cursor.x
Ejemplo n.º 6
0
def _draw_icon(screen: Screen, index: int, symbol: str = "") -> int:
    if index != 1:
        return 0

    fg, bg = screen.cursor.fg, screen.cursor.bg
    screen.cursor.fg = as_rgb(color_as_int(Color(255, 250, 205)))
    screen.cursor.bg = as_rgb(color_as_int(Color(60, 71, 77)))
    screen.draw(symbol)
    screen.cursor.fg, screen.cursor.bg = fg, bg
    screen.cursor.x = len(symbol)
    return screen.cursor.x
Ejemplo n.º 7
0
def shape_string(text="abcd",
                 family='monospace',
                 size=11.0,
                 dpi=96.0,
                 path=None):
    with setup_for_testing(family, size,
                           dpi) as (sprites, cell_width, cell_height):
        s = Screen(None, 1, len(text) * 2)
        line = s.line(0)
        s.draw(text)
        return test_shape(line, path)
Ejemplo n.º 8
0
def _draw_left_status(
    draw_data: DrawData,
    screen: Screen,
    tab: TabBarData,
    before: int,
    max_title_length: int,
    index: int,
    is_last: bool,
    extra_data: ExtraData,
) -> int:
    if draw_data.leading_spaces:
        screen.draw(" " * draw_data.leading_spaces)
    draw_title(draw_data, screen, tab, index)
    trailing_spaces = min(max_title_length - 1, draw_data.trailing_spaces)
    max_title_length -= trailing_spaces
    extra = screen.cursor.x - before - max_title_length
    if extra > 0:
        screen.cursor.x -= extra + 1
        screen.draw("…")
    if trailing_spaces:
        screen.draw(" " * trailing_spaces)
    end = screen.cursor.x
    screen.cursor.bold = screen.cursor.italic = False
    screen.cursor.fg = 0
    if not is_last:
        screen.cursor.bg = as_rgb(color_as_int(draw_data.inactive_bg))
        screen.draw(draw_data.sep)
    screen.cursor.bg = 0
    return end
Ejemplo n.º 9
0
def render_string(text: str, family: str = 'monospace', size: float = 11.0, dpi: float = 96.0) -> Tuple[int, int, List[bytes]]:
    with setup_for_testing(family, size, dpi) as (sprites, cell_width, cell_height):
        s = Screen(None, 1, len(text)*2)
        line = s.line(0)
        s.draw(text)
        test_render_line(line)
    cells = []
    found_content = False
    for i in reversed(range(s.columns)):
        sp = list(line.sprite_at(i))
        sp[2] &= 0xfff
        tsp = sp[0], sp[1], sp[2]
        if tsp == (0, 0, 0) and not found_content:
            continue
        found_content = True
        cells.append(sprites[tsp])
    return cell_width, cell_height, list(reversed(cells))
Ejemplo n.º 10
0
 def create_screen(self, cols=5, lines=5, scrollback=5, cell_width=10, cell_height=20, options=None):
     final_options = {'scrollback_pager_history_size': 1024, 'click_interval': 0.5}
     if options:
         final_options.update(options)
     options = Options(merge_configs(defaults._asdict(), final_options))
     set_options(options)
     c = Callbacks()
     return Screen(c, lines, cols, scrollback, cell_width, cell_height, 0, c)
Ejemplo n.º 11
0
def render_string(text, family='monospace', size=11.0, dpi=96.0):
    with setup_for_testing(family, size,
                           dpi) as (sprites, cell_width, cell_height):
        s = Screen(None, 1, len(text) * 2)
        line = s.line(0)
        s.draw(text)
        test_render_line(line)
    cells = []
    found_content = False
    for i in reversed(range(s.columns)):
        sp = list(line.sprite_at(i))
        sp[2] &= 0xfff
        sp = tuple(sp)
        if sp == (0, 0, 0) and not found_content:
            continue
        found_content = True
        cells.append(sprites[sp])
    return cell_width, cell_height, list(reversed(cells))
Ejemplo n.º 12
0
 def create_screen(self,
                   cols=5,
                   lines=5,
                   scrollback=5,
                   cell_width=10,
                   cell_height=20):
     c = Callbacks()
     return Screen(c, lines, cols, scrollback, cell_width, cell_height, 0,
                   c)
Ejemplo n.º 13
0
 def create_screen(self,
                   cols=5,
                   lines=5,
                   scrollback=5,
                   cell_width=10,
                   cell_height=20,
                   options=None):
     opts = self.set_options(options)
     c = Callbacks(opts)
     s = Screen(c, lines, cols, scrollback, cell_width, cell_height, 0, c)
     return s
Ejemplo n.º 14
0
 def create_screen(self,
                   cols=5,
                   lines=5,
                   scrollback=5,
                   cell_width=10,
                   cell_height=20,
                   options={}):
     options = Options(merge_configs(defaults._asdict(), options))
     set_options(options)
     c = Callbacks()
     return Screen(c, lines, cols, scrollback, cell_width, cell_height, 0,
                   c)
Ejemplo n.º 15
0
 def create_screen(self,
                   cols=5,
                   lines=5,
                   scrollback=5,
                   cell_width=10,
                   cell_height=20,
                   options=None):
     if options is None:
         options = {'scrollback_pager_history_size': 1024}
     options = Options(merge_configs(defaults._asdict(), options))
     set_options(options)
     c = Callbacks()
     return Screen(c, lines, cols, scrollback, cell_width, cell_height, 0,
                   c)
Ejemplo n.º 16
0
def _draw_left_status(
    draw_data: DrawData,
    screen: Screen,
    tab: TabBarData,
    before: int,
    max_title_length: int,
    index: int,
    is_last: bool,
    extra_data: ExtraData,
) -> int:
    print(extra_data)
    if draw_data.leading_spaces:
        screen.draw(" " * draw_data.leading_spaces)

    # TODO: https://github.com/kovidgoyal/kitty/discussions/4447#discussioncomment-2463083
    # tm = get_boss().active_tab_manager
    #     if tm is not None:
    #         w = tm.active_window
    #         if w is not None:
    #             cwd = w.cwd_of_child or ''
    #             log_error(cwd)

    draw_title(draw_data, screen, tab, index)
    trailing_spaces = min(max_title_length - 1, draw_data.trailing_spaces)
    max_title_length -= trailing_spaces
    extra = screen.cursor.x - before - max_title_length
    if extra > 0:
        screen.cursor.x -= extra + 1
        screen.draw("…")
    if trailing_spaces:
        screen.draw(" " * trailing_spaces)
    end = screen.cursor.x
    screen.cursor.bold = screen.cursor.italic = False
    screen.cursor.fg = 0
    if not is_last:
        screen.cursor.bg = as_rgb(color_as_int(draw_data.inactive_bg))
        screen.draw(draw_data.sep)
    screen.cursor.bg = 0
    return end
Ejemplo n.º 17
0
 def create_screen(self, cols=5, lines=5, scrollback=5):
     c = Callbacks()
     return Screen(c, lines, cols, scrollback, 0, c)
Ejemplo n.º 18
0
class PTY:
    def __init__(self,
                 argv,
                 rows=25,
                 columns=80,
                 scrollback=100,
                 cell_width=10,
                 cell_height=20,
                 cwd=None,
                 env=None):
        if isinstance(argv, str):
            argv = shlex.split(argv)
        pid, self.master_fd = fork()
        self.is_child = pid == CHILD
        self.write_buf = b''
        if self.is_child:
            while read_screen_size().width != columns * cell_width:
                time.sleep(0.01)
            if cwd:
                os.chdir(cwd)
            os.execvpe(argv[0], argv, env or os.environ)
        os.set_blocking(self.master_fd, False)
        self.cell_width = cell_width
        self.cell_height = cell_height
        self.set_window_size(rows=rows, columns=columns)
        self.callbacks = Callbacks(self)
        self.screen = Screen(self.callbacks, rows, columns, scrollback,
                             cell_width, cell_height, 0, self.callbacks)
        self.received_bytes = b''

    def turn_off_echo(self):
        s = termios.tcgetattr(self.master_fd)
        s[3] &= ~termios.ECHO
        termios.tcsetattr(self.master_fd, termios.TCSANOW, s)

    def is_echo_on(self):
        s = termios.tcgetattr(self.master_fd)
        return True if s[3] & termios.ECHO else False

    def __del__(self):
        if not self.is_child:
            fd = self.master_fd
            del self.master_fd
            os.close(fd)

    def write_to_child(self, data):
        if isinstance(data, str):
            data = data.encode('utf-8')
        self.write_buf += data

    def send_cmd_to_child(self, cmd):
        self.write_to_child(cmd + '\r')

    def process_input_from_child(self, timeout=10):
        rd, wd, err = select.select([self.master_fd],
                                    [self.master_fd] if self.write_buf else [],
                                    [self.master_fd], timeout)
        if err:
            raise OSError('master_fd is in error condition')
        while wd:
            try:
                n = os.write(self.master_fd, self.write_buf)
            except (BlockingIOError, OSError):
                n = 0
            if not n:
                break
            self.write_buf = self.write_buf[n:]

        bytes_read = 0
        while rd:
            try:
                data = os.read(self.master_fd, io.DEFAULT_BUFFER_SIZE)
            except (BlockingIOError, OSError):
                data = b''
            if not data:
                break
            bytes_read += len(data)
            self.received_bytes += data
            parse_bytes(self.screen, data)
        return bytes_read

    def wait_till(self, q, timeout=10):
        end_time = time.monotonic() + timeout
        while not q() and time.monotonic() <= end_time:
            self.process_input_from_child(
                timeout=max(0, end_time - time.monotonic()))
        if not q():
            raise TimeoutError(
                f'The condition was not met. Screen contents: \n {repr(self.screen_contents())}'
            )

    def set_window_size(self, rows=25, columns=80):
        if hasattr(self, 'screen'):
            self.screen.resize(rows, columns)
        x_pixels = columns * self.cell_width
        y_pixels = rows * self.cell_height
        s = struct.pack('HHHH', rows, columns, x_pixels, y_pixels)
        fcntl.ioctl(self.master_fd, termios.TIOCSWINSZ, s)

    def screen_contents(self):
        lines = []
        for i in range(self.screen.lines):
            x = str(self.screen.line(i))
            if x:
                lines.append(x)
        return '\n'.join(lines)

    def last_cmd_output(self, as_ansi=False, add_wrap_markers=False):
        from kitty.window import cmd_output
        return cmd_output(self.screen,
                          as_ansi=as_ansi,
                          add_wrap_markers=add_wrap_markers)
Ejemplo n.º 19
0
 def create_screen(self, cols=5, lines=5, scrollback=5):
     return Screen(Callbacks(), lines, cols, scrollback)