···131131| `.txz` | `.tar.xz` |
132132| `.tzst` | `.tar.zst` |
133133134134+You can also pass a compound format as the leading argument (like the `tar` subcommand) to make it explicit, without writing out a target filename:
135135+136136+```bash
137137+# Compress a directory to directory.tar.gz
138138+cmprss tar.gz directory
139139+140140+# Same, using the shortcut form
141141+cmprss tgz directory out.tgz
142142+```
143143+134144Pipes can still be used if preferred:
135145136146```bash
+12
src/backends/mod.rs
···6363 _ => compressor_from_str(ext).map(|c| vec![c]),
6464 }
6565}
6666+6767+/// Resolve a dotted format string (e.g. `tar.gz`, `tgz`, `xz`) into a
6868+/// compressor chain. Every dot-separated segment is resolved via
6969+/// `chain_from_ext` and concatenated in order. Returns `None` if any
7070+/// segment isn't a known codec or shortcut.
7171+pub fn chain_from_format_str(s: &str) -> Option<Vec<Box<dyn Compressor>>> {
7272+ let mut chain = Vec::new();
7373+ for part in s.split('.') {
7474+ chain.extend(chain_from_ext(part)?);
7575+ }
7676+ if chain.is_empty() { None } else { Some(chain) }
7777+}
+20-1
src/main.rs
···7878 Manpage,
7979}
80808181+/// If the first positional arg looks like a dotted format string (e.g.
8282+/// `tar.gz`, `tgz`) and isn't an existing path on disk, remove it from
8383+/// `io_list` and return the equivalent compressor chain. This gives the
8484+/// compound formats the same ergonomic treatment as the `tar` subcommand
8585+/// without cluttering `--help` with every permutation.
8686+fn take_format_prefix(io_list: &mut Vec<String>) -> Option<Box<dyn Compressor>> {
8787+ let first = io_list.first()?;
8888+ if std::path::Path::new(first).exists() {
8989+ return None;
9090+ }
9191+ let chain = chain_from_format_str(first)?;
9292+ io_list.remove(0);
9393+ Some(Box::new(Pipeline::new(chain)))
9494+}
9595+8196fn write_completions(shell: Shell) -> Result {
8297 let mut cmd = CmprssArgs::command();
8398 clap_complete::generate(shell, &mut cmd, "cmprss", &mut std::io::stdout());
···115130 Some(Format::SevenZ(a)) => command(Some(Box::new(SevenZ::new(&a))), &a.common_args),
116131 Some(Format::Completions { shell }) => write_completions(shell),
117132 Some(Format::Manpage) => write_manpage(),
118118- None => command(None, &args.base_args),
133133+ None => {
134134+ let mut base_args = args.base_args;
135135+ let compressor = take_format_prefix(&mut base_args.io_list);
136136+ command(compressor, &base_args)
137137+ }
119138 }
120139 .unwrap_or_else(|e| {
121140 eprintln!("ERROR(cmprss): {}", e);