f
This commit is contained in:
@@ -34,6 +34,14 @@ except ImportError:
|
||||
TEXTUAL_AVAILABLE = False
|
||||
|
||||
|
||||
# Import ResultModel from the API for unification
|
||||
try:
|
||||
from SYS.result_table_api import ResultModel
|
||||
except ImportError:
|
||||
# Fallback if not available yet in directory structure (unlikely)
|
||||
ResultModel = None
|
||||
|
||||
|
||||
def _sanitize_cell_text(value: Any) -> str:
|
||||
"""Coerce to a single-line, tab-free string suitable for terminal display."""
|
||||
if value is None:
|
||||
@@ -741,8 +749,11 @@ class ResultTable:
|
||||
row = self.add_row()
|
||||
row.payload = result
|
||||
|
||||
# Handle ResultModel from the new strict API (SYS/result_table_api.py)
|
||||
if ResultModel and isinstance(result, ResultModel):
|
||||
self._add_result_model(row, result)
|
||||
# Handle TagItem from get_tag.py (tag display with index)
|
||||
if hasattr(result, "__class__") and result.__class__.__name__ == "TagItem":
|
||||
elif hasattr(result, "__class__") and result.__class__.__name__ == "TagItem":
|
||||
self._add_tag_item(row, result)
|
||||
# Handle ResultItem from search_file.py (compact display)
|
||||
elif hasattr(result, "__class__") and result.__class__.__name__ == "ResultItem":
|
||||
@@ -781,6 +792,62 @@ class ResultTable:
|
||||
payloads.append(payload)
|
||||
return payloads
|
||||
|
||||
@classmethod
|
||||
def from_api_table(cls, api_table: Any) -> "ResultTable":
|
||||
"""Convert a strict SYS.result_table_api.ResultTable into an interactive monolith ResultTable.
|
||||
|
||||
This allows providers using the new strict API to benefit from the monolith's
|
||||
interactive selection (@N) and rich layout features.
|
||||
"""
|
||||
# Duck typing check instead of strict isinstance to keep dependencies light
|
||||
if not hasattr(api_table, "rows") or not hasattr(api_table, "columns"):
|
||||
return cls(str(api_table))
|
||||
|
||||
title = getattr(api_table, "provider", "")
|
||||
# Try to get provider metadata title if available
|
||||
meta = getattr(api_table, "meta", {})
|
||||
if meta and isinstance(meta, dict):
|
||||
title = meta.get("title") or title
|
||||
|
||||
instance = cls(title)
|
||||
|
||||
# Import adapters if we want to extract selection args automatically
|
||||
# but let's keep it simple: we rely on add_result logic for most things.
|
||||
|
||||
# Iterate rows and build interactive ones
|
||||
for r in api_table.rows:
|
||||
row = instance.add_row()
|
||||
row.payload = r
|
||||
|
||||
# Use columns defined in the API table
|
||||
for col in api_table.columns:
|
||||
try:
|
||||
val = col.extractor(r)
|
||||
if col.format_fn:
|
||||
val = col.format_fn(val)
|
||||
row.add_column(col.header, val)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return instance
|
||||
|
||||
def _add_result_model(self, row: ResultRow, result: ResultModel) -> None:
|
||||
"""Extract and add ResultModel fields from the new API to row."""
|
||||
row.add_column("Title", result.title)
|
||||
|
||||
if result.ext:
|
||||
row.add_column("Ext", result.ext)
|
||||
|
||||
if result.size_bytes is not None:
|
||||
# Use the existing format_mb helper in this file
|
||||
row.add_column("Size", format_mb(result.size_bytes))
|
||||
|
||||
if result.source:
|
||||
row.add_column("Source", result.source)
|
||||
|
||||
# Add a placeholder for metadata-like display if needed in the main table
|
||||
# but usually metadata is handled by the detail panel now
|
||||
|
||||
def _add_search_result(self, row: ResultRow, result: Any) -> None:
|
||||
"""Extract and add SearchResult fields to row."""
|
||||
cols = getattr(result, "columns", None)
|
||||
@@ -1830,12 +1897,45 @@ def format_result(result: Any, title: str = "") -> str:
|
||||
return str(table)
|
||||
|
||||
def extract_item_metadata(item: Any) -> Dict[str, Any]:
|
||||
"""Extract a comprehensive set of metadata from an item for the ItemDetailView."""
|
||||
"""Extract a comprehensive set of metadata from an item for the ItemDetailView.
|
||||
|
||||
Now supports SYS.result_table_api.ResultModel as a first-class input.
|
||||
"""
|
||||
if item is None:
|
||||
return {}
|
||||
|
||||
out = {}
|
||||
|
||||
# Handle ResultModel specifically for better detail display
|
||||
if ResultModel and isinstance(item, ResultModel):
|
||||
if item.title: out["Title"] = item.title
|
||||
if item.path: out["Path"] = item.path
|
||||
if item.ext: out["Ext"] = item.ext
|
||||
if item.size_bytes: out["Size"] = format_mb(item.size_bytes)
|
||||
if item.source: out["Store"] = item.source
|
||||
|
||||
# Merge internal metadata dict
|
||||
if item.metadata:
|
||||
for k, v in item.metadata.items():
|
||||
# Convert keys to readable labels (snake_case -> Title Case)
|
||||
label = str(k).replace("_", " ").title()
|
||||
if label not in out and v is not None:
|
||||
out[label] = v
|
||||
|
||||
# URLs/Tags/Relations from metadata if present
|
||||
data = item.metadata or {}
|
||||
url = _get_first_dict_value(data, ["url", "URL"])
|
||||
if url: out["Url"] = url
|
||||
|
||||
rels = _get_first_dict_value(data, ["relationships", "rel"])
|
||||
if rels: out["Relations"] = rels
|
||||
|
||||
tags = _get_first_dict_value(data, ["tags", "tag"])
|
||||
if tags: out["Tags"] = tags
|
||||
|
||||
return out
|
||||
|
||||
# Fallback to existing extraction logic for legacy objects/dicts
|
||||
# Use existing extractors from match-standard result table columns
|
||||
title = extract_title_value(item)
|
||||
if title:
|
||||
|
||||
Reference in New Issue
Block a user