This commit is contained in:
nose
2025-12-07 20:52:47 -08:00
parent e3747555bf
commit be37eb9d5b
6 changed files with 373 additions and 28 deletions

View File

@@ -37,6 +37,8 @@ if str(SRC_DIR) not in sys.path:
from cli_renderers import Renderer # noqa: E402
from tarot import Card, Tarot, Tree, Cube # noqa: E402
import tarot.ui as ui_mod # noqa: E402
from tarot.ui import SpreadDisplay, display_cards as ui_display_cards # noqa: E402
app = typer.Typer(add_completion=True, help="CLI playground for the Tarot API.")
@@ -56,6 +58,7 @@ SAFE_ROOTS: Dict[str, Any] = {
"tree": Tree,
"cube": Cube,
"letter": letter_ns,
"ui": ui_mod,
}
_MISSING_DOCS: Set[str] = set()
@@ -69,6 +72,8 @@ ROOT_COMMANDS = [
"tree",
"cube",
"letter",
"display-cards",
"display-spread",
"help",
"quit",
"exit",
@@ -186,6 +191,10 @@ def _periodic_symbols() -> List[str]:
return list(periodic.keys()) if isinstance(periodic, dict) else []
def _spread_names() -> List[str]:
return list(SpreadDisplay.LAYOUTS.keys())
def _current_fragment(text: str) -> str:
stripped = text.rstrip()
if not stripped:
@@ -269,6 +278,9 @@ def _completion_candidates(text: str) -> List[str]:
if len(tokens) == 3 and tokens[1].lower() == "periodic":
return [s for s in _periodic_symbols() if s.lower().startswith(fragment)]
if cmd == "display-spread":
return [name for name in _spread_names() if name.lower().startswith(fragment)]
if cmd == "search":
# Simple heuristics: suggest option flags or option values based on prior flag
if last_token.startswith("-"):
@@ -399,6 +411,9 @@ def _print_structure_table() -> None:
"Draw a spread with random cards",
"tarot.deck.card.spread('Celtic Cross')",
),
("ui.display_cards([card1, card2])", "Open GUI to view cards", "ui.display_cards([tarot.deck.card(1)])"),
("display-spread 'Celtic Cross'", "CLI: draw + show spread", "python typer-test.py display-spread 'Celtic Cross'"),
("display-cards 1 2 3", "CLI: show specific cards", "python typer-test.py display-cards 1 2 3"),
("tarot.planet()", "Planet correspondences as dict", "tarot.planet()['Venus']"),
("tarot.hexagram()", "I Ching hexagrams as dict", "tarot.hexagram()[1]"),
("tree.sephera(n)", "Kabbalistic sephiroth", "tree.sephera(1)"),
@@ -784,6 +799,39 @@ def _handle_repl_command(parts: List[str], raw_line: str = "") -> bool:
console.print("No cards matched that filter.")
else:
_print_cards_table(cards)
@app.command("display-cards")
def display_cards_cmd(
numbers: List[int] = typer.Argument(..., help="Card numbers to display"),
deck_name: str = typer.Option("default", help="Deck name for UI display"),
) -> None:
"""Open a GUI window showing the given card numbers."""
_ensure_deck()
cards: List[Card] = []
for num in numbers:
card = Tarot.deck.card(num) # type: ignore[attr-defined]
if card is None:
typer.echo(f"Card {num} not found.")
raise typer.Exit(code=1)
cards.append(card)
ui_display_cards(cards, deck_name)
@app.command("display-spread")
def display_spread_cmd(
spread_name: str = typer.Argument("Celtic Cross", help="Spread name (e.g., 'Celtic Cross')"),
deck_name: str = typer.Option("default", help="Deck name for UI display"),
) -> None:
"""Draw a spread and open the GUI display for it."""
_ensure_deck()
reading = Tarot.deck.card.spread(spread_name) # type: ignore[attr-defined]
if reading is None:
typer.echo(f"Spread '{spread_name}' not found.")
raise typer.Exit(code=1)
ui_mod.display_spread(reading, deck_name)
return True
if cmd == "planet":
planet_name = parts[1] if len(parts) > 1 else None
@@ -800,6 +848,52 @@ def _handle_repl_command(parts: List[str], raw_line: str = "") -> bool:
return True
_render_value(planet_obj)
return True
if cmd == "display-cards":
if len(parts) < 2:
console.print("Usage: display-cards <card numbers...>")
console.print("Examples: display-cards 1 2 3")
console.print(" display-cards 2,11,20")
return True
_ensure_deck()
nums: List[int] = []
# Handle both space-separated and comma-separated numbers
tokens = []
for tok in parts[1:]:
# Split by comma if present
if "," in tok:
tokens.extend(tok.split(","))
else:
tokens.append(tok)
for tok in tokens:
tok = tok.strip()
if not tok:
continue
try:
nums.append(int(tok))
except ValueError:
console.print(f"Invalid card number: {tok}")
return True
cards: List[Card] = []
for num in nums:
card = Tarot.deck.card(num) # type: ignore[attr-defined]
if card is None:
console.print(f"Card {num} not found.")
return True
cards.append(card)
ui_display_cards(cards)
return True
if cmd == "display-spread":
spread_name = " ".join(parts[1:]) if len(parts) > 1 else "Celtic Cross"
_ensure_deck()
reading = Tarot.deck.card.spread(spread_name) # type: ignore[attr-defined]
if reading is None:
console.print(f"Spread '{spread_name}' not found.")
return True
ui_mod.display_spread(reading)
return True
if cmd == "hexagram":
hex_num = None
if len(parts) > 1 and parts[1].isdigit():