hedl_cli/cli/utility.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//! Utility commands for HEDL CLI.
19//!
20//! This module provides utility commands that enhance the CLI experience,
21//! such as shell completion generation.
22
23use crate::commands;
24use clap::Subcommand;
25use clap::CommandFactory;
26use clap_complete::shells::*;
27
28/// Utility commands.
29///
30/// These commands provide helpful utilities for working with the HEDL CLI,
31/// including shell completion generation and help system enhancements.
32#[derive(Subcommand)]
33pub enum UtilityCommands {
34 /// Generate shell completion scripts
35 ///
36 /// Generates shell completion scripts for various shells, enabling
37 /// tab completion for HEDL commands, options, and file names.
38 ///
39 /// Supported shells: bash, zsh, fish, powershell, elvish
40 Completion {
41 /// Shell to generate completions for (bash, zsh, fish, powershell, elvish)
42 #[arg(value_name = "SHELL")]
43 shell: String,
44
45 /// Print installation instructions instead of generating script
46 #[arg(short, long)]
47 install: bool,
48 },
49}
50
51impl UtilityCommands {
52 /// Execute the utility command.
53 ///
54 /// # Returns
55 ///
56 /// Returns `Ok(())` on success, or an error message on failure.
57 ///
58 /// # Errors
59 ///
60 /// Returns `Err` if:
61 /// - Unsupported shell is specified
62 /// - Completion generation fails
63 pub fn execute(self) -> Result<(), String> {
64 match self {
65 UtilityCommands::Completion { shell, install } => {
66 if install {
67 println!("{}", commands::print_installation_instructions(&shell));
68 Ok(())
69 } else {
70 generate_completion(&shell)
71 }
72 }
73 }
74 }
75}
76
77/// Generate shell completion for the specified shell.
78///
79/// This is a helper function that creates a temporary command instance
80/// for completion generation. It needs access to the full CLI structure.
81///
82/// # Arguments
83///
84/// * `shell` - Shell name (bash, zsh, fish, powershell, elvish)
85///
86/// # Returns
87///
88/// Returns `Ok(())` on success, or an error message on failure.
89///
90/// # Errors
91///
92/// Returns `Err` if the shell is not supported.
93fn generate_completion(shell: &str) -> Result<(), String> {
94 // We need to create a temporary CLI structure for completion generation.
95 // This is a bit awkward since we're in a submodule, but we can use
96 // a trait-based approach to avoid circular dependencies.
97
98 // For now, we'll use a temporary command that matches the main CLI.
99 // This should be replaced with a better solution that uses the actual
100 // CLI command from main.rs.
101
102 use clap::Parser;
103
104 #[derive(Parser)]
105 #[command(name = "hedl")]
106 #[command(author, version, about = "HEDL - Hierarchical Entity Data Language toolkit")]
107 struct TempCli {
108 #[command(subcommand)]
109 command: super::Commands,
110 }
111
112 let mut cmd = TempCli::command();
113
114 match shell.to_lowercase().as_str() {
115 "bash" => commands::generate_completion_for_command(Bash, &mut cmd),
116 "zsh" => commands::generate_completion_for_command(Zsh, &mut cmd),
117 "fish" => commands::generate_completion_for_command(Fish, &mut cmd),
118 "powershell" | "pwsh" => commands::generate_completion_for_command(PowerShell, &mut cmd),
119 "elvish" => commands::generate_completion_for_command(Elvish, &mut cmd),
120 _ => Err(format!(
121 "Unsupported shell: '{}'. Supported shells: bash, zsh, fish, powershell, elvish",
122 shell
123 )),
124 }
125}