d
This commit is contained in:
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user