Skip to content

Commit

Permalink
feat: "gen_completions" command
Browse files Browse the repository at this point in the history
- cargo add clap_complete
- move commands related code into commands::mods.rs to simplify main.rs
  • Loading branch information
shawn111 committed May 2, 2024
1 parent c095ed8 commit b2e1413
Show file tree
Hide file tree
Showing 9 changed files with 122 additions and 55 deletions.
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ description = "A tool to simplify reprovisioning a fresh OS. Installs packages a
[dependencies]
anyhow = "1.0"
clap = { version = "4.5.4", features = ["derive"] }
clap_complete = "4.5.2"
colored = "2.1"
comfy-table = "7"
comtrya-lib = { path = "../lib", version = "0.8.8" }
Expand Down
2 changes: 1 addition & 1 deletion app/src/commands/apply.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use rhai::Engine;
use std::{collections::HashMap, ops::Deref};
use tracing::{debug, error, info, instrument, span, trace, warn};

#[derive(Parser, Debug)]
#[derive(Parser, Debug, PartialEq)]
pub(crate) struct Apply {
/// Run a subset of your manifests, comma separated list
#[arg(short, long, value_delimiter = ',')]
Expand Down
3 changes: 1 addition & 2 deletions app/src/commands/contexts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ use comfy_table::{presets::NOTHING, Attribute, Cell, ContentArrangement, Table};

use clap::Parser;

#[derive(Parser, Debug)]
#[command()]
#[derive(Parser, Debug, PartialEq)]
pub(crate) struct Contexts {
/// Show the values of the contexts
#[arg(long)]
Expand Down
29 changes: 29 additions & 0 deletions app/src/commands/gen_completions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use std::io;

use super::ComtryaCommand;
use crate::Runtime;

use clap::{Command, CommandFactory, Parser};
use clap_complete::{generate, Generator, Shell};

use crate::GlobalArgs;

#[derive(Parser, Debug, PartialEq)]
#[command(arg_required_else_help = true)]
pub(crate) struct GenCompletions {
/// If provided, outputs the completion file for given shell
#[arg(value_enum)]
shell: Shell,
}

fn print_completions<G: Generator>(gen: G, cmd: &mut Command) {
generate(gen, cmd, cmd.get_name().to_string(), &mut io::stdout());
}

impl ComtryaCommand for GenCompletions {
fn execute(&self, _runtime: &Runtime) -> anyhow::Result<()> {
print_completions(self.shell, &mut GlobalArgs::command());

Ok(())
}
}
37 changes: 37 additions & 0 deletions app/src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use clap::Subcommand;

mod apply;
pub(crate) use apply::Apply;

Expand All @@ -7,8 +9,43 @@ pub(crate) use version::Version;
mod contexts;
pub(crate) use contexts::Contexts;

mod gen_completions;
pub(crate) use gen_completions::GenCompletions;

use crate::Runtime;

pub trait ComtryaCommand {
fn execute(&self, runtime: &Runtime) -> anyhow::Result<()>;
}

#[derive(Debug, Subcommand, PartialEq)]
pub enum Commands {
/// Apply manifests
#[clap(aliases = &["do", "run"])]
Apply(Apply),

/// Print version information
Version(Version),

/// List available contexts (BETA)
Contexts(Contexts),

/// Auto generate completions
///
/// for examples:
/// - bash: ```source <(comtrya gen-completions bash)```
/// - fish: ```comtrya gen-completions fish | source```
#[command(long_about, verbatim_doc_comment)]
GenCompletions(GenCompletions),
}

impl Commands {
pub fn execute(self, runtime: &Runtime) -> anyhow::Result<()> {
match self {
Self::Apply(apply) => apply.execute(&runtime),
Self::Version(version) => version.execute(&runtime),
Self::Contexts(contexts) => contexts.execute(&runtime),
Self::GenCompletions(gen_completions) => gen_completions.execute(&runtime),
}
}
}
3 changes: 1 addition & 2 deletions app/src/commands/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ use crate::Runtime;

use clap::Parser;

#[derive(Parser, Debug)]
#[command()]
#[derive(Parser, Debug, PartialEq)]
pub(crate) struct Version {}

impl ComtryaCommand for Version {
Expand Down
40 changes: 7 additions & 33 deletions app/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use std::io;

use commands::ComtryaCommand;
use clap::Parser;

use clap::{Parser, Subcommand};
use comtrya_lib::contexts::build_contexts;
use comtrya_lib::contexts::Contexts;
use comtrya_lib::manifests;
Expand All @@ -16,7 +15,8 @@ mod commands;
mod config;

use config::{load_config, Config};
#[derive(Parser, Debug)]

#[derive(Parser, Debug, PartialEq)]
#[command(version, about, name="comtrya", long_about = None)]
struct GlobalArgs {
#[arg(short = 'd', long)]
Expand All @@ -31,37 +31,15 @@ struct GlobalArgs {
verbose: u8,

#[command(subcommand)]
command: Commands,
}

#[derive(Debug, Subcommand)]
enum Commands {
/// Apply manifests
#[clap(aliases = &["do", "run"])]
Apply(commands::Apply),

/// Print version information
Version(commands::Version),

/// List available contexts (BETA)
Contexts(commands::Contexts),
command: commands::Commands,
}

#[derive(Debug)]
pub struct Runtime {
pub(crate) args: GlobalArgs,
pub(crate) config: Config,
pub(crate) contexts: Contexts,
}

pub(crate) fn execute(runtime: Runtime) -> anyhow::Result<()> {
match &runtime.args.command {
Commands::Apply(apply) => apply.execute(&runtime),
Commands::Version(version) => version.execute(&runtime),
Commands::Contexts(contexts) => contexts.execute(&runtime),
}
}

fn configure_tracing(args: &GlobalArgs) {
let stdout_writer = match args.verbose {
0 => io::stdout.with_max_level(tracing::Level::INFO),
Expand Down Expand Up @@ -89,6 +67,7 @@ fn configure_tracing(args: &GlobalArgs) {

fn main() -> anyhow::Result<()> {
let args = GlobalArgs::parse();

configure_tracing(&args);

let config = match load_config(&args) {
Expand All @@ -105,14 +84,9 @@ fn main() -> anyhow::Result<()> {

// Run Context Providers
let contexts = build_contexts(&config);
let runtime = Runtime { config, contexts };

let runtime = Runtime {
args,
config,
contexts,
};

execute(runtime)?;
args.command.execute(&runtime)?;

Ok(())
}
Expand Down
52 changes: 35 additions & 17 deletions docs/src/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,39 @@ comtrya -h
```

```
USAGE:
comtrya [FLAGS] [OPTIONS] <SUBCOMMAND>
FLAGS:
-h, --help Prints help information
--no-color Disable color printing
-V, --version Prints version information
-v, --verbose Debug & tracing mode (-v, -vv)
OPTIONS:
-d, --manifest-directory <manifest-directory> Directory
SUBCOMMANDS:
apply Apply manifests
contexts List available contexts (BETA)
help Prints this message or the help of the given subcommand(s)
version Print version information
A tool to simplify reprovisioning a fresh OS. Installs packages and manages dotfiles.
Usage: comtrya [OPTIONS] <COMMAND>
Commands:
apply Apply manifests
version Print version information
contexts List available contexts (BETA)
gen-completions Auto generate completions
help Print this message or the help of the given subcommand(s)
Options:
-d, --manifest-directory <MANIFEST_DIRECTORY>
--no-color Disable color printing
-v... Debug & tracing mode (-v, -vv)
-h, --help Print help
-V, --version Print version
```

## Auto generate completions

Shell completions for comtrya can be generated by desired shell via gen-completions subcommand.

```
comtrya gen-completions [SHELL]
```

for bash
```
source <(comtrya gen-completions)
```

for fish
```
comtrya gen-completions fish | source
```

0 comments on commit b2e1413

Please sign in to comment.