This commit is contained in:
nose
2025-12-16 01:45:01 -08:00
parent a03eb0d1be
commit 9873280f0e
36 changed files with 4911 additions and 1225 deletions

View File

@@ -13,6 +13,7 @@ from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional, Union, Callable, Tuple
from pathlib import Path
import json
import shutil
# Optional Textual imports - graceful fallback if not available
try:
@@ -121,6 +122,17 @@ class ResultRow:
"""Add a column to this row."""
str_value = str(value) if value is not None else ""
# Tables are single-line per row: normalize hard line breaks inside cells
# so values (e.g., long descriptions) don't break the ASCII box shape.
if str_value:
str_value = (
str_value
.replace("\r\n", " ")
.replace("\n", " ")
.replace("\r", " ")
.replace("\t", " ")
)
# Normalize extension columns globally and cap to 5 characters
if str(name).strip().lower() == "ext":
str_value = str_value.strip().lstrip(".")
@@ -717,6 +729,12 @@ class ResultTable:
"""
if not self.rows:
return "No results"
# Cap rendering to terminal width so long tables don't hard-wrap and
# visually break the border/shape.
term_width = shutil.get_terminal_size(fallback=(120, 24)).columns
if not term_width or term_width <= 0:
term_width = 120
# Calculate column widths
col_widths: Dict[str, int] = {}
@@ -739,7 +757,16 @@ class ResultTable:
column_names = list(col_widths.keys())
def capped_width(name: str) -> int:
cap = 5 if name.lower() == "ext" else 90
if name.lower() == "ext":
cap = 5
else:
# Single-column tables (e.g., get-tag) can use more horizontal space,
# but still must stay within the terminal to avoid hard wrapping.
if len(column_names) == 1:
# Keep room for side walls and optional row-number column.
cap = max(30, min(240, term_width - 6))
else:
cap = 90
return min(col_widths[name], cap)
widths = ([] if self.no_choice else [num_width]) + [capped_width(name) for name in column_names]
@@ -752,6 +779,10 @@ class ResultTable:
if self.header_lines:
table_width = max(table_width, max(len(line) for line in self.header_lines) + 2)
# Ensure final render doesn't exceed terminal width (minus 1 safety column).
safe_term_width = max(20, term_width - 1)
table_width = min(table_width, safe_term_width)
def wrap(text: str) -> str:
"""Wrap content with side walls and pad to table width."""
if len(text) > table_width - 2:
@@ -763,12 +794,26 @@ class ResultTable:
# Title block
if self.title:
lines.append("|" + "=" * (table_width - 2) + "|")
lines.append(wrap(self.title.ljust(table_width - 2)))
safe_title = (
str(self.title)
.replace("\r\n", " ")
.replace("\n", " ")
.replace("\r", " ")
.replace("\t", " ")
)
lines.append(wrap(safe_title.ljust(table_width - 2)))
lines.append("|" + "=" * (table_width - 2) + "|")
# Optional header metadata lines
for meta in self.header_lines:
lines.append(wrap(meta))
safe_meta = (
str(meta)
.replace("\r\n", " ")
.replace("\n", " ")
.replace("\r", " ")
.replace("\t", " ")
)
lines.append(wrap(safe_meta))
# Add header with # column
header_parts = [] if self.no_choice else ["#".ljust(num_width)]
@@ -787,6 +832,14 @@ class ResultTable:
for col_name in column_names:
width = capped_width(col_name)
col_value = row.get_column(col_name) or ""
if col_value:
col_value = (
col_value
.replace("\r\n", " ")
.replace("\n", " ")
.replace("\r", " ")
.replace("\t", " ")
)
if len(col_value) > width:
col_value = col_value[: width - 3] + "..."
row_parts.append(col_value.ljust(width))