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_complete::shells::{Bash, Elvish, Fish, PowerShell, Zsh};
26
27/// Utility commands.
28///
29/// These commands provide helpful utilities for working with the HEDL CLI,
30/// including shell completion generation and help system enhancements.
31#[derive(Subcommand)]
32pub enum UtilityCommands {
33    /// Generate shell completion scripts
34    ///
35    /// Generates shell completion scripts for various shells, enabling
36    /// tab completion for HEDL commands, options, and file names.
37    ///
38    /// Supported shells: bash, zsh, fish, powershell, elvish
39    Completion {
40        /// Shell to generate completions for (bash, zsh, fish, powershell, elvish)
41        #[arg(value_name = "SHELL")]
42        shell: String,
43
44        /// Print installation instructions instead of generating script
45        #[arg(short, long)]
46        install: bool,
47    },
48}
49
50impl UtilityCommands {
51    /// Execute the utility command.
52    ///
53    /// # Returns
54    ///
55    /// Returns `Ok(())` on success, or an error message on failure.
56    ///
57    /// # Errors
58    ///
59    /// Returns `Err` if:
60    /// - Unsupported shell is specified
61    /// - Completion generation fails
62    pub fn execute(self) -> Result<(), crate::error::CliError> {
63        match self {
64            UtilityCommands::Completion { shell, install } => {
65                if install {
66                    println!("{}", commands::print_installation_instructions(&shell));
67                    Ok(())
68                } else {
69                    generate_completion(&shell)
70                }
71            }
72        }
73    }
74}
75
76/// Generate shell completion for the specified shell.
77///
78/// This is a helper function that uses the shared CLI command factory
79/// for completion generation, ensuring consistency with the actual CLI.
80///
81/// # Arguments
82///
83/// * `shell` - Shell name (bash, zsh, fish, powershell, elvish)
84///
85/// # Returns
86///
87/// Returns `Ok(())` on success, or an error message on failure.
88///
89/// # Errors
90///
91/// Returns `Err` if the shell is not supported.
92fn generate_completion(shell: &str) -> Result<(), crate::error::CliError> {
93    // Use the shared CLI command factory to ensure consistency with the actual CLI.
94    // This eliminates duplication and ensures generated completions always match
95    // the current command structure.
96
97    use crate::create_cli_command;
98    use crate::error::CliError;
99
100    let mut cmd = create_cli_command();
101
102    match shell.to_lowercase().as_str() {
103        "bash" => commands::generate_completion_for_command(Bash, &mut cmd),
104        "zsh" => commands::generate_completion_for_command(Zsh, &mut cmd),
105        "fish" => commands::generate_completion_for_command(Fish, &mut cmd),
106        "powershell" | "pwsh" => commands::generate_completion_for_command(PowerShell, &mut cmd),
107        "elvish" => commands::generate_completion_for_command(Elvish, &mut cmd),
108        _ => Err(CliError::invalid_input(format!(
109            "Unsupported shell: '{shell}'. Supported shells: bash, zsh, fish, powershell, elvish"
110        ))),
111    }
112}