diff --git a/Cargo.lock b/Cargo.lock index 68b82c9..758456c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -114,6 +114,15 @@ dependencies = [ "syn", ] +[[package]] +name = "clap_generate" +version = "3.0.0-beta.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "097ab5db1c3417442270cd57c8dd39f6c3114d3ce09d595f9efddbb1fcfaa799" +dependencies = [ + "clap", +] + [[package]] name = "crc32fast" version = "1.2.1" @@ -283,6 +292,7 @@ dependencies = [ "atty", "bzip2", "clap", + "clap_generate", "flate2", "infer", "libc", diff --git a/Cargo.toml b/Cargo.toml index c42ac8b..e9d9b02 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,10 @@ zip = { version = "0.5.13", default-features = false, features = ["defl flate2 = { version = "1.0.22", default-features = false, features = ["zlib"] } zstd = { version = "0.9.0", default-features = false, features = ["thin"] } +[build-dependencies] +clap = "=3.0.0-beta.5" +clap_generate = "=3.0.0-beta.5" + [dev-dependencies] tempfile = "3.2.0" infer = "0.5.0" diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..5372154 --- /dev/null +++ b/build.rs @@ -0,0 +1,22 @@ +use clap::{ArgEnum, IntoApp}; +use clap_generate::{generate_to, Shell}; + +use std::{env, fs::create_dir_all, path::Path}; + +include!("src/opts.rs"); + +fn main() { + println!("cargo:rerun-if-env-changed=GEN_COMPLETIONS"); + + if env::var_os("GEN_COMPLETIONS") != Some("1".into()) { + return; + } + + let out = &Path::new(&env::var_os("OUT_DIR").unwrap()).join("completions"); + create_dir_all(out).unwrap(); + let app = &mut Opts::into_app(); + + for shell in Shell::value_variants() { + generate_to(*shell, app, "ouch", out).unwrap(); + } +} diff --git a/src/archive/zip.rs b/src/archive/zip.rs index db35727..f15e650 100644 --- a/src/archive/zip.rs +++ b/src/archive/zip.rs @@ -11,7 +11,7 @@ use zip::{self, read::ZipFile, ZipArchive}; use crate::{ info, - utils::{self, dir_is_empty,strip_cur_dir, Bytes}, + utils::{self, dir_is_empty, strip_cur_dir, Bytes}, }; use self::utf8::get_invalid_utf8_paths; diff --git a/src/cli.rs b/src/cli.rs index 7a13aab..bd9a8de 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -5,50 +5,9 @@ use std::{ vec::Vec, }; -use clap::{Parser, ValueHint}; +use clap::Parser; -use crate::Error; - -#[derive(Parser, Debug)] -#[clap(version, about)] -pub struct Opts { - /// Skip overwrite questions positively. - #[clap(short, long, conflicts_with = "no")] - pub yes: bool, - - /// Skip overwrite questions negatively. - #[clap(short, long)] - pub no: bool, - - #[clap(subcommand)] - pub cmd: Subcommand, -} - -#[derive(Parser, PartialEq, Eq, Debug)] -pub enum Subcommand { - /// Compress files. Alias: c - #[clap(alias = "c")] - Compress { - /// Files to be compressed - #[clap(required = true, min_values = 1)] - files: Vec, - - /// The resulting file. Its extensions specify how the files will be compressed and they need to be supported - #[clap(required = true, value_hint = ValueHint::FilePath)] - output: PathBuf, - }, - /// Compress files. Alias: d - #[clap(alias = "d")] - Decompress { - /// Files to be decompressed - #[clap(required = true, min_values = 1)] - files: Vec, - - /// Decompress files in a directory other than the current - #[clap(short, long, value_hint = ValueHint::DirPath)] - output: Option, - }, -} +use crate::{Error, Opts, Subcommand}; impl Opts { /// A helper method that calls `clap::Parser::parse` and then translates relative paths to absolute. diff --git a/src/commands.rs b/src/commands.rs index 6d41347..b4e6fab 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -12,7 +12,6 @@ use utils::colors; use crate::{ archive, - cli::{Opts, Subcommand}, error::FinalError, extension::{ self, @@ -22,7 +21,7 @@ use crate::{ utils::nice_directory_display, utils::to_utf, utils::{self, dir_is_empty}, - Error, + Error, Opts, Subcommand, }; // Used in BufReader and BufWriter to perform less syscalls diff --git a/src/lib.rs b/src/lib.rs index 9a1a795..d0650e0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,18 +5,20 @@ //! 2. It's required by some integration tests at tests/ folder. // Public modules -pub mod cli; +pub mod archive; pub mod commands; // Private modules -pub mod archive; +mod cli; mod dialogs; mod error; mod extension; mod macros; +mod opts; mod utils; pub use error::{Error, Result}; +pub use opts::{Opts, Subcommand}; /// The status code ouch has when an error is encountered pub const EXIT_FAILURE: i32 = libc::EXIT_FAILURE; diff --git a/src/main.rs b/src/main.rs index 9fc88ec..eb886f9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use ouch::{cli::Opts, commands, Result}; +use ouch::{commands, Opts, Result}; fn main() { if let Err(err) = run() { diff --git a/src/opts.rs b/src/opts.rs new file mode 100644 index 0000000..6d414a8 --- /dev/null +++ b/src/opts.rs @@ -0,0 +1,44 @@ +use clap::{Parser, ValueHint}; + +use std::path::PathBuf; + +#[derive(Parser, Debug)] +#[clap(version, about)] +pub struct Opts { + /// Skip overwrite questions positively. + #[clap(short, long, conflicts_with = "no")] + pub yes: bool, + + /// Skip overwrite questions negatively. + #[clap(short, long)] + pub no: bool, + + #[clap(subcommand)] + pub cmd: Subcommand, +} + +#[derive(Parser, PartialEq, Eq, Debug)] +pub enum Subcommand { + /// Compress files. Alias: c + #[clap(alias = "c")] + Compress { + /// Files to be compressed + #[clap(required = true, min_values = 1)] + files: Vec, + + /// The resulting file. Its extensions specify how the files will be compressed and they need to be supported + #[clap(required = true, value_hint = ValueHint::FilePath)] + output: PathBuf, + }, + /// Compress files. Alias: d + #[clap(alias = "d")] + Decompress { + /// Files to be decompressed + #[clap(required = true, min_values = 1)] + files: Vec, + + /// Decompress files in a directory other than the current + #[clap(short, long, value_hint = ValueHint::DirPath)] + output: Option, + }, +} diff --git a/tests/compress_and_decompress.rs b/tests/compress_and_decompress.rs index 77d929d..71e5d13 100644 --- a/tests/compress_and_decompress.rs +++ b/tests/compress_and_decompress.rs @@ -7,10 +7,7 @@ use std::{ time::Duration, }; -use ouch::{ - cli::{Opts, Subcommand}, - commands::run, -}; +use ouch::{commands::run, Opts, Subcommand}; use rand::{rngs::SmallRng, RngCore, SeedableRng}; use tempfile::NamedTempFile; use utils::*; diff --git a/tests/utils.rs b/tests/utils.rs index 10cc749..ad3bdf4 100644 --- a/tests/utils.rs +++ b/tests/utils.rs @@ -7,10 +7,7 @@ use std::{ path::{Path, PathBuf}, }; -use ouch::{ - cli::{Opts, Subcommand}, - commands::run, -}; +use ouch::{commands::run, Opts, Subcommand}; pub fn create_empty_dir(at: &Path, filename: &str) -> PathBuf { let dirname = Path::new(filename);