diff --git a/justfile b/justfile index fb4713d..3a27543 100644 --- a/justfile +++ b/justfile @@ -256,11 +256,11 @@ build-dist: dist-supplemental: mkdir -p dist @# Generate completions and store them in dist/ - {{_cargo}} run --release {{_build_flags}} -- --dump-completions bash > dist/{{ _pkgname }}.bash - {{_cargo}} run --release {{_build_flags}} -- --dump-completions zsh > dist/{{ _pkgname }}.zsh - {{_cargo}} run --release {{_build_flags}} -- --dump-completions fish > dist/{{ _pkgname }}.fish - {{_cargo}} run --release {{_build_flags}} -- --dump-completions elvish > dist/{{ _pkgname }}.elvish - {{_cargo}} run --release {{_build_flags}} -- --dump-completions powershell > dist/{{ _pkgname }}.powershell + {{_cargo}} run --release {{_build_flags}} -- dump-completions bash > dist/{{ _pkgname }}.bash + {{_cargo}} run --release {{_build_flags}} -- dump-completions zsh > dist/{{ _pkgname }}.zsh + {{_cargo}} run --release {{_build_flags}} -- dump-completions fish > dist/{{ _pkgname }}.fish + {{_cargo}} run --release {{_build_flags}} -- dump-completions elvish > dist/{{ _pkgname }}.elvish + {{_cargo}} run --release {{_build_flags}} -- dump-completions powershell > dist/{{ _pkgname }}.powershell @# Generate manpage and store it gzipped in dist/ @# (This comes last so the earlier calls to `cargo run` will get the compiler warnings out) help2man -N '{{_cargo}} run {{_build_flags}} --' \ diff --git a/src/app.rs b/src/app.rs index f5fad60..67ff2fc 100644 --- a/src/app.rs +++ b/src/app.rs @@ -76,6 +76,8 @@ pub enum Command { }, /// List all available templates that can be downloaded ListTemplates, + /// Write a completion definition for the specified shell to stdout (bash, zsh, etc.) + DumpCompletions { shell: Option }, } /// Runs the command `add` @@ -134,12 +136,26 @@ fn run_list_templates() -> Result<()> { Ok(()) } +/// Runs the command `dump-completion` to generate a shell completion script +fn run_dump_completion(shell: Option) -> Result<()> { + let shell = shell.ok_or(ErrorKind::NoShellProvided)?; + debug!("Request to dump completion for {}", shell); + CliOpts::clap().gen_completions_to( + CliOpts::clap().get_bin_name().unwrap_or_else(|| structopt::clap::crate_name!()), + shell, + &mut ::std::io::stdout(), + ); + + Ok(()) +} + /// The actual `main()` pub fn main(opts: CliOpts) -> Result<()> { match opts.cmd { Command::Add { glob } => run_add(&glob)?, Command::Get { lang } => run_get(&lang)?, Command::ListTemplates => run_list_templates()?, + Command::DumpCompletions { shell } => run_dump_completion(shell)?, }; Ok(()) diff --git a/src/cache.rs b/src/cache.rs index 564c043..08c889e 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -1,6 +1,5 @@ //! Module to implement a simple cache use crate::errors::*; -use crate::template::GithubTemplates; use core::time::Duration; use log::{debug, trace}; use serde::Serialize; @@ -9,6 +8,10 @@ use std::io::{BufReader, BufWriter}; use std::path::PathBuf; use std::time::SystemTime; +/// Trait for a simple cache +/// +/// Each struct implementing this trais has to offer functions to `get`, `set` an object and check +/// if an value `exists`. pub trait Cache where T: Serialize + serde::de::DeserializeOwned { /// Stores the `data` under the given `key` diff --git a/src/errors.rs b/src/errors.rs index 329d1b0..304769c 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -21,6 +21,9 @@ error_chain! { TemplateNoContent { description("template contains no content that could be used or written. try to `load_content` first.") } + NoShellProvided { + description("no shell provided"), + } } } diff --git a/src/helpers.rs b/src/helpers.rs index 7038d14..0ca8a2b 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -12,8 +12,8 @@ use crate::errors::*; use crate::{helpers, template::GithubTemplates}; use directories::ProjectDirs; -use std::path::PathBuf; -use structopt::{clap, StructOpt}; +use std::{env, path::PathBuf}; +use structopt::StructOpt; /// Modified version of Clap's default template for proper help2man compatibility /// @@ -47,10 +47,6 @@ pub struct BoilerplateOpts { /// Display timestamps on log messages (sec, ms, ns, none) #[structopt(short, long, value_name = "resolution")] pub timestamp: Option, - - /// Write a completion definition for the specified shell to stdout (bash, zsh, etc.) - #[structopt(long, value_name = "shell")] - pub dump_completions: Option, } /// Checks if the given dir contains the root `.git` dir diff --git a/src/main.rs b/src/main.rs index cd984c5..cb7afa9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,12 +35,11 @@ extern crate error_chain; // stdlib imports use std::convert::TryInto; -use std::io; // 3rd-party imports mod errors; -use log::{debug, trace}; -use structopt::{clap, StructOpt}; +use log::trace; +use structopt::StructOpt; // Local imports mod app; @@ -78,17 +77,6 @@ fn main() { .expect("initializing logging output"); trace!("Initialized logging"); - // If requested, generate shell completions and then exit with status of "success" - if let Some(shell) = opts.boilerplate.dump_completions { - debug!("Request to dump completion for {}", shell); - app::CliOpts::clap().gen_completions_to( - app::CliOpts::clap().get_bin_name().unwrap_or_else(|| clap::crate_name!()), - shell, - &mut io::stdout(), - ); - std::process::exit(0); - }; - trace!("Starting with application"); if let Err(ref e) = app::main(opts) { use std::io::prelude::*;