Files
Medios-Macina/cmdlet/get_note.py

182 lines
5.8 KiB
Python
Raw Normal View History

2025-12-12 21:55:38 -08:00
from __future__ import annotations
2026-03-25 22:39:30 -07:00
from typing import Any, Dict, List, Sequence
2025-12-12 21:55:38 -08:00
import sys
from SYS.logger import log
2026-03-25 22:39:30 -07:00
from SYS.detail_view_helpers import create_detail_view, prepare_detail_metadata
from SYS.payload_builders import build_table_result_payload
from SYS.result_publication import publish_result_table
from SYS.result_table_helpers import add_row_columns
2025-12-12 21:55:38 -08:00
from SYS import pipeline as ctx
2025-12-16 23:23:43 -08:00
from . import _shared as sh
Cmdlet = sh.Cmdlet
CmdletArg = sh.CmdletArg
SharedArgs = sh.SharedArgs
normalize_hash = sh.normalize_hash
parse_cmdlet_args = sh.parse_cmdlet_args
normalize_result_input = sh.normalize_result_input
should_show_help = sh.should_show_help
2025-12-12 21:55:38 -08:00
class Get_Note(Cmdlet):
2025-12-12 21:55:38 -08:00
def __init__(self) -> None:
super().__init__(
name="get-note",
summary="List notes on a file in a store.",
2025-12-29 17:05:03 -08:00
usage='get-note -store <store> [-query "hash:<sha256>"]',
alias=["get-notes",
"get_note"],
2025-12-12 21:55:38 -08:00
arg=[
SharedArgs.STORE,
2025-12-20 02:12:45 -08:00
SharedArgs.QUERY,
2025-12-12 21:55:38 -08:00
],
detail=[
"- Notes are retrieved via the selected store backend.",
"- Lyrics are stored in a note named 'lyric'.",
],
exec=self.run,
)
try:
SharedArgs.STORE.choices = SharedArgs.get_store_choices(None)
except Exception:
pass
self.register()
def run(self, result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
if should_show_help(args):
log(f"Cmdlet: {self.name}\nSummary: {self.summary}\nUsage: {self.usage}")
return 0
parsed = parse_cmdlet_args(args, self)
store_override = parsed.get("store")
2026-03-25 22:39:30 -07:00
query_hash, query_valid = sh.require_single_hash_query(
parsed.get("query"),
"[get_note] Error: -query must be of the form hash:<sha256>",
log_file=sys.stderr,
)
if not query_valid:
2025-12-20 02:12:45 -08:00
return 1
2025-12-12 21:55:38 -08:00
results = normalize_result_input(result)
if not results:
2025-12-20 02:12:45 -08:00
if store_override and query_hash:
results = [{
"store": str(store_override),
"hash": query_hash
}]
2025-12-12 21:55:38 -08:00
else:
2025-12-29 17:05:03 -08:00
log(
'[get_note] Error: Requires piped item(s) or -store and -query "hash:<sha256>"',
file=sys.stderr,
)
2025-12-12 21:55:38 -08:00
return 1
2026-03-25 22:39:30 -07:00
store_registry = None
2025-12-12 21:55:38 -08:00
any_notes = False
2025-12-31 05:17:37 -08:00
display_items: List[Dict[str, Any]] = []
2026-01-12 20:33:14 -08:00
# We assume single subject for get-note detail view
main_res = results[0]
2026-03-25 22:39:30 -07:00
metadata = prepare_detail_metadata(main_res)
note_table = create_detail_view(
"Notes",
metadata,
table_name="note",
source_command=("get-note", []),
2026-01-12 20:33:14 -08:00
)
2025-12-12 21:55:38 -08:00
for res in results:
if not isinstance(res, dict):
continue
2026-03-25 22:39:30 -07:00
store_name, resolved_hash = sh.resolve_item_store_hash(
res,
override_store=str(store_override) if store_override else None,
override_hash=str(query_hash) if query_hash else None,
path_fields=("path",),
)
2025-12-12 21:55:38 -08:00
if not store_name:
log(
"[get_note] Error: Missing -store and item has no store field",
file=sys.stderr
)
2025-12-12 21:55:38 -08:00
return 1
if not resolved_hash:
continue
2026-01-12 20:33:14 -08:00
# Update metadata if we resolved a hash that wasn't in source
if resolved_hash and not metadata.get("Hash"):
metadata["Hash"] = resolved_hash
if store_name and not metadata.get("Store"):
metadata["Store"] = store_name
2025-12-12 21:55:38 -08:00
2026-03-25 22:39:30 -07:00
backend, store_registry, exc = sh.get_store_backend(
config,
store_name,
store_registry=store_registry,
)
if backend is None:
log(
f"[get_note] Error: Unknown store '{store_name}': {exc}",
file=sys.stderr
)
2025-12-12 21:55:38 -08:00
return 1
notes = {}
try:
notes = backend.get_note(
resolved_hash,
config=config
) or {}
2025-12-12 21:55:38 -08:00
except Exception:
notes = {}
if not notes:
continue
any_notes = True
# Emit each note as its own row so CLI renders a proper note table
for k in sorted(notes.keys(), key=lambda x: str(x).lower()):
v = notes.get(k)
raw_text = str(v or "")
2025-12-23 16:36:39 -08:00
# Keep payload small for IPC/pipes.
raw_text = raw_text[:999]
2025-12-12 21:55:38 -08:00
preview = " ".join(raw_text.replace("\r", "").split("\n"))
2026-03-25 22:39:30 -07:00
payload = build_table_result_payload(
columns=[
("Name", str(k)),
("Text", preview.strip()),
2025-12-31 05:17:37 -08:00
],
2026-03-25 22:39:30 -07:00
store=store_name,
hash=resolved_hash,
note_name=str(k),
note_text=raw_text,
)
2025-12-31 05:17:37 -08:00
display_items.append(payload)
if note_table is not None:
2026-03-25 22:39:30 -07:00
add_row_columns(
note_table,
[("Name", str(k)), ("Text", preview.strip())],
)
2026-01-12 20:33:14 -08:00
2025-12-31 05:17:37 -08:00
ctx.emit(payload)
2025-12-12 21:55:38 -08:00
2026-01-12 20:33:14 -08:00
# Always set the table overlay even if empty to show item details
2026-03-25 22:39:30 -07:00
publish_result_table(ctx, note_table, display_items, subject=result, overlay=True)
2026-01-12 20:33:14 -08:00
2025-12-12 21:55:38 -08:00
if not any_notes:
2026-01-12 20:33:14 -08:00
log("No notes found.")
2025-12-12 21:55:38 -08:00
return 0
CMDLET = Get_Note()