hedl_cli/cli/core.rs
1// Dweve HEDL - Hierarchical Entity Data Language
2//
3// Copyright (c) 2025 Dweve IP B.V. and individual contributors.
4//
5// SPDX-License-Identifier: Apache-2.0
6//
7// Licensed under the Apache License, Version 2.0 (the "License");
8// you may not use this file except in compliance with the License.
9// You may obtain a copy of the License in the LICENSE file at the
10// root of this repository or at: http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Core HEDL commands for validation, formatting, linting, and inspection.
19//!
20//! This module contains the fundamental HEDL CLI commands that operate on
21//! individual HEDL files for validation, formatting, and analysis.
22
23use crate::commands;
24use clap::Subcommand;
25
26/// Core HEDL commands.
27///
28/// These commands provide the essential functionality for working with HEDL files:
29/// validation, formatting, linting, inspection, and statistics.
30///
31/// # Commands
32///
33/// - **Validate**: Check HEDL syntax and semantic correctness
34/// - **Format**: Convert to canonical form with optional optimizations
35/// - **Lint**: Check for best practices and style issues
36/// - **Inspect**: Visualize internal structure
37/// - **Stats**: Analyze size and token efficiency
38#[derive(Subcommand)]
39pub enum CoreCommands {
40 /// Validate a HEDL file
41 ///
42 /// Checks the syntax and semantic correctness of a HEDL file. In strict mode,
43 /// all references must resolve to existing entities.
44 Validate {
45 /// Input file path
46 #[arg(value_name = "FILE")]
47 file: String,
48
49 /// Strict mode (fail on any error)
50 #[arg(short, long)]
51 strict: bool,
52 },
53
54 /// Format a HEDL file to canonical form
55 ///
56 /// Reformats a HEDL file to its canonical representation. Supports various
57 /// formatting options including ditto optimization and automatic count hints.
58 Format {
59 /// Input file path
60 #[arg(value_name = "FILE")]
61 file: String,
62
63 /// Output file path (defaults to stdout)
64 #[arg(short, long)]
65 output: Option<String>,
66
67 /// Check only (exit 1 if not canonical)
68 #[arg(short, long)]
69 check: bool,
70
71 /// Use ditto optimization
72 #[arg(long, default_value = "true")]
73 ditto: bool,
74
75 /// Automatically add count hints to all matrix lists
76 #[arg(long)]
77 with_counts: bool,
78 },
79
80 /// Lint a HEDL file for best practices
81 ///
82 /// Analyzes a HEDL file for style issues, best practices violations, and
83 /// potential problems. Can output results in text or JSON format.
84 Lint {
85 /// Input file path
86 #[arg(value_name = "FILE")]
87 file: String,
88
89 /// Output format (text, json)
90 #[arg(short, long, default_value = "text")]
91 format: String,
92
93 /// Treat warnings as errors
94 #[arg(short = 'W', long)]
95 warn_error: bool,
96 },
97
98 /// Print parsed structure (debug)
99 ///
100 /// Displays the internal structure of a HEDL file as a tree, useful for
101 /// debugging and understanding how HEDL parses the file.
102 Inspect {
103 /// Input file path
104 #[arg(value_name = "FILE")]
105 file: String,
106
107 /// Show detailed internal structure
108 #[arg(short, long)]
109 verbose: bool,
110 },
111
112 /// Show size/token savings vs other formats
113 ///
114 /// Analyzes a HEDL file and compares its size and token count against
115 /// equivalent representations in JSON, YAML, XML, CSV, and Parquet.
116 Stats {
117 /// Input HEDL file
118 #[arg(value_name = "FILE")]
119 file: String,
120
121 /// Show estimated token counts for LLM context
122 #[arg(short, long)]
123 tokens: bool,
124 },
125}
126
127impl CoreCommands {
128 /// Execute the core command.
129 ///
130 /// # Returns
131 ///
132 /// Returns `Ok(())` on success, or an error message on failure.
133 ///
134 /// # Errors
135 ///
136 /// Returns `Err` if the command execution fails.
137 pub fn execute(self) -> Result<(), String> {
138 match self {
139 CoreCommands::Validate { file, strict } => commands::validate(&file, strict),
140 CoreCommands::Format {
141 file,
142 output,
143 check,
144 ditto,
145 with_counts,
146 } => commands::format(&file, output.as_deref(), check, ditto, with_counts),
147 CoreCommands::Lint {
148 file,
149 format,
150 warn_error,
151 } => commands::lint(&file, &format, warn_error),
152 CoreCommands::Inspect { file, verbose } => commands::inspect(&file, verbose),
153 CoreCommands::Stats { file, tokens } => commands::stats(&file, tokens),
154 }
155 }
156}