# Path: src/rosrepo/util.py
# def isatty(fd):
#     return hasattr(fd, "isatty") and fd.isatty()
# 
# def get_terminal_size():
#     global _cached_terminal_size
#     if _cached_terminal_size is not None:
#         return _cached_terminal_size
#     try:
#         with open(os.ctermid(), "rb") as f:
#             cr = struct.unpack('hh', fcntl.ioctl(f.fileno(), termios.TIOCGWINSZ, '1234'))
#     except (IOError, struct.error):
#         raise OSError("Cannot determine terminal size")
#     _cached_terminal_size = int(cr[1]), int(cr[0])
#     return _cached_terminal_size
# 
# class UserError(RuntimeError):
#     pass
# 
# Path: src/rosrepo/terminal_color.py
# def fmt(msg, use_color=True, reset=True):
#     """Replaces color annotations with ansi escape sequences"""
#     global _ansi
#     msg = msg.replace('@!', '@{boldon}')
#     msg = msg.replace('@/', '@{italicson}')
#     msg = msg.replace('@_', '@{ulon}')
#     msg = msg.replace('@|', '@{reset}')
#     t = ColorTemplate(msg)
#     return t.safe_substitute(_ansi if use_color else _no_ansi) + (ansi('reset') if reset and use_color else '')


import sys
import re
from getpass import getpass
    from itertools import izip_longest as zip_longest
    from itertools import zip_longest
from .util import isatty, get_terminal_size, UserError
from .terminal_color import fmt as color_fmt
    from .terminal_color import ansi
        from .resolver import get_system_package_manager
class TableView(object):
    def __init__(self, *args, **kwargs):
        self.columns = args
        self.expand = kwargs.get("expand", False)
        if not self.columns:
            self.width = [1, 1]
        else:
            self.width = [max(1, len(remove_ansi(color_fmt(c)))) for c in self.columns]
        self.rows = []

    def add_row(self, *args):
        row = [r if isinstance(r, list) or isinstance(r, tuple) else (r,) for r in args]
        row = [r if isinstance(r, tuple) or len(r) > 0 else [""] for r in row]  # Handle special case with empty lists
        assert len(row) == len(self.width)
        self.rows.append(row)
        self.width = [max(w, *(len(remove_ansi(color_fmt(r))) for r in rs)) for w, rs in zip(self.width, row)]

    def add_separator(self):
        self.rows.append(None)

    def empty(self):
        return len(self.rows) == 0

    def sort(self, column_index):
        self.rows.sort(key=lambda x: x[column_index])

    def write(self, fd=None, use_color=None):
        width = self.width
        actual_width = sum(width) + 3 * len(width) - 1
        try:

# Path: src/rosrepo/util.py
# def isatty(fd):
#     return hasattr(fd, "isatty") and fd.isatty()
# 
# def get_terminal_size():
#     global _cached_terminal_size
#     if _cached_terminal_size is not None:
#         return _cached_terminal_size
#     try:
#         with open(os.ctermid(), "rb") as f:
#             cr = struct.unpack('hh', fcntl.ioctl(f.fileno(), termios.TIOCGWINSZ, '1234'))
#     except (IOError, struct.error):
#         raise OSError("Cannot determine terminal size")
#     _cached_terminal_size = int(cr[1]), int(cr[0])
#     return _cached_terminal_size
# 
# class UserError(RuntimeError):
#     pass
# 
# Path: src/rosrepo/terminal_color.py
# def fmt(msg, use_color=True, reset=True):
#     """Replaces color annotations with ansi escape sequences"""
#     global _ansi
#     msg = msg.replace('@!', '@{boldon}')
#     msg = msg.replace('@/', '@{italicson}')
#     msg = msg.replace('@_', '@{ulon}')
#     msg = msg.replace('@|', '@{reset}')
#     t = ColorTemplate(msg)
#     return t.safe_substitute(_ansi if use_color else _no_ansi) + (ansi('reset') if reset and use_color else '')


# Path: src/rosrepo/ui.py
import sys
import re
from getpass import getpass
    from itertools import izip_longest as zip_longest
    from itertools import zip_longest
from .util import isatty, get_terminal_size, UserError
from .terminal_color import fmt as color_fmt
    from .terminal_color import ansi
        from .resolver import get_system_package_manager

class TableView(object):
    def __init__(self, *args, **kwargs):
        self.columns = args
        self.expand = kwargs.get("expand", False)
        if not self.columns:
            self.width = [1, 1]
        else:
            self.width = [max(1, len(remove_ansi(color_fmt(c)))) for c in self.columns]
        self.rows = []

    def add_row(self, *args):
        row = [r if isinstance(r, list) or isinstance(r, tuple) else (r,) for r in args]
        row = [r if isinstance(r, tuple) or len(r) > 0 else [""] for r in row]  # Handle special case with empty lists
        assert len(row) == len(self.width)
        self.rows.append(row)
        self.width = [max(w, *(len(remove_ansi(color_fmt(r))) for r in rs)) for w, rs in zip(self.width, row)]

    def add_separator(self):
        self.rows.append(None)

    def empty(self):
        return len(self.rows) == 0

    def sort(self, column_index):
        self.rows.sort(key=lambda x: x[column_index])

    def write(self, fd=None, use_color=None):
        width = self.width
        actual_width = sum(width) + 3 * len(width) - 1
        try:

            total_width = get_terminal_size()[0]