zenith_cli/commands/mod.rs
1//! Command implementations for the Zenith CLI.
2//!
3//! Each submodule exposes a pure function whose core logic operates on
4//! in-memory source bytes/strings — never touching the filesystem. File I/O
5//! (reading the document, writing formatted source or rendered output) is the
6//! responsibility of the dispatcher in `lib.rs`.
7
8pub mod fmt;
9pub mod fonts;
10pub mod inspect;
11pub mod library;
12pub mod merge;
13pub mod new;
14pub mod plugin;
15pub mod render;
16pub mod schema;
17pub mod theme;
18pub mod tokens;
19pub mod tx;
20pub mod validate;
21pub mod variant;
22pub mod workspace;
23
24// ── Shared helpers ────────────────────────────────────────────────────────────
25
26/// Serialise `value` to pretty-printed JSON, falling back to the error
27/// message string if serialisation itself fails (which cannot happen for
28/// these well-typed DTOs, but is kept as a safe fallback).
29pub(crate) fn serialize_pretty<T: serde::Serialize>(value: &T) -> String {
30 serde_json::to_string_pretty(value).unwrap_or_else(|e| e.to_string())
31}
32
33/// Serialise `value` to compact (whitespace-free) JSON.
34///
35/// This is the token-minimal form used by the MCP server for the text mirror of
36/// a structured result — `serialize_pretty` is for human terminals, this is for
37/// machine consumers where every whitespace byte is a wasted token.
38pub(crate) fn serialize_compact<T: serde::Serialize>(value: &T) -> String {
39 serde_json::to_string(value).unwrap_or_else(|e| e.to_string())
40}
41
42/// Format a single diagnostic as a human-readable line:
43/// `severity[code] (subject_id): message` (the subject is omitted when absent).
44pub(crate) fn format_diagnostic_line(d: &zenith_core::Diagnostic) -> String {
45 let sev = crate::json_types::severity_str(&d.severity);
46 let subject = d
47 .subject_id
48 .as_deref()
49 .map(|s| format!(" ({})", s))
50 .unwrap_or_default();
51 format!("{}[{}]{}: {}", sev, d.code, subject, d.message)
52}
53
54/// Format a hard (Error-severity) diagnostic as `error[code]: message`.
55///
56/// Used in "filter for Error, then format" pipelines in merge, variant, and
57/// render. Centralised here so the string shape has exactly one definition.
58pub(crate) fn format_error_diag(d: &zenith_core::Diagnostic) -> String {
59 format!("error[{}]: {}", d.code, d.message)
60}