mirror of
https://github.com/ouch-org/ouch.git
synced 2025-07-29 14:12:49 +00:00
Add --format flag to specify formats when compressing
This commit is contained in:
parent
fddc79628a
commit
ea1d3bf6bb
@ -10,7 +10,7 @@ use clap::Parser;
|
||||
use fs_err as fs;
|
||||
use once_cell::sync::OnceCell;
|
||||
|
||||
use crate::{Opts, QuestionPolicy, Subcommand};
|
||||
use crate::{error::FinalError, Opts, QuestionPolicy, Subcommand};
|
||||
|
||||
/// Whether to enable accessible output (removes info output and reduces other
|
||||
/// output, removes visual markers like '[' and ']').
|
||||
@ -26,6 +26,13 @@ impl Opts {
|
||||
pub fn parse_args() -> crate::Result<(Self, QuestionPolicy)> {
|
||||
let mut opts = Self::parse();
|
||||
|
||||
if opts.format.as_ref().map(String::is_empty).unwrap_or(false) {
|
||||
let error = FinalError::with_title("Given --format flag is empty")
|
||||
.hint("Try passing a supported extension, like --format tar.gz");
|
||||
|
||||
return Err(error.into());
|
||||
}
|
||||
|
||||
ACCESSIBLE.set(opts.accessible).unwrap();
|
||||
|
||||
let (Subcommand::Compress { files, .. }
|
||||
|
@ -46,7 +46,8 @@ fn represents_several_files(files: &[PathBuf]) -> bool {
|
||||
pub fn run(args: Opts, question_policy: QuestionPolicy) -> crate::Result<()> {
|
||||
match args.cmd {
|
||||
Subcommand::Compress { mut files, output: output_path } => {
|
||||
// If the output_path file exists and is the same as some of the input files, warn the user and skip those inputs (in order to avoid compression recursion)
|
||||
// If the output_path file exists and is the same as some of the input files, warn the
|
||||
// user and skip those inputs (in order to avoid compression recursion)
|
||||
if output_path.exists() {
|
||||
clean_input_files_if_needed(&mut files, &fs::canonicalize(&output_path)?);
|
||||
}
|
||||
@ -56,7 +57,15 @@ pub fn run(args: Opts, question_policy: QuestionPolicy) -> crate::Result<()> {
|
||||
}
|
||||
|
||||
// Formats from path extension, like "file.tar.gz.xz" -> vec![Tar, Gzip, Lzma]
|
||||
let mut formats = extension::extensions_from_path(&output_path);
|
||||
let mut formats = if let Some(format) = args.format {
|
||||
extension::from_format_text(&format).ok_or_else(|| {
|
||||
FinalError::with_title(format!("Cannot compress to '{}'.", to_utf(&output_path)))
|
||||
.detail("Supplied compression format is not valid")
|
||||
.hint("Check --help for all supported formats")
|
||||
})
|
||||
} else {
|
||||
Ok(extension::extensions_from_path(&output_path))
|
||||
}?;
|
||||
|
||||
if formats.is_empty() {
|
||||
let error = FinalError::with_title(format!("Cannot compress to '{}'.", to_utf(&output_path)))
|
||||
|
@ -102,8 +102,54 @@ impl fmt::Display for CompressionFormat {
|
||||
}
|
||||
}
|
||||
|
||||
// use crate::extension::CompressionFormat::*;
|
||||
//
|
||||
/// Returns the list of compression formats that correspond to the given extension text.
|
||||
///
|
||||
/// # Examples:
|
||||
/// - `"tar" => Some(&[Tar])`
|
||||
/// - `"tgz" => Some(&[Tar, Gzip])`
|
||||
///
|
||||
/// Note that the text given as input should not contain any dots, otherwise, None will be returned.
|
||||
pub fn compression_formats_from_text(extension: &str) -> Option<&'static [CompressionFormat]> {
|
||||
match extension {
|
||||
"tar" => Some(&[Tar]),
|
||||
"tgz" => Some(&[Tar, Gzip]),
|
||||
"tbz" | "tbz2" => Some(&[Tar, Bzip]),
|
||||
"tlz4" => Some(&[Tar, Lz4]),
|
||||
"txz" | "tlzma" => Some(&[Tar, Lzma]),
|
||||
"tsz" => Some(&[Tar, Snappy]),
|
||||
"tzst" => Some(&[Tar, Zstd]),
|
||||
"zip" => Some(&[Zip]),
|
||||
"bz" | "bz2" => Some(&[Bzip]),
|
||||
"gz" => Some(&[Gzip]),
|
||||
"lz4" => Some(&[Lz4]),
|
||||
"xz" | "lzma" => Some(&[Lzma]),
|
||||
"sz" => Some(&[Snappy]),
|
||||
"zst" => Some(&[Zstd]),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Grab a user given format, and parse it.
|
||||
///
|
||||
/// # Examples:
|
||||
/// - `"tar.gz" => Extension { ... [Tar, Gz] }`
|
||||
/// - `".tar.gz" => Extension { ... [Tar, Gz] }`
|
||||
pub fn from_format_text(format: &str) -> Option<Vec<Extension>> {
|
||||
let mut extensions = vec![];
|
||||
|
||||
// Ignore all dots, use filter to ignore dots at first and last char leaving empty pieces
|
||||
let extension_pieces = format.split('.').filter(|piece| !piece.is_empty());
|
||||
for piece in extension_pieces {
|
||||
let extension = match compression_formats_from_text(piece) {
|
||||
Some(formats) => Extension::new(formats, piece),
|
||||
None => return None,
|
||||
};
|
||||
extensions.push(extension);
|
||||
}
|
||||
|
||||
extensions.reverse();
|
||||
Some(extensions)
|
||||
}
|
||||
|
||||
/// Extracts extensions from a path,
|
||||
/// return both the remaining path and the list of extension objects
|
||||
@ -120,25 +166,10 @@ pub fn separate_known_extensions_from_name(mut path: &Path) -> (&Path, Vec<Exten
|
||||
|
||||
// While there is known extensions at the tail, grab them
|
||||
while let Some(extension) = path.extension().and_then(OsStr::to_str) {
|
||||
let formats: &[CompressionFormat] = match extension {
|
||||
"tar" => &[Tar],
|
||||
"tgz" => &[Tar, Gzip],
|
||||
"tbz" | "tbz2" => &[Tar, Bzip],
|
||||
"tlz4" => &[Tar, Lz4],
|
||||
"txz" | "tlzma" => &[Tar, Lzma],
|
||||
"tsz" => &[Tar, Snappy],
|
||||
"tzst" => &[Tar, Zstd],
|
||||
"zip" => &[Zip],
|
||||
"bz" | "bz2" => &[Bzip],
|
||||
"gz" => &[Gzip],
|
||||
"lz4" => &[Lz4],
|
||||
"xz" | "lzma" => &[Lzma],
|
||||
"sz" => &[Snappy],
|
||||
"zst" => &[Zstd],
|
||||
_ => break,
|
||||
let extension = match compression_formats_from_text(extension) {
|
||||
Some(formats) => Extension::new(formats, extension),
|
||||
None => break,
|
||||
};
|
||||
|
||||
let extension = Extension::new(formats, extension);
|
||||
extensions.push(extension);
|
||||
|
||||
// Update for the next iteration
|
||||
|
@ -20,6 +20,10 @@ pub struct Opts {
|
||||
pub no: bool,
|
||||
|
||||
/// Activate accessibility mode, reducing visual noise
|
||||
#[clap(short = 'f', long)]
|
||||
pub format: Option<String>,
|
||||
|
||||
/// Ignore autodetection, specifying
|
||||
#[clap(short = 'A', long, env = "ACCESSIBLE")]
|
||||
pub accessible: bool,
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user