Skip to main content

zenith_cli/cli/
library.rs

1//! Argument types for `zenith library` and its subcommands.
2
3use clap::{Args, Subcommand};
4use std::path::PathBuf;
5
6/// Arguments for `zenith library`.
7///
8/// The library subsystem is a set of reusable **packs** — collections of design
9/// assets that you materialize into a `.zen` document.  A pack is identified by
10/// a package id such as `@zenith/filters`, and each pack exports one or more
11/// named **items** addressed as `<package>#<item>` (e.g.
12/// `@zenith/flowchart#decision`).
13///
14/// Three item kinds exist:
15///
16/// * **token** — a filter or mask token (e.g. `@zenith/filters#sepia`).  Added
17///   to the document's `tokens` block; apply with `filter=(token)"sepia"` or
18///   `mask=(token)"vignette"` on any node.
19/// * **component** — a reusable node group (e.g. a flowchart shape) that is
20///   materialized as an `instance` on a named page.  Requires `--page <id>`.
21/// * **action** — a canned transaction op sequence (e.g.
22///   `@zenith/brand-kit#apply-2026`) that mutates the target document's tokens
23///   or layout.  No page required.
24///
25/// Embedded `@zenith/*` packs are bundled in the binary; project-local packs
26/// live in `<project-dir>/libraries/*.zen` and shadow the embedded ones.
27///
28/// WORKFLOW:
29///   zenith library list                          # discover packs + items
30///   zenith library show @zenith/filters#sepia    # inspect one item
31///   zenith library add @zenith/filters#sepia --into poster.zen
32#[derive(Debug, Args)]
33#[command(
34    long_about = "Manage reusable library packs (embedded @zenith/* presets + project-local packs).\n\n\
35A pack exports items addressed as <package>#<item>, e.g. `@zenith/flowchart#decision`.\n\
36Item kinds:\n  \
37token     — filter or mask token; copy into tokens block, apply with filter=(token)\"id\"\n  \
38component — reusable node group; materialized as an instance on a page (requires --page)\n  \
39action    — canned tx op sequence; runs a transaction against the target document\n\n\
40Embedded @zenith/* packs are built in; project packs live in libraries/*.zen and shadow them.\n\n\
41WORKFLOW:\n  \
42zenith library list                          # discover packs and items\n  \
43zenith library show @zenith/filters#sepia    # inspect item content before adding\n  \
44zenith library add @zenith/filters#sepia --into poster.zen"
45)]
46pub struct LibraryArgs {
47    #[command(subcommand)]
48    pub command: LibrarySub,
49}
50
51/// Subcommands of `zenith library`.
52#[derive(Debug, Subcommand)]
53pub enum LibrarySub {
54    /// List all resolved library packs (project + embedded presets) and items.
55    ///
56    /// Lists every available pack and its exported items.  Run `zenith library
57    /// show <package>#<item>` to inspect any item in detail before adding it.
58    List(LibraryListArgs),
59
60    /// Inspect a library item in detail before adding it.
61    ///
62    /// Shows the package, item id, and kind-specific content: filter/mask token
63    /// types and ops, component node structure, or action op sequence.  Prints
64    /// the exact `zenith library add` invocation to materialize the item.
65    Show(LibraryShowArgs),
66
67    /// Materialize a library item into a target `.zen` document.
68    Add(LibraryAddArgs),
69}
70
71/// Arguments for `zenith library add`.
72#[derive(Debug, Args)]
73pub struct LibraryAddArgs {
74    /// The item to add, as `<package>#<item>`, e.g. `@zenith/flowchart#decision`.
75    pub spec: String,
76
77    /// Target `.zen` document to materialize the item into (written in-place,
78    /// unless `--dry-run`). Its parent directory is the project dir whose
79    /// `libraries/*.zen` packs are resolved alongside the embedded presets.
80    #[arg(long, value_name = "FILE")]
81    pub into: PathBuf,
82
83    /// Id of the page in the target document to place the instance on.
84    ///
85    /// Required only for COMPONENT items; TOKEN items (filter tokens) ignore it.
86    #[arg(long, value_name = "ID")]
87    pub page: Option<String>,
88
89    /// Instance origin as `X,Y` in pixels (default `0,0`).
90    #[arg(long, value_name = "X,Y")]
91    pub at: Option<String>,
92
93    /// Override the generated instance id base (default: the item name).
94    #[arg(long, value_name = "ID")]
95    pub id: Option<String>,
96
97    /// Print the resulting source to stdout WITHOUT writing the file.
98    #[arg(long)]
99    pub dry_run: bool,
100}
101
102/// Arguments for `zenith library list`.
103#[derive(Debug, Args)]
104pub struct LibraryListArgs {
105    /// Project directory, or a `.zen` file whose parent is the project directory.
106    /// Project `libraries/*.zen` packs are scanned alongside embedded presets.
107    /// Defaults to the current working directory.
108    pub path: Option<PathBuf>,
109
110    /// Emit machine-readable JSON instead of a human-readable listing.
111    #[arg(long)]
112    pub json: bool,
113}
114
115/// Arguments for `zenith library show`.
116#[derive(Debug, Args)]
117#[command(after_help = "EXAMPLES:\n  \
118zenith library show @zenith/filters#sepia       # inspect a filter token\n  \
119zenith library show @zenith/flowchart#decision  # inspect a component\n  \
120zenith library show @zenith/brand-kit#apply-2026 --json")]
121pub struct LibraryShowArgs {
122    /// The item to inspect, as `<package>#<item>`, e.g. `@zenith/filters#sepia`.
123    pub spec: String,
124
125    /// Project directory, or a `.zen` file whose parent is the project directory.
126    /// Project `libraries/*.zen` packs are resolved alongside embedded presets.
127    /// Defaults to the current working directory.
128    pub path: Option<PathBuf>,
129
130    /// Emit machine-readable JSON instead of a human-readable summary.
131    #[arg(long)]
132    pub json: bool,
133}