hh
This commit is contained in:
@@ -1923,14 +1923,9 @@ class PipelineExecutor:
|
||||
# PHASE 4: Retrieve and filter items from current result set
|
||||
# ====================================================================
|
||||
# Cache items_list to avoid redundant lookups in helper functions below.
|
||||
# Priority: display items (from overlays like get-metadata) > last result items
|
||||
try:
|
||||
if display_table is not None and stage_table is display_table:
|
||||
items_list = ctx.get_last_result_items() or []
|
||||
else:
|
||||
if hasattr(ctx, "get_last_selectable_result_items"):
|
||||
items_list = ctx.get_last_selectable_result_items() or []
|
||||
else:
|
||||
items_list = ctx.get_last_result_items() or []
|
||||
items_list = ctx.get_last_result_items() or []
|
||||
except Exception as exc:
|
||||
debug(f"@N: Exception getting items_list: {exc}")
|
||||
items_list = []
|
||||
|
||||
@@ -3825,3 +3825,65 @@ def check_url_exists_in_storage(
|
||||
_mark_preflight_checked()
|
||||
return True
|
||||
|
||||
|
||||
def display_and_persist_items(
|
||||
items: List[Any],
|
||||
title: str = "Result",
|
||||
subject: Optional[Any] = None,
|
||||
display_type: str = "item",
|
||||
table: Optional[Table] = None,
|
||||
) -> None:
|
||||
"""Display detail panels and persist items for @N selection.
|
||||
|
||||
This helper function:
|
||||
1. Renders individual detail panels for each item
|
||||
2. Creates a result table with all items (or uses provided table)
|
||||
3. Persists the table so @N selection works across command boundaries
|
||||
|
||||
Args:
|
||||
items: List of items/dicts to display and make selectable
|
||||
title: Title for the result table (default: "Result")
|
||||
subject: Optional subject to associate with the results (usually first item or list)
|
||||
display_type: Type of display - "item" (default), "tag", or "custom" (no panels)
|
||||
table: Optional pre-built Table object (if None, creates new Table with title)
|
||||
"""
|
||||
if not items:
|
||||
return
|
||||
|
||||
try:
|
||||
# Create result table if not provided
|
||||
if table is None:
|
||||
table = Table(title=title)
|
||||
|
||||
# Render detail panels for each item (unless display_type is "custom")
|
||||
if display_type != "custom":
|
||||
try:
|
||||
from SYS.rich_display import render_item_details_panel
|
||||
|
||||
# Determine panel title prefix based on display type
|
||||
panel_prefix = "Tag" if display_type == "tag" else "Item"
|
||||
|
||||
# Render detail panel for each item
|
||||
for idx, item in enumerate(items, 1):
|
||||
try:
|
||||
render_item_details_panel(item, title=f"#{idx} {panel_prefix} Details")
|
||||
except Exception:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Add items to table if not already added by caller
|
||||
if not getattr(table, "_items_added", False):
|
||||
for item in items:
|
||||
table.add_result(item)
|
||||
|
||||
setattr(table, "_rendered_by_cmdlet", True)
|
||||
|
||||
# Use provided subject or default to first item
|
||||
if subject is None:
|
||||
subject = items[0] if len(items) == 1 else list(items)
|
||||
|
||||
# Persist table for @N selection across command boundaries
|
||||
pipeline_context.set_last_result_table(table, list(items), subject=subject)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@@ -704,19 +704,10 @@ class Add_File(Cmdlet):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
for idx, payload in enumerate(collected_payloads, 1):
|
||||
render_item_details_panel(payload, title=f"#{idx} Item Details")
|
||||
|
||||
table = Table("Result")
|
||||
for payload in collected_payloads:
|
||||
table.add_result(payload)
|
||||
setattr(table, "_rendered_by_cmdlet", True)
|
||||
subject = collected_payloads[0] if len(collected_payloads) == 1 else collected_payloads
|
||||
ctx.set_last_result_table_overlay(
|
||||
table,
|
||||
collected_payloads,
|
||||
subject=subject
|
||||
)
|
||||
# Use helper to display items and make them @-selectable
|
||||
from ._shared import display_and_persist_items
|
||||
display_and_persist_items(collected_payloads, title="Result", subject=subject)
|
||||
|
||||
try:
|
||||
ctx.set_last_result_items_only(list(collected_payloads))
|
||||
|
||||
@@ -1082,15 +1082,10 @@ class Add_Tag(Cmdlet):
|
||||
from SYS.rich_display import render_item_details_panel
|
||||
from SYS.result_table import Table
|
||||
|
||||
for idx, item in enumerate(display_items, 1):
|
||||
render_item_details_panel(item, title=f"#{idx} Item Details")
|
||||
|
||||
table = Table("Result")
|
||||
for item in display_items:
|
||||
table.add_result(item)
|
||||
setattr(table, "_rendered_by_cmdlet", True)
|
||||
subject = display_items[0] if len(display_items) == 1 else list(display_items)
|
||||
ctx.set_last_result_table_overlay(table, list(display_items), subject=subject)
|
||||
# Use helper to display items and make them @-selectable
|
||||
from ._shared import display_and_persist_items
|
||||
display_and_persist_items(list(display_items), title="Result", subject=subject)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
@@ -743,23 +743,10 @@ class Download_File(Cmdlet):
|
||||
pass
|
||||
|
||||
try:
|
||||
from SYS.rich_display import render_item_details_panel
|
||||
from SYS.result_table import Table
|
||||
|
||||
for idx, item in enumerate(emitted_items, 1):
|
||||
render_item_details_panel(item, title=f"#{idx} Item Details")
|
||||
|
||||
table = Table("Result")
|
||||
for item in emitted_items:
|
||||
table.add_result(item)
|
||||
setattr(table, "_rendered_by_cmdlet", True)
|
||||
|
||||
subject = emitted_items[0] if len(emitted_items) == 1 else list(emitted_items)
|
||||
pipeline_context.set_last_result_table_overlay(
|
||||
table,
|
||||
list(emitted_items),
|
||||
subject=subject,
|
||||
)
|
||||
# Use helper to display items and make them @-selectable
|
||||
from ._shared import display_and_persist_items
|
||||
display_and_persist_items(list(emitted_items), title="Result", subject=subject)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@@ -1969,7 +1956,12 @@ class Download_File(Cmdlet):
|
||||
else:
|
||||
import re
|
||||
|
||||
if not re.match(r"^\s*#?\d+\s*$", str(query_format)):
|
||||
if re.match(r"^\s*#?\d+\s*$", str(query_format)):
|
||||
# Numeric format like "720" or "1080p" - will be resolved later via resolve_height_selector
|
||||
# Don't set ytdl_format yet; let it fall through to per-URL resolution
|
||||
pass
|
||||
else:
|
||||
# Non-numeric format string - use as literal
|
||||
ytdl_format = query_format
|
||||
debug(f"DEBUG: [download-file] Using literal query_format '{query_format}' as ytdl_format")
|
||||
playlist_selection_handled = False
|
||||
|
||||
@@ -317,14 +317,9 @@ class Get_Metadata(Cmdlet):
|
||||
"get-metadata",
|
||||
list(args))
|
||||
self._add_table_body_row(table, row)
|
||||
ctx.set_last_result_table_overlay(table, [row], row)
|
||||
try:
|
||||
from SYS.rich_display import render_item_details_panel
|
||||
|
||||
render_item_details_panel(row)
|
||||
table._rendered_by_cmdlet = True
|
||||
except Exception:
|
||||
pass
|
||||
# Use helper to display item and make it @-selectable
|
||||
from ._shared import display_and_persist_items
|
||||
display_and_persist_items([row], title=table_title, subject=row)
|
||||
ctx.emit(row)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -323,10 +323,21 @@ def _emit_tags_as_table(
|
||||
"""
|
||||
from SYS.result_table import ItemDetailView, extract_item_metadata
|
||||
|
||||
# Prepare metadata for the detail view
|
||||
metadata = extract_item_metadata(subject)
|
||||
# Prepare metadata for the detail view, extracting all fields from subject first
|
||||
metadata = extract_item_metadata(subject) or {}
|
||||
|
||||
# Overlays/Overrides from explicit args if subject was partial
|
||||
# Preserve all additional fields from subject dict if it's a dict-like object
|
||||
if isinstance(subject, dict):
|
||||
for key, value in subject.items():
|
||||
# Skip internal/control fields
|
||||
if not key.startswith("_") and key not in {"selection_action", "selection_args"}:
|
||||
# Convert keys to readable labels (snake_case -> Title Case)
|
||||
label = str(key).replace("_", " ").title()
|
||||
# Only add if not already present from extract_item_metadata
|
||||
if label not in metadata and value is not None:
|
||||
metadata[label] = value
|
||||
|
||||
# Apply explicit parameter overrides (these take priority)
|
||||
if item_title:
|
||||
metadata["Title"] = item_title
|
||||
if file_hash:
|
||||
@@ -341,7 +352,7 @@ def _emit_tags_as_table(
|
||||
table = ItemDetailView("Tags", item_metadata=metadata, max_columns=1, exclude_tags=True)
|
||||
table.set_source_command("get-tag", [])
|
||||
|
||||
# Create TagItem for each tag
|
||||
# Create TagItem for each tag and add to table
|
||||
tag_items = []
|
||||
for idx, tag_name in enumerate(tags_list, start=1):
|
||||
tag_item = TagItem(
|
||||
@@ -356,38 +367,38 @@ def _emit_tags_as_table(
|
||||
table.add_result(tag_item)
|
||||
# Also emit to pipeline for downstream processing
|
||||
ctx.emit(tag_item)
|
||||
|
||||
# Store the table and items in history so @.. works to go back
|
||||
# Use overlay mode so it doesn't push the previous search to history stack
|
||||
# This makes get-tag behave like a transient view
|
||||
table_applied = False
|
||||
try:
|
||||
ctx.set_last_result_table_overlay(table, tag_items, subject)
|
||||
table_applied = True
|
||||
except AttributeError:
|
||||
try:
|
||||
ctx.set_last_result_table(table, tag_items, subject)
|
||||
table_applied = True
|
||||
except Exception:
|
||||
table_applied = False
|
||||
except Exception:
|
||||
table_applied = False
|
||||
|
||||
# Display the rich panel (metadata info) if not in quiet/emit-only mode.
|
||||
# In the TUI, this output is captured and shown in the log pane.
|
||||
|
||||
# Mark that items were already added to the table
|
||||
setattr(table, "_items_added", True)
|
||||
|
||||
# Display the table and persist for @N selection
|
||||
if not quiet:
|
||||
try:
|
||||
from SYS.rich_display import stdout_console
|
||||
stdout_console().print(table)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if table_applied:
|
||||
try:
|
||||
if hasattr(ctx, "set_current_stage_table"):
|
||||
ctx.set_current_stage_table(table)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Use the shared helper to persist the table for @N selection
|
||||
try:
|
||||
from cmdlet._shared import display_and_persist_items
|
||||
# Skip panel rendering since table already exists with custom ItemDetailView
|
||||
display_and_persist_items(
|
||||
tag_items,
|
||||
title=table.title if hasattr(table, 'title') else "Tags",
|
||||
subject=subject,
|
||||
display_type="custom",
|
||||
table=table,
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Also update the current stage table for TUI
|
||||
try:
|
||||
if hasattr(ctx, "set_current_stage_table"):
|
||||
ctx.set_current_stage_table(table)
|
||||
except Exception:
|
||||
pass
|
||||
# Note: CLI will handle displaying the table via ResultTable formatting
|
||||
|
||||
|
||||
@@ -1705,6 +1716,11 @@ def _run_impl(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
|
||||
# For store-backed items (Hydrus/Folders), we want the latest state.
|
||||
if display_tags and not emit_mode and not is_store_backed:
|
||||
subject_payload = _subject_payload_with(display_tags)
|
||||
# Merge the full result object into subject_payload so all original metadata is preserved
|
||||
if isinstance(result, dict):
|
||||
for key, value in result.items():
|
||||
if key not in subject_payload and not key.startswith("_"):
|
||||
subject_payload[key] = value
|
||||
_emit_tags_as_table(
|
||||
display_tags,
|
||||
file_hash=file_hash,
|
||||
@@ -1739,6 +1755,12 @@ def _run_impl(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
|
||||
current,
|
||||
service_name if source == "hydrus" else None,
|
||||
)
|
||||
# Merge the full result object into subject_payload so all original metadata is preserved
|
||||
# (e.g., url, source_url, etc. from search results)
|
||||
if isinstance(result, dict):
|
||||
for key, value in result.items():
|
||||
if key not in subject_payload and not key.startswith("_"):
|
||||
subject_payload[key] = value
|
||||
_emit_tags_as_table(
|
||||
current,
|
||||
file_hash=file_hash,
|
||||
|
||||
Reference in New Issue
Block a user