working product
This commit is contained in:
parent
1ee311e561
commit
903fe0392c
1 changed files with 163 additions and 117 deletions
280
checkpkg.py
280
checkpkg.py
|
@ -94,147 +94,193 @@ def fetch_package_data(package):
|
|||
return None
|
||||
|
||||
def print_table(output, headers, selected_pms, args):
|
||||
"""Print formatted table with consistent alignment"""
|
||||
"""Print formatted table with consistent alignment or list for small terminals"""
|
||||
# Terminal dimensions
|
||||
terminal_width = shutil.get_terminal_size().columns
|
||||
min_col_width = 10
|
||||
padding = 1 # Space on each side of the column content
|
||||
|
||||
# Calculate initial column widths based on content
|
||||
pkg_col_width = max(
|
||||
len(headers[0]),
|
||||
max(len(pkg) for pkg in args.packages) if args.packages else min_col_width
|
||||
) + (padding * 2)
|
||||
# Calculate package availability for coloring
|
||||
pkg_availability = {}
|
||||
for pkg in args.packages:
|
||||
versions = output.get(pkg, {})
|
||||
available_count = sum(1 for pm in selected_pms if versions.get(pm, 'Not found') != 'Not found')
|
||||
|
||||
if available_count == 0:
|
||||
pkg_availability[pkg] = 'red' # Not available anywhere
|
||||
elif available_count == len(selected_pms):
|
||||
pkg_availability[pkg] = 'green' # Available everywhere
|
||||
else:
|
||||
pkg_availability[pkg] = 'yellow' # Available in some places
|
||||
|
||||
# Allocate remaining space proportionally to other columns
|
||||
remaining_width = terminal_width - pkg_col_width - (3 * len(selected_pms)) # 3 chars for " | "
|
||||
version_col_width = max(min_col_width, remaining_width // len(selected_pms))
|
||||
# Determine minimum required widths
|
||||
min_pkg_width = max(len(pkg) for pkg in args.packages) + 2
|
||||
min_pm_width = 10
|
||||
min_required_width = min_pkg_width + (min_pm_width * len(selected_pms)) + (3 * len(selected_pms))
|
||||
|
||||
# Define column widths
|
||||
col_widths = [pkg_col_width] + [version_col_width] * len(selected_pms)
|
||||
# If terminal is too narrow for the table, use list format instead
|
||||
if terminal_width < min_required_width and len(selected_pms) > 1:
|
||||
print_list_format(output, headers, selected_pms, args, pkg_availability)
|
||||
return
|
||||
|
||||
# Adjust to fit terminal if needed
|
||||
while sum(col_widths) + (3 * (len(col_widths) - 1)) > terminal_width and min(col_widths) > min_col_width:
|
||||
max_idx = col_widths.index(max(col_widths))
|
||||
col_widths[max_idx] -= 1
|
||||
# Calculate column widths
|
||||
padding = 1 # Space on each side of content
|
||||
|
||||
# Calculate total table width for separators
|
||||
# Package column width
|
||||
pkg_col_width = min(min_pkg_width + 4, max(min_pkg_width, terminal_width // (len(selected_pms) + 3)))
|
||||
|
||||
# PM column widths (divide remaining space equally)
|
||||
remaining_width = terminal_width - pkg_col_width - (3 * len(selected_pms))
|
||||
pm_col_width = max(min_pm_width, remaining_width // len(selected_pms))
|
||||
|
||||
col_widths = [pkg_col_width] + [pm_col_width] * len(selected_pms)
|
||||
|
||||
# Print header row
|
||||
header_cells = []
|
||||
for i, header in enumerate(headers):
|
||||
text = header.center(col_widths[i] - (2 * padding))
|
||||
cell = " " * padding + colorize(text, 'header') + " " * padding
|
||||
header_cells.append(cell)
|
||||
|
||||
print(" | ".join(header_cells))
|
||||
|
||||
# Print separator line
|
||||
total_width = sum(col_widths) + (3 * (len(col_widths) - 1))
|
||||
|
||||
# Print headers (centered)
|
||||
header_row = []
|
||||
for idx, header in enumerate(headers):
|
||||
header_text = header.center(col_widths[idx] - (padding * 2))
|
||||
padded_header = " " * padding + colorize(header_text, 'header') + " " * padding
|
||||
header_row.append(padded_header.ljust(col_widths[idx]))
|
||||
|
||||
print(" | ".join(header_row))
|
||||
|
||||
# Print main separator line
|
||||
print("-" * total_width)
|
||||
|
||||
# Process and print each package row
|
||||
for pkg_index, pkg in enumerate(args.packages):
|
||||
versions = output.get(pkg, {pm: 'Not found' for pm in selected_pms})
|
||||
# Print each package row
|
||||
for pkg_idx, pkg in enumerate(args.packages):
|
||||
versions = output.get(pkg, {})
|
||||
|
||||
# Prepare content for each cell
|
||||
cells_content = []
|
||||
# First collect all data for this package
|
||||
package_data = []
|
||||
|
||||
# Package name (first column)
|
||||
cells_content.append(colorize(pkg, 'bold'))
|
||||
package_data.append([colorize(pkg, pkg_availability[pkg])])
|
||||
|
||||
# Version information (remaining columns)
|
||||
# Version data for each package manager
|
||||
for pm in selected_pms:
|
||||
version = versions.get(pm, 'Not found')
|
||||
color = 'green' if version != 'Not found' else 'red'
|
||||
if 'AUR' in version: color = 'yellow'
|
||||
# Apply color to the entire string at once
|
||||
cells_content.append(colorize(version, color))
|
||||
|
||||
# Apply wrapping to each cell based on column width
|
||||
wrapped_cells = []
|
||||
for idx, content in enumerate(cells_content):
|
||||
# Use raw text for wrapping calculation, but keep the colored text for display
|
||||
raw_text = content
|
||||
if colorize.is_tty:
|
||||
# Remove ANSI color codes for length calculation
|
||||
raw_text = re.sub(r'\033\[\d+m', '', content)
|
||||
|
||||
avail_width = col_widths[idx] - (padding * 2)
|
||||
if version == 'Not found':
|
||||
package_data.append([colorize('-', 'red')])
|
||||
continue
|
||||
|
||||
# Wrap text without color codes
|
||||
wrapped_lines = textwrap.wrap(
|
||||
raw_text,
|
||||
width=avail_width,
|
||||
break_long_words=False,
|
||||
break_on_hyphens=True
|
||||
) or ['']
|
||||
# Extract version number and repositories
|
||||
version_parts = []
|
||||
match = re.match(r'(.*?)\s+\((.*)\)$', version)
|
||||
|
||||
# If we have color codes, we need to re-apply coloring to each wrapped line
|
||||
if colorize.is_tty:
|
||||
color = None
|
||||
if idx == 0: # Package name
|
||||
color = 'bold'
|
||||
else: # Version info
|
||||
if 'Not found' in raw_text:
|
||||
color = 'red'
|
||||
elif 'AUR' in raw_text:
|
||||
color = 'yellow'
|
||||
else:
|
||||
color = 'green'
|
||||
if match:
|
||||
ver_num, repos = match.groups()
|
||||
version_parts.append(colorize(ver_num, 'green'))
|
||||
|
||||
# Apply the same color to each wrapped line
|
||||
wrapped_lines = [colorize(line, color) for line in wrapped_lines]
|
||||
|
||||
wrapped_cells.append(wrapped_lines)
|
||||
|
||||
# Determine how many lines this row needs
|
||||
max_lines = max(len(cell) for cell in wrapped_cells)
|
||||
|
||||
# Print each line of the row
|
||||
for line_idx in range(max_lines):
|
||||
row_parts = []
|
||||
for col_idx, cell_lines in enumerate(wrapped_cells):
|
||||
if line_idx < len(cell_lines):
|
||||
content = cell_lines[line_idx]
|
||||
if line_idx > 0: # For continuation lines
|
||||
# Indent continuation lines for better readability
|
||||
# We can't simply add characters to colored text, need to handle differently
|
||||
if colorize.is_tty:
|
||||
# Need to extract the color codes and apply them after indent
|
||||
plain_content = re.sub(r'\033\[\d+m', '', content)
|
||||
color_prefix = content[:content.find(plain_content)]
|
||||
color_suffix = COLORS['reset']
|
||||
content = color_prefix + " " + plain_content + color_suffix
|
||||
else:
|
||||
content = " " + content
|
||||
|
||||
# Calculate proper padding with color codes
|
||||
if colorize.is_tty:
|
||||
plain_content = re.sub(r'\033\[\d+m', '', content)
|
||||
color_parts = content.split(plain_content)
|
||||
padded = " " * padding + content + " " * padding
|
||||
|
||||
# For colored text, we need to calculate padding differently
|
||||
plain_padded = " " * padding + plain_content + " " * padding
|
||||
padding_needed = col_widths[col_idx] - len(plain_padded)
|
||||
if padding_needed > 0:
|
||||
padded += " " * padding_needed
|
||||
else:
|
||||
padded = (" " * padding + content + " " * padding).ljust(col_widths[col_idx])
|
||||
|
||||
row_parts.append(padded)
|
||||
# Format repositories
|
||||
repo_lines = []
|
||||
repo_text = "(" + repos + ")"
|
||||
|
||||
# Wrap repository text if needed
|
||||
avail_width = col_widths[len(package_data)] - (2 * padding)
|
||||
if len(repo_text) <= avail_width:
|
||||
repo_lines.append(colorize(repo_text, 'green'))
|
||||
else:
|
||||
# Empty space for this cell in this line
|
||||
row_parts.append(" " * col_widths[col_idx])
|
||||
|
||||
print(" | ".join(row_parts))
|
||||
# Handle wrapping for repositories
|
||||
repo_parts = repos.split(', ')
|
||||
current_line = "("
|
||||
|
||||
for repo in repo_parts:
|
||||
if len(current_line) + len(repo) + 2 <= avail_width:
|
||||
if current_line != "(":
|
||||
current_line += ", "
|
||||
current_line += repo
|
||||
else:
|
||||
if current_line != "(":
|
||||
current_line += ")"
|
||||
repo_lines.append(colorize(current_line, 'green'))
|
||||
current_line = " " + repo
|
||||
|
||||
if current_line != "(":
|
||||
current_line += ")" if not current_line.startswith(" ") else ""
|
||||
repo_lines.append(colorize(current_line, 'green'))
|
||||
|
||||
# Combined version and repo lines
|
||||
package_data.append([version_parts[0]] + repo_lines)
|
||||
else:
|
||||
# Simple version string
|
||||
package_data.append([colorize(version, 'green')])
|
||||
|
||||
# Add a separator between packages (but not after the last one)
|
||||
if pkg_index < len(args.packages) - 1:
|
||||
# Use a lighter separator for between packages
|
||||
# Determine max number of lines needed
|
||||
max_lines = max(len(column) for column in package_data)
|
||||
|
||||
# Print all lines for this package
|
||||
for line_idx in range(max_lines):
|
||||
row_cells = []
|
||||
|
||||
for col_idx, col_data in enumerate(package_data):
|
||||
if line_idx < len(col_data):
|
||||
# Actual content
|
||||
content = col_data[line_idx]
|
||||
content_plain = re.sub(r'\033\[\d+m', '', content)
|
||||
|
||||
# Calculate padding
|
||||
left_pad = padding
|
||||
right_pad = max(0, col_widths[col_idx] - len(content_plain) - left_pad)
|
||||
|
||||
cell = " " * left_pad + content + " " * right_pad
|
||||
else:
|
||||
# Empty cell
|
||||
cell = " " * col_widths[col_idx]
|
||||
|
||||
row_cells.append(cell)
|
||||
|
||||
print(" | ".join(row_cells))
|
||||
|
||||
# Add separator between packages
|
||||
if pkg_idx < len(args.packages) - 1:
|
||||
print("·" * total_width)
|
||||
|
||||
def print_list_format(output, headers, selected_pms, args, pkg_availability):
|
||||
"""Print packages in a vertical list format for narrow terminals"""
|
||||
terminal_width = shutil.get_terminal_size().columns
|
||||
|
||||
for pkg_idx, pkg in enumerate(args.packages):
|
||||
pkg_color = pkg_availability[pkg]
|
||||
versions = output.get(pkg, {})
|
||||
|
||||
# Print package header with color based on availability
|
||||
print(f"\n{colorize('Package:', 'bold')} {colorize(pkg, pkg_color)}")
|
||||
print("-" * min(40, terminal_width - 2))
|
||||
|
||||
# Print versions for each package manager
|
||||
for pm in selected_pms:
|
||||
pm_name = headers[selected_pms.index(pm) + 1] # Get friendly display name
|
||||
version = versions.get(pm, 'Not found')
|
||||
|
||||
if version == 'Not found':
|
||||
print(f"{colorize(pm_name, 'header')}: {colorize('-', 'red')}")
|
||||
else:
|
||||
# Extract version and repo information
|
||||
match = re.match(r'(.*?)\s+\((.*)\)$', version)
|
||||
if match:
|
||||
ver_num, repos = match.groups()
|
||||
|
||||
# Handle long repository lists with wrapping
|
||||
if len(pm_name) + len(ver_num) + len(repos) + 5 > terminal_width:
|
||||
print(f"{colorize(pm_name, 'header')}: {colorize(ver_num, 'green')}")
|
||||
# Wrap repositories with proper indentation
|
||||
wrapper = textwrap.TextWrapper(
|
||||
width=terminal_width - 4,
|
||||
initial_indent=" ",
|
||||
subsequent_indent=" "
|
||||
)
|
||||
wrapped = wrapper.fill(f"({repos})")
|
||||
print(colorize(wrapped, 'green'))
|
||||
else:
|
||||
print(f"{colorize(pm_name, 'header')}: {colorize(ver_num, 'green')} ({repos})")
|
||||
else:
|
||||
print(f"{colorize(pm_name, 'header')}: {colorize(version, 'green')}")
|
||||
|
||||
# Add separator between packages
|
||||
if pkg_idx < len(args.packages) - 1:
|
||||
print("\n" + "-" * min(40, terminal_width - 2))
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Package search tool')
|
||||
parser.add_argument('--all', action='store_true')
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue