mirror of
https://github.com/ouch-org/ouch.git
synced 2025-06-08 04:25:31 +00:00
Start replacing clap
with oof
This commit is contained in:
parent
535d4fcc93
commit
0c9131c307
@ -22,6 +22,9 @@ bzip2 = "0.4.2"
|
|||||||
flate2 = "1.0.14"
|
flate2 = "1.0.14"
|
||||||
zip = "0.5.11"
|
zip = "0.5.11"
|
||||||
|
|
||||||
|
# Dependency from workspace
|
||||||
|
oof = { path = "./oof" }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
|
@ -8,9 +8,9 @@ use std::{
|
|||||||
/// ArgFlag::long(), is actually a Flag::long(), but sets a internal attribute.
|
/// ArgFlag::long(), is actually a Flag::long(), but sets a internal attribute.
|
||||||
///
|
///
|
||||||
/// Examples in here pls
|
/// Examples in here pls
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct ArgFlag;
|
pub struct ArgFlag;
|
||||||
|
|
||||||
#[allow(clippy::new_ret_no_self)]
|
|
||||||
impl ArgFlag {
|
impl ArgFlag {
|
||||||
pub fn long(name: &'static str) -> Flag {
|
pub fn long(name: &'static str) -> Flag {
|
||||||
Flag {
|
Flag {
|
||||||
@ -44,7 +44,7 @@ impl Flag {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, PartialEq, Eq, Debug)]
|
||||||
pub struct Flags {
|
pub struct Flags {
|
||||||
pub boolean_flags: BTreeSet<&'static str>,
|
pub boolean_flags: BTreeSet<&'static str>,
|
||||||
pub argument_flags: BTreeMap<&'static str, OsString>,
|
pub argument_flags: BTreeMap<&'static str, OsString>,
|
||||||
@ -70,6 +70,7 @@ impl Flags {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum FlagType {
|
pub enum FlagType {
|
||||||
None,
|
None,
|
||||||
Short,
|
Short,
|
||||||
|
@ -173,9 +173,9 @@ pub fn filter_flags(
|
|||||||
if let FlagType::Long = flag_type {
|
if let FlagType::Long = flag_type {
|
||||||
let flag = trim_double_hyphen(flag);
|
let flag = trim_double_hyphen(flag);
|
||||||
|
|
||||||
let flag_info = long_flags_info
|
let flag_info = long_flags_info.get(flag).unwrap_or_else(|| {
|
||||||
.get(flag)
|
panic!("User error: Unexpected/UNKNOWN flag '{}'", flag);
|
||||||
.unwrap_or_else(|| panic!("User error: Unexpected/UNKNOWN flag '{}'", flag));
|
});
|
||||||
|
|
||||||
let flag_name = flag_info.long;
|
let flag_name = flag_info.long;
|
||||||
|
|
||||||
@ -275,26 +275,26 @@ mod tests {
|
|||||||
assert_eq!(args[0], "a");
|
assert_eq!(args[0], "a");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
// #[test]
|
||||||
fn test_flag_info_macros() {
|
// fn test_flag_info_macros() {
|
||||||
let flags_info = [
|
// let flags_info = [
|
||||||
arg_flag!('o', "output_file"),
|
// arg_flag!('o', "output_file"),
|
||||||
arg_flag!("delay"),
|
// arg_flag!("delay"),
|
||||||
flag!('v', "verbose"),
|
// flag!('v', "verbose"),
|
||||||
flag!('h', "help"),
|
// flag!('h', "help"),
|
||||||
flag!("version"),
|
// flag!("version"),
|
||||||
];
|
// ];
|
||||||
|
|
||||||
let expected = [
|
// let expected = [
|
||||||
ArgFlag::long("output_file").short('o'),
|
// ArgFlag::long("output_file").short('o'),
|
||||||
ArgFlag::long("delay"),
|
// ArgFlag::long("delay"),
|
||||||
Flag::long("verbose").short('v'),
|
// Flag::long("verbose").short('v'),
|
||||||
Flag::long("help").short('h'),
|
// Flag::long("help").short('h'),
|
||||||
Flag::long("version"),
|
// Flag::long("version"),
|
||||||
];
|
// ];
|
||||||
|
|
||||||
assert_eq!(flags_info, expected);
|
// assert_eq!(flags_info, expected);
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
// TODO: remove should_panic and use proper error handling inside of filter_args
|
// TODO: remove should_panic and use proper error handling inside of filter_args
|
||||||
@ -349,23 +349,23 @@ mod tests {
|
|||||||
/// Create a flag with long flag (?).
|
/// Create a flag with long flag (?).
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! flag {
|
macro_rules! flag {
|
||||||
($short:expr, $long:expr) => {
|
($short:expr, $long:expr) => {{
|
||||||
Flag::long($long).short($short)
|
oof::Flag::long($long).short($short)
|
||||||
};
|
}};
|
||||||
|
|
||||||
($long:expr) => {
|
($long:expr) => {{
|
||||||
Flag::long($long)
|
oof::Flag::long($long)
|
||||||
};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a flag with long flag (?), receives argument (?).
|
/// Create a flag with long flag (?), receives argument (?).
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! arg_flag {
|
macro_rules! arg_flag {
|
||||||
($short:expr, $long:expr) => {
|
($short:expr, $long:expr) => {{
|
||||||
ArgFlag::long($long).short($short)
|
oof::ArgFlag::long($long).short($short)
|
||||||
};
|
}};
|
||||||
|
|
||||||
($long:expr) => {
|
($long:expr) => {{
|
||||||
ArgFlag::long($long)
|
oof::ArgFlag::long($long)
|
||||||
};
|
}};
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ pub fn trim_double_hyphen(flag_text: &str) -> &str {
|
|||||||
/// Util function to skip the single leading short flag hyphen.
|
/// Util function to skip the single leading short flag hyphen.
|
||||||
pub fn trim_single_hyphen(flag_text: &str) -> &str {
|
pub fn trim_single_hyphen(flag_text: &str) -> &str {
|
||||||
let mut chars = flag_text.chars();
|
let mut chars = flag_text.chars();
|
||||||
|
|
||||||
chars.next(); // Skipping 1 char
|
chars.next(); // Skipping 1 char
|
||||||
chars.as_str()
|
chars.as_str()
|
||||||
}
|
}
|
||||||
|
396
src/cli.rs
396
src/cli.rs
@ -1,212 +1,260 @@
|
|||||||
use std::{
|
use std::{
|
||||||
convert::TryFrom,
|
convert::TryFrom,
|
||||||
|
env,
|
||||||
|
ffi::OsString,
|
||||||
fs,
|
fs,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
|
|
||||||
use clap::{Arg, Values};
|
use oof::{arg_flag, flag};
|
||||||
use colored::Colorize;
|
|
||||||
|
|
||||||
use crate::{extension::Extension, file::File};
|
// use clap::{Arg, Values};
|
||||||
|
// use colored::Colorize;
|
||||||
|
|
||||||
|
// use crate::{extension::Extension, file::File};
|
||||||
|
use crate::file::File;
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Debug)]
|
#[derive(PartialEq, Eq, Debug)]
|
||||||
pub enum CommandKind {
|
pub enum Command {
|
||||||
Compression(
|
/// Files to be compressed
|
||||||
/// Files to be compressed
|
Compress {
|
||||||
Vec<PathBuf>,
|
files: Vec<PathBuf>,
|
||||||
),
|
flags: oof::Flags,
|
||||||
Decompression(
|
},
|
||||||
/// Files to be decompressed and their extensions
|
/// Files to be decompressed and their extensions
|
||||||
Vec<File>,
|
Decompress {
|
||||||
),
|
files: Vec<PathBuf>,
|
||||||
|
output_folder: Option<PathBuf>,
|
||||||
|
flags: oof::Flags,
|
||||||
|
},
|
||||||
|
ShowHelp,
|
||||||
|
ShowVersion,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
// #[derive(PartialEq, Eq, Debug)]
|
||||||
pub enum Flags {
|
// pub struct Command {
|
||||||
// No flags supplied
|
// pub kind: CommandKind,
|
||||||
None,
|
// pub output: Option<File>,
|
||||||
// Flag -y, --yes supplied
|
// }
|
||||||
AlwaysYes,
|
|
||||||
// Flag -n, --no supplied
|
|
||||||
AlwaysNo,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Debug)]
|
// // pub fn clap_app<'a, 'b>() -> clap::App<'a, 'b> {
|
||||||
pub struct Command {
|
// // clap::App::new("ouch")
|
||||||
pub kind: CommandKind,
|
// // .version("0.1.4")
|
||||||
pub output: Option<File>,
|
// // .about("ouch is a unified compression & decompression utility")
|
||||||
}
|
// // .after_help(
|
||||||
|
// // "ouch infers what to based on the extensions of the input files and output file received.
|
||||||
|
// // Examples: `ouch -i movies.tar.gz classes.zip -o Videos/` in order to decompress files into a folder.
|
||||||
|
// // `ouch -i headers/ sources/ Makefile -o my-project.tar.gz`
|
||||||
|
// // `ouch -i image{1..50}.jpeg -o images.zip`
|
||||||
|
// // Please relate any issues or contribute at https://github.com/vrmiguel/ouch")
|
||||||
|
// // .author("Vinícius R. Miguel")
|
||||||
|
// // .help_message("Displays this message and exits")
|
||||||
|
// // .settings(&[
|
||||||
|
// // clap::AppSettings::ColoredHelp,
|
||||||
|
// // clap::AppSettings::ArgRequiredElseHelp,
|
||||||
|
// // ])
|
||||||
|
// // .arg(
|
||||||
|
// // Arg::with_name("input")
|
||||||
|
// // .required(true)
|
||||||
|
// // .multiple(true)
|
||||||
|
// // .long("input")
|
||||||
|
// // .short("i")
|
||||||
|
// // .help("The input files or directories.")
|
||||||
|
// // .takes_value(true),
|
||||||
|
// // )
|
||||||
|
// // .arg(
|
||||||
|
// // Arg::with_name("output")
|
||||||
|
// // // --output/-o not required when output can be inferred from the input files
|
||||||
|
// // .required(false)
|
||||||
|
// // .multiple(false)
|
||||||
|
// // .long("output")
|
||||||
|
// // .short("o")
|
||||||
|
// // .help("The output directory or compressed file.")
|
||||||
|
// // .takes_value(true),
|
||||||
|
// // )
|
||||||
|
// // .arg(
|
||||||
|
// // Arg::with_name("yes")
|
||||||
|
// // .required(false)
|
||||||
|
// // .multiple(false)
|
||||||
|
// // .long("yes")
|
||||||
|
// // .short("y")
|
||||||
|
// // .help("Says yes to all confirmation dialogs.")
|
||||||
|
// // .conflicts_with("no")
|
||||||
|
// // .takes_value(false),
|
||||||
|
// // )
|
||||||
|
// // .arg(
|
||||||
|
// // Arg::with_name("no")
|
||||||
|
// // .required(false)
|
||||||
|
// // .multiple(false)
|
||||||
|
// // .long("no")
|
||||||
|
// // .short("n")
|
||||||
|
// // .help("Says no to all confirmation dialogs.")
|
||||||
|
// // .conflicts_with("yes")
|
||||||
|
// // .takes_value(false),
|
||||||
|
// // )
|
||||||
|
// // }
|
||||||
|
|
||||||
pub fn clap_app<'a, 'b>() -> clap::App<'a, 'b> {
|
// // pub fn get_matches() -> clap::ArgMatches<'static> {
|
||||||
clap::App::new("ouch")
|
// // clap_app().get_matches()
|
||||||
.version("0.1.4")
|
// // }
|
||||||
.about("ouch is a unified compression & decompression utility")
|
|
||||||
.after_help(
|
|
||||||
"ouch infers what to based on the extensions of the input files and output file received.
|
|
||||||
Examples: `ouch -i movies.tar.gz classes.zip -o Videos/` in order to decompress files into a folder.
|
|
||||||
`ouch -i headers/ sources/ Makefile -o my-project.tar.gz`
|
|
||||||
`ouch -i image{1..50}.jpeg -o images.zip`
|
|
||||||
Please relate any issues or contribute at https://github.com/vrmiguel/ouch")
|
|
||||||
.author("Vinícius R. Miguel")
|
|
||||||
.help_message("Displays this message and exits")
|
|
||||||
.settings(&[
|
|
||||||
clap::AppSettings::ColoredHelp,
|
|
||||||
clap::AppSettings::ArgRequiredElseHelp,
|
|
||||||
])
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("input")
|
|
||||||
.required(true)
|
|
||||||
.multiple(true)
|
|
||||||
.long("input")
|
|
||||||
.short("i")
|
|
||||||
.help("The input files or directories.")
|
|
||||||
.takes_value(true),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("output")
|
|
||||||
// --output/-o not required when output can be inferred from the input files
|
|
||||||
.required(false)
|
|
||||||
.multiple(false)
|
|
||||||
.long("output")
|
|
||||||
.short("o")
|
|
||||||
.help("The output directory or compressed file.")
|
|
||||||
.takes_value(true),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("yes")
|
|
||||||
.required(false)
|
|
||||||
.multiple(false)
|
|
||||||
.long("yes")
|
|
||||||
.short("y")
|
|
||||||
.help("Says yes to all confirmation dialogs.")
|
|
||||||
.conflicts_with("no")
|
|
||||||
.takes_value(false),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("no")
|
|
||||||
.required(false)
|
|
||||||
.multiple(false)
|
|
||||||
.long("no")
|
|
||||||
.short("n")
|
|
||||||
.help("Says no to all confirmation dialogs.")
|
|
||||||
.conflicts_with("yes")
|
|
||||||
.takes_value(false),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_matches() -> clap::ArgMatches<'static> {
|
// pub fn parse_matches(matches: clap::ArgMatches<'static>) -> {
|
||||||
clap_app().get_matches()
|
// let flag = match (matches.is_present("yes"), matches.is_present("no")) {
|
||||||
}
|
// (true, true) => unreachable!(),
|
||||||
|
// (true, _) => Flags::AlwaysYes,
|
||||||
|
// (_, true) => Flags::AlwaysNo,
|
||||||
|
// (_, _) => Flags::None,
|
||||||
|
// };
|
||||||
|
|
||||||
pub fn parse_matches(matches: clap::ArgMatches<'static>) -> crate::Result<(Command, Flags)> {
|
// Ok((Command::try_from(matches)?, flag))
|
||||||
let flag = match (matches.is_present("yes"), matches.is_present("no")) {
|
// }
|
||||||
(true, true) => unreachable!(),
|
|
||||||
(true, _) => Flags::AlwaysYes,
|
|
||||||
(_, true) => Flags::AlwaysNo,
|
|
||||||
(_, _) => Flags::None,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok((Command::try_from(matches)?, flag))
|
// impl TryFrom<clap::ArgMatches<'static>> for Command {
|
||||||
}
|
// type Error = crate::Error;
|
||||||
|
|
||||||
impl TryFrom<clap::ArgMatches<'static>> for Command {
|
// fn try_from(matches: clap::ArgMatches<'static>) -> crate::Result<Command> {
|
||||||
type Error = crate::Error;
|
// let process_decompressible_input = |input_files: Values| {
|
||||||
|
// let input_files =
|
||||||
|
// input_files.map(|filename| (Path::new(filename), Extension::new(filename)));
|
||||||
|
|
||||||
fn try_from(matches: clap::ArgMatches<'static>) -> crate::Result<Command> {
|
// for file in input_files.clone() {
|
||||||
let process_decompressible_input = |input_files: Values| {
|
// match file {
|
||||||
let input_files =
|
// (filename, Ok(_)) => {
|
||||||
input_files.map(|filename| (Path::new(filename), Extension::new(filename)));
|
// let path = Path::new(filename);
|
||||||
|
// if !path.exists() {
|
||||||
|
// return Err(crate::Error::FileNotFound(filename.into()));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// (filename, Err(_)) => {
|
||||||
|
// return Err(crate::Error::InputsMustHaveBeenDecompressible(
|
||||||
|
// filename.into(),
|
||||||
|
// ));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
for file in input_files.clone() {
|
// Ok(input_files
|
||||||
match file {
|
// .map(|(filename, extension)| {
|
||||||
(filename, Ok(_)) => {
|
// (fs::canonicalize(filename).unwrap(), extension.unwrap())
|
||||||
let path = Path::new(filename);
|
// })
|
||||||
if !path.exists() {
|
// .map(File::from)
|
||||||
return Err(crate::Error::FileNotFound(filename.into()));
|
// .collect::<Vec<_>>())
|
||||||
}
|
// };
|
||||||
}
|
|
||||||
(filename, Err(_)) => {
|
|
||||||
return Err(crate::Error::InputsMustHaveBeenDecompressible(
|
|
||||||
filename.into(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(input_files
|
// // Possibilities:
|
||||||
.map(|(filename, extension)| {
|
// // * Case 1: output not supplied, therefore try to infer output by checking if all input files are decompressible
|
||||||
(fs::canonicalize(filename).unwrap(), extension.unwrap())
|
// // * Case 2: output supplied
|
||||||
})
|
|
||||||
.map(File::from)
|
|
||||||
.collect::<Vec<_>>())
|
|
||||||
};
|
|
||||||
|
|
||||||
// Possibilities:
|
// let output_was_supplied = matches.is_present("output");
|
||||||
// * Case 1: output not supplied, therefore try to infer output by checking if all input files are decompressible
|
|
||||||
// * Case 2: output supplied
|
|
||||||
|
|
||||||
let output_was_supplied = matches.is_present("output");
|
// let input_files = matches.values_of("input").unwrap(); // Safe to unwrap since input is an obligatory argument
|
||||||
|
|
||||||
let input_files = matches.values_of("input").unwrap(); // Safe to unwrap since input is an obligatory argument
|
// if output_was_supplied {
|
||||||
|
// let output_file = matches.value_of("output").unwrap(); // Safe unwrap since we've established that output was supplied
|
||||||
|
|
||||||
if output_was_supplied {
|
// let output_file_extension = Extension::new(output_file);
|
||||||
let output_file = matches.value_of("output").unwrap(); // Safe unwrap since we've established that output was supplied
|
|
||||||
|
|
||||||
let output_file_extension = Extension::new(output_file);
|
// let output_is_compressible = output_file_extension.is_ok();
|
||||||
|
// if output_is_compressible {
|
||||||
|
// // The supplied output is compressible, so we'll compress our inputs to it
|
||||||
|
|
||||||
let output_is_compressible = output_file_extension.is_ok();
|
// let canonical_paths = input_files.clone().map(Path::new).map(fs::canonicalize);
|
||||||
if output_is_compressible {
|
// for (filename, canonical_path) in input_files.zip(canonical_paths.clone()) {
|
||||||
// The supplied output is compressible, so we'll compress our inputs to it
|
// if let Err(err) = canonical_path {
|
||||||
|
// let path = PathBuf::from(filename);
|
||||||
|
// if !path.exists() {
|
||||||
|
// return Err(crate::Error::FileNotFound(path));
|
||||||
|
// }
|
||||||
|
|
||||||
let canonical_paths = input_files.clone().map(Path::new).map(fs::canonicalize);
|
// eprintln!("{} {}", "[ERROR]".red(), err);
|
||||||
for (filename, canonical_path) in input_files.zip(canonical_paths.clone()) {
|
// return Err(crate::Error::IoError);
|
||||||
if let Err(err) = canonical_path {
|
// }
|
||||||
let path = PathBuf::from(filename);
|
// }
|
||||||
if !path.exists() {
|
|
||||||
return Err(crate::Error::FileNotFound(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
eprintln!("{} {}", "[ERROR]".red(), err);
|
// let input_files = canonical_paths.map(Result::unwrap).collect();
|
||||||
return Err(crate::Error::IoError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let input_files = canonical_paths.map(Result::unwrap).collect();
|
// Ok(Command {
|
||||||
|
// kind: CommandKind::Compression(input_files),
|
||||||
|
// output: Some(File {
|
||||||
|
// path: output_file.into(),
|
||||||
|
// contents_in_memory: None,
|
||||||
|
// extension: Some(output_file_extension.unwrap()),
|
||||||
|
// }),
|
||||||
|
// })
|
||||||
|
// } else {
|
||||||
|
// // Output not supplied
|
||||||
|
// // Checking if input files are decompressible
|
||||||
|
|
||||||
Ok(Command {
|
// let input_files = process_decompressible_input(input_files)?;
|
||||||
kind: CommandKind::Compression(input_files),
|
|
||||||
output: Some(File {
|
|
||||||
path: output_file.into(),
|
|
||||||
contents_in_memory: None,
|
|
||||||
extension: Some(output_file_extension.unwrap()),
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
// Output not supplied
|
|
||||||
// Checking if input files are decompressible
|
|
||||||
|
|
||||||
let input_files = process_decompressible_input(input_files)?;
|
// Ok(Command {
|
||||||
|
// kind: CommandKind::Decompression(input_files),
|
||||||
|
// output: Some(File {
|
||||||
|
// path: output_file.into(),
|
||||||
|
// contents_in_memory: None,
|
||||||
|
// extension: None,
|
||||||
|
// }),
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// // else: output file not supplied
|
||||||
|
// // Case 1: all input files are decompressible
|
||||||
|
// // Case 2: error
|
||||||
|
// let input_files = process_decompressible_input(input_files)?;
|
||||||
|
|
||||||
Ok(Command {
|
// Ok(Command {
|
||||||
kind: CommandKind::Decompression(input_files),
|
// kind: CommandKind::Decompression(input_files),
|
||||||
output: Some(File {
|
// output: None,
|
||||||
path: output_file.into(),
|
// })
|
||||||
contents_in_memory: None,
|
// }
|
||||||
extension: None,
|
// }
|
||||||
}),
|
// }
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// else: output file not supplied
|
|
||||||
// Case 1: all input files are decompressible
|
|
||||||
// Case 2: error
|
|
||||||
let input_files = process_decompressible_input(input_files)?;
|
|
||||||
|
|
||||||
Ok(Command {
|
pub fn parse_args_and_flags() -> crate::Result<Command> {
|
||||||
kind: CommandKind::Decompression(input_files),
|
let args: Vec<OsString> = env::args_os().skip(1).collect();
|
||||||
output: None,
|
|
||||||
|
if oof::matches_any_arg(&args, &["--help", "-h"]) {
|
||||||
|
return Ok(Command::ShowHelp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if oof::matches_any_arg(&args, &["--version"]) {
|
||||||
|
return Ok(Command::ShowHelp);
|
||||||
|
}
|
||||||
|
|
||||||
|
let subcommands = &["compress"];
|
||||||
|
|
||||||
|
let mut flags_info = vec![
|
||||||
|
flag!('y', "yes"),
|
||||||
|
flag!('n', "no"),
|
||||||
|
// flag!('v', "verbose"),
|
||||||
|
];
|
||||||
|
|
||||||
|
match oof::pop_subcommand(&mut args, subcommands) {
|
||||||
|
Some(&"compress") => {
|
||||||
|
let (args, flags) = oof::filter_flags(args, &flags_info)?;
|
||||||
|
let files = args.into_iter().map(PathBuf::from).collect();
|
||||||
|
|
||||||
|
todo!("Adicionar output_file, que é o files.pop() do fim");
|
||||||
|
Ok(Command::Compress { files, flags })
|
||||||
|
}
|
||||||
|
// Defaults to decompression when there is no subcommand
|
||||||
|
None => {
|
||||||
|
// Specific flag
|
||||||
|
flags_info.push(arg_flag!('o', "output_file"));
|
||||||
|
|
||||||
|
// Parse flags
|
||||||
|
let (args, flags) = oof::filter_flags(args, &flags_info)?;
|
||||||
|
|
||||||
|
let files = args.into_iter().map(PathBuf::from).collect();
|
||||||
|
let output_folder = flags.take_arg("output_folder").map(PathBuf::from);
|
||||||
|
|
||||||
|
Ok(Command::Decompress {
|
||||||
|
files,
|
||||||
|
output_folder,
|
||||||
|
flags,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
_ => unreachable!("You should match each subcommand passed."),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
21
src/error.rs
21
src/error.rs
@ -18,7 +18,7 @@ pub enum Error {
|
|||||||
InputsMustHaveBeenDecompressible(PathBuf),
|
InputsMustHaveBeenDecompressible(PathBuf),
|
||||||
InternalError,
|
InternalError,
|
||||||
CompressingRootFolder,
|
CompressingRootFolder,
|
||||||
WalkdirError
|
WalkdirError,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
@ -61,8 +61,17 @@ impl fmt::Display for Error {
|
|||||||
write!(f, "{} ", "[ERROR]".red())?;
|
write!(f, "{} ", "[ERROR]".red())?;
|
||||||
let spacing = " ";
|
let spacing = " ";
|
||||||
writeln!(f, "It seems you're trying to compress the root folder.")?;
|
writeln!(f, "It seems you're trying to compress the root folder.")?;
|
||||||
writeln!(f, "{}This is unadvisable since ouch does compressions in-memory.", spacing)?;
|
writeln!(
|
||||||
write!(f, "{}Use a more appropriate tool for this, such as {}.", spacing, "rsync".green())
|
f,
|
||||||
|
"{}This is unadvisable since ouch does compressions in-memory.",
|
||||||
|
spacing
|
||||||
|
)?;
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}Use a more appropriate tool for this, such as {}.",
|
||||||
|
spacing,
|
||||||
|
"rsync".green()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Error::InternalError => {
|
Error::InternalError => {
|
||||||
write!(f, "{} ", "[ERROR]".red())?;
|
write!(f, "{} ", "[ERROR]".red())?;
|
||||||
@ -108,3 +117,9 @@ impl From<walkdir::Error> for Error {
|
|||||||
Self::WalkdirError
|
Self::WalkdirError
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<oof::OofError> for Error {
|
||||||
|
fn from(err: oof::OofError) -> Self {
|
||||||
|
todo!("We need to implement this properly");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,7 +3,7 @@ use std::{ffi::OsStr, fs, io::Write, path::PathBuf};
|
|||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
cli::{Command, CommandKind, Flags},
|
cli::Command,
|
||||||
compressors::{
|
compressors::{
|
||||||
BzipCompressor, Compressor, Entry, GzipCompressor, LzmaCompressor, TarCompressor,
|
BzipCompressor, Compressor, Entry, GzipCompressor, LzmaCompressor, TarCompressor,
|
||||||
ZipCompressor,
|
ZipCompressor,
|
||||||
@ -230,8 +230,31 @@ impl Evaluator {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn evaluate(command: Command, flags: Flags) -> crate::Result<()> {
|
pub fn evaluate(command: Command) -> crate::Result<()> {
|
||||||
let output = command.output.clone();
|
// Compress {
|
||||||
|
// files: Vec<PathBuf>,
|
||||||
|
// flags: oof::Flags,
|
||||||
|
// },
|
||||||
|
// /// Files to be decompressed and their extensions
|
||||||
|
// Decompress {
|
||||||
|
// files: Vec<PathBuf>,
|
||||||
|
// output_folder: Option<PathBuf>,
|
||||||
|
// flags: oof::Flags,
|
||||||
|
// },
|
||||||
|
// ShowHelp,
|
||||||
|
// ShowVersion,
|
||||||
|
match command {
|
||||||
|
Command::Compress { files, flags } => {}
|
||||||
|
Command::Decompress {
|
||||||
|
files,
|
||||||
|
output_folder,
|
||||||
|
flags,
|
||||||
|
} => {
|
||||||
|
// for file in files { decompress }
|
||||||
|
}
|
||||||
|
Command::ShowHelp => todo!(),
|
||||||
|
Command::ShowVersion => todo!(),
|
||||||
|
}
|
||||||
|
|
||||||
match command.kind {
|
match command.kind {
|
||||||
CommandKind::Compression(files_to_compress) => {
|
CommandKind::Compression(files_to_compress) => {
|
||||||
|
@ -20,7 +20,6 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run() -> crate::Result<()> {
|
fn run() -> crate::Result<()> {
|
||||||
let matches = cli::get_matches();
|
let command = cli::parse_args_and_flags()?;
|
||||||
let (command, flags) = cli::parse_matches(matches)?;
|
Evaluator::evaluate(command)
|
||||||
Evaluator::evaluate(command, flags)
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user