feat: Add list-formats command and central format registry
Closes #859
This PR addresses several CLI user experience issues related to discovering supported formats by introducing a central format registry and a new list-formats subcommand. The previous approach had inconsistent, out-of-date, and context-unaware hints for formats.
The Problem
As detailed in issue #859, there were three core problems:
- No straightforward way to list supported formats from the CLI.
- Hints for the
--formatflag did not distinguish between compression and decompression capabilities. - The hardcoded hint lists were out of date with the actual supported formats.
These issues stemmed from the lack of a single source of truth for format information.
The Solution
This PR implements the suggestions from the issue by making format information a central, authoritative part of the application.
-
Central Format Registry (
src/formats.rs) A new module,src/formats.rs, now acts as the single source of truth. It defines every supported format, its extensions and aliases, its role (archive vs. compressor), and its capabilities (compress/decompress). This eliminates hardcoded lists and prevents future drift between documentation, hints, and application logic. -
New
list-formatsSubcommand A new subcommandouch list-formats(with aliasesformatsandsupport) has been added. It prints a detailed, beautifully formatted table of all supported formats and their capabilities, generated directly from the new registry. -
Smarter, Context-Aware Hints Error messages are now much more helpful. The logic distinguishes between two types of errors:
- Missing Format: If a format is missing entirely (e.g.,
ouch compress file output), the hint is highly specific to the command being run, showing only the formats that support compression. - Invalid Format: If an invalid format is passed via
--format(e.g.,ouch decompress file --format asd), the tool assumes the user might be confused about general capabilities, so it provides broader guidance by showing two separate, clearly labeled lists for all supported compression and decompression formats.
- Missing Format: If a format is missing entirely (e.g.,
-
Code Refactoring The
extension.rsanderror.rsmodules have been refactored to consume information from the newformats.rsregistry, ensuring consistency across the entire application.
Benefits of the New list-formats Command
The new ouch list-formats command provides a comprehensive and easy-to-understand overview of all supported formats, empowering users to understand and use ouch more effectively.
-
Clarifies Format Roles: The
ROLEcolumn immediately teaches the user the crucial difference between anarchive(a container for multiple files, liketarorzip) and acompressor(an algorithm that works on a single stream of data). This helps users understand why they needtarto compress a directory. -
Shows Explicit Capabilities: The
COMPRESSandDECOMPRESScolumns remove all guesswork. Users can see at a glance that, for example,ouchcan decompress.rarfiles but cannot create them, or that.lzmadecompression is supported but compression is not. -
Demystifies Shorthands: The separate shorthands table clearly shows how convenient aliases like
tgzexpand to their fulltar.gzequivalent, distinguishing them from single-format extensions.
New CLI Output
Here are some examples of the new and improved output.
1. The list-formats command output:
Note: The layout is responsive. The capabilities and shorthands tables will appear side-by-side on wide terminals, or stacked vertically on narrow ones.
ROLE column:
• archive — holds multiple files in one container (e.g., tar, zip, 7z)
• compressor — compresses a single stream; use with 'tar' for directories Shorthand chains (left → expands to right).
These are filename shortcuts only.
COMPRESS / DECOMPRESS columns show what this tool supports for each format. Example: 'tgz' expands to 'tar.gz'.
┌────────┬─────────────┬─────────────┬──────────┬────────────┬─────────────────────────────────┐ ┌───────────┬────────────┐
│ FORMAT ┆ LONG NAME ┆ ROLE ┆ COMPRESS ┆ DECOMPRESS ┆ NOTES │ │ SHORTHAND ┆ EXPANDS TO │
╞════════╪═════════════╪═════════════╪══════════╪════════════╪═════════════════════════════════╡ ╞═══════════╪════════════╡
│ tar ┆ Tar ┆ archive ┆ yes ┆ yes ┆ │ │ tgz ┆ tar.gz │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ zip ┆ ZIP ┆ archive ┆ yes ┆ yes ┆ cannot be streamed when chained │ │ tbz ┆ tar.bz2 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ rar ┆ RAR ┆ archive ┆ no ┆ yes ┆ │ │ tbz2 ┆ tar.bz2 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 7z ┆ 7-Zip ┆ archive ┆ yes ┆ yes ┆ cannot be streamed when chained │ │ tbz3 ┆ tar.bz3 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ gz ┆ Gzip ┆ compressor ┆ yes ┆ yes ┆ │ │ tlz4 ┆ tar.lz4 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ bz2/bz ┆ Bzip2 ┆ compressor ┆ yes ┆ yes ┆ │ │ txz ┆ tar.xz │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ bz3 ┆ Bzip3 ┆ compressor ┆ yes ┆ yes ┆ │ │ tlzma ┆ tar.lzma │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ xz ┆ XZ (LZMA2) ┆ compressor ┆ yes ┆ yes ┆ │ │ tlz ┆ tar.lz │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ lzma ┆ LZMA (v1) ┆ compressor ┆ no ┆ yes ┆ │ │ tsz ┆ tar.sz │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ lz ┆ Lzip ┆ compressor ┆ no ┆ yes ┆ │ │ tzst ┆ tar.zst │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ └───────────┴────────────┘
│ lz4 ┆ LZ4 ┆ compressor ┆ yes ┆ yes ┆ │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ sz ┆ Snappy (sz) ┆ compressor ┆ yes ┆ yes ┆ │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ zst ┆ Zstandard ┆ compressor ┆ yes ┆ yes ┆ │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ br ┆ Brotli ┆ compressor ┆ yes ┆ yes ┆ │
└────────┴─────────────┴─────────────┴──────────┴────────────┴─────────────────────────────────┘
2. Context-aware hint for a missing compression format:
[ERROR] Cannot compress to 'output'.
- You shall supply the compression format
hint: Try adding supported extensions (see --help):
hint: ouch compress <FILES>... output.tar.gz
hint: ouch compress <FILES>... output.zip
hint:
hint: Alternatively, you can overwrite this option by using the '--format' flag:
hint: ouch compress <FILES>... output --format tar.gz
hint: Supported extensions for compression are: tar, zip, 7z, gz, bz2, bz3, xz, lz4, sz, zst, br
hint: Supported aliases are: tgz, tbz, tbz2, tbz3, tlz4, txz, tlzma, tlz, tsz, tzst
hint: For detailed capabilities and notes, run: ouch list-formats
3. General hint for an invalid format provided via flag:
[ERROR] Failed to parse `--format asd`
- Unsupported extension 'asd'
hint: Supported extensions for compression are: tar, zip, 7z, gz, bz2, bz3, xz, lz4, sz, zst, br
hint: Supported extensions for decompression are: tar, zip, rar, 7z, gz, bz2, bz3, xz, lzma, lz, lz4, sz, zst, br
hint: Supported aliases are: tgz, tbz, tbz2, tbz3, tlz4, txz, tlzma, tlz, tsz, tzst
hint: For detailed capabilities and notes, run: ouch list-formats
hint:
hint: Examples:
hint: --format tar
hint: --format gz
hint: --format tar.gz