Skip to content

barkanido/command-line-template

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Command-Line Template

A production-ready Rust command-line application template with subcommands, JSON configuration, and clean architecture.

Features

  • Subcommand Architecture: Easily extensible command structure using clap
  • JSON Configuration: Persistent configuration with CLI argument override support
  • Cross-Platform: Works on Linux, macOS, and Windows with proper config paths
  • Clean Error Handling: Uses anyhow for ergonomic error propagation
  • Modular Design: Organized code structure for maintainability

Project Structure

src/
├── main.rs           # Entry point, CLI parsing, and dispatch logic
├── cli.rs            # Command-line argument definitions (clap)
├── config.rs         # Configuration loading/saving (JSON)
└── commands/         # Subcommand implementations
    ├── mod.rs        # Module exports
    ├── init.rs       # Initialize configuration
    ├── run.rs        # Main application logic
    └── status.rs     # Show application status

Installation

cargo build --release

The binary will be available at target/release/command-line-template.

Usage

Initialize Configuration

Create a default configuration file:

command-line-template init

Force overwrite existing configuration:

command-line-template init --force

Configuration file locations:

  • Linux/macOS: ~/.config/command-line-template/config.json
  • Windows: %APPDATA%\command-line-template\config.json

Run the Application

Execute the main application logic:

command-line-template run

With options:

command-line-template run --input myfile.txt --output result.txt

Override config values from CLI:

command-line-template run --verbose true --timeout 60 --custom-value "test"

Check Status

Show application status:

command-line-template status

Show full configuration:

command-line-template status --all

Global Options

These options work with any subcommand and override config file values:

  • -c, --config <PATH>: Use a custom config file location
  • -v, --verbose <BOOL>: Enable verbose output
  • -t, --timeout <SECONDS>: Set timeout duration

Example:

command-line-template --verbose true --timeout 120 run --input data.txt

Configuration

The configuration file uses JSON format. Default configuration:

{
  "verbose": false,
  "timeout": 30,
  "custom_value": ""
}

Edit the configuration file to set default values. CLI arguments always override config file values.

Extending the Template

Adding a New Subcommand

  1. Define the command in src/cli.rs:
#[derive(Subcommand, Debug)]
pub enum Commands {
    // ... existing commands ...
    
    /// Your new command description
    NewCommand {
        /// Command-specific argument
        #[arg(short, long)]
        argument: Option<String>,
    },
}
  1. Create implementation in src/commands/newcommand.rs:
use anyhow::Result;
use crate::config::Config;

pub fn execute(config: &Config, argument: Option<String>) -> Result<()> {
    println!("Executing new command");
    // Your command logic here
    Ok(())
}
  1. Export the module in src/commands/mod.rs:
pub mod newcommand;
  1. Add dispatch logic in src/main.rs:
match cli.command {
    // ... existing commands ...
    Commands::NewCommand { argument } => {
        commands::newcommand::execute(&config, argument)?;
    }
}

Adding Configuration Fields

  1. Add field to Config struct in src/config.rs:
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
    // ... existing fields ...
    
    #[serde(default)]
    pub new_field: String,
}
  1. Update Default implementation:
impl Default for Config {
    fn default() -> Self {
        Self {
            // ... existing fields ...
            new_field: String::from("default_value"),
        }
    }
}
  1. Add CLI argument in src/cli.rs (if needed):
#[derive(Parser, Debug)]
pub struct Cli {
    // ... existing fields ...
    
    #[arg(long, global = true)]
    pub new_field: Option<String>,
}
  1. Update merge logic in src/config.rs:
pub fn merge_with_cli(&mut self, /* ... */, new_field: Option<String>) {
    // ... existing merges ...
    if let Some(nf) = new_field {
        self.new_field = nf;
    }
}

Dependencies

  • clap: Command-line argument parsing with derive macros
  • serde: Serialization/deserialization framework
  • serde_json: JSON support for configuration files
  • anyhow: Flexible error handling
  • directories: Cross-platform config directory resolution

License

This is a template project. Choose your own license when using this template.

About

a template for a command line tool in rust using clap

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages