Enable wrap_help

This commit is contained in:
Andrew 2023-10-03 15:05:56 +13:00
parent 93e5d7c751
commit be89acc623
4 changed files with 93 additions and 95 deletions

11
Cargo.lock generated
View file

@ -125,6 +125,7 @@ dependencies = [
"bitflags", "bitflags",
"clap_lex", "clap_lex",
"strsim", "strsim",
"terminal_size",
] ]
[[package]] [[package]]
@ -596,6 +597,16 @@ dependencies = [
"winapi-util", "winapi-util",
] ]
[[package]]
name = "terminal_size"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237"
dependencies = [
"rustix",
"windows-sys",
]
[[package]] [[package]]
name = "typed-arena" name = "typed-arena"
version = "2.0.2" version = "2.0.2"

View file

@ -56,6 +56,7 @@ version = "1.7.0"
[dependencies.clap] [dependencies.clap]
optional = true optional = true
version = "4.3.8" version = "4.3.8"
features = ["wrap_help"]
[target.'cfg(windows)'.dependencies.glob] [target.'cfg(windows)'.dependencies.glob]
optional = true optional = true

View file

@ -9,10 +9,9 @@ Arguments:
Options: Options:
-o, --opt <level> -o, --opt <level>
Set the optimization level preset. The default level 2 is quite fast Set the optimization level preset. The default level 2 is quite fast and provides good
and provides good compression. Lower levels are faster, higher levels compression. Lower levels are faster, higher levels provide better compression, though
provide better compression, though with increasingly diminishing with increasingly diminishing returns.
returns.
0 => --zc 5 --fast (1 trial, determined heuristically) 0 => --zc 5 --fast (1 trial, determined heuristically)
1 => --zc 10 --fast (1 trial, determined heuristically) 1 => --zc 10 --fast (1 trial, determined heuristically)
@ -23,20 +22,19 @@ Options:
6 => --zc 12 -f 0-9 (10 trials) 6 => --zc 12 -f 0-9 (10 trials)
max => (stable alias for the max level) max => (stable alias for the max level)
Manually specifying a compression option (zc, f, etc.) will override Manually specifying a compression option (zc, f, etc.) will override the optimization
the optimization preset, regardless of the order you write the preset, regardless of the order you write the arguments.
arguments.
[default: 2] [default: 2]
-r, --recursive -r, --recursive
When directories are given as input, traverse the directory trees and When directories are given as input, traverse the directory trees and optimize all PNG
optimize all PNG files found (files with “.png” or “.apng” extension). files found (files with “.png” or “.apng” extension).
--dir <directory> --dir <directory>
Write output file(s) to <directory>. If the directory does not exist, Write output file(s) to <directory>. If the directory does not exist, it will be created.
it will be created. Note that this will not preserve the directory Note that this will not preserve the directory structure of the input files when used with
structure of the input files when used with '--recursive'. '--recursive'.
--out <file> --out <file>
Write output file to <file> Write output file to <file>
@ -63,17 +61,16 @@ Options:
CAUTION: 'all' will convert APNGs to standard PNGs. CAUTION: 'all' will convert APNGs to standard PNGs.
Note that 'bKGD', 'sBIT' and 'hIST' will be forcibly stripped if the Note that 'bKGD', 'sBIT' and 'hIST' will be forcibly stripped if the color type or bit
color type or bit depth is changed, regardless of any options set. depth is changed, regardless of any options set.
--keep <list> --keep <list>
Strip all metadata except in the comma-separated list Strip all metadata except in the comma-separated list
-a, --alpha -a, --alpha
Perform additional optimization on images with an alpha channel, by Perform additional optimization on images with an alpha channel, by altering the color
altering the color values of fully transparent pixels. This is values of fully transparent pixels. This is generally recommended for better compression,
generally recommended for better compression, but take care as this is but take care as this is technically a lossy transformation and may be unsuitable for some
technically a lossy transformation and may be unsuitable for some
applications. applications.
-i, --interlace <type> -i, --interlace <type>
@ -83,16 +80,14 @@ Options:
1 => Apply Adam7 interlacing on all images that are processed 1 => Apply Adam7 interlacing on all images that are processed
keep => Keep the existing interlacing type of each image keep => Keep the existing interlacing type of each image
Note that interlacing can add 25-50% to the size of an optimized Note that interlacing can add 25-50% to the size of an optimized image. Only use it if you
image. Only use it if you believe the benefits outweigh the costs for believe the benefits outweigh the costs for your use case.
your use case.
[default: 0] [default: 0]
--scale16 --scale16
Forcibly reduce 16-bit images to 8-bit. Reduction is performed by Forcibly reduce 16-bit images to 8-bit. Reduction is performed by scaling the values, such
scaling the values, such that e.g. 0x00FF is reduced to 0x01 rather that e.g. 0x00FF is reduced to 0x01 rather than 0x00.
than 0x00.
-v, --verbose... -v, --verbose...
Run in verbose mode (use twice to increase verbosity) Run in verbose mode (use twice to increase verbosity)
@ -101,9 +96,8 @@ Options:
Run in quiet mode Run in quiet mode
-f, --filters <list> -f, --filters <list>
Peform compression trials with each of the given filter types. You can Peform compression trials with each of the given filter types. You can specify a
specify a comma-separated list, or a range of values. E.g. '-f 0-3' is comma-separated list, or a range of values. E.g. '-f 0-3' is the same as '-f 0,1,2,3'.
the same as '-f 0,1,2,3'.
PNG delta filters (apply the same filter to every line) PNG delta filters (apply the same filter to every line)
0 => None (recommended to always include this filter) 0 => None (recommended to always include this filter)
@ -121,13 +115,13 @@ Options:
The default value depends on the optimization level preset. The default value depends on the optimization level preset.
--fast --fast
Perform a fast compression evaluation of each enabled filter, followed Perform a fast compression evaluation of each enabled filter, followed by a single main
by a single main compression trial of the best result. Recommended compression trial of the best result. Recommended if you have more filters enabled than
if you have more filters enabled than CPU cores. CPU cores.
--zc <level> --zc <level>
Deflate compression level (1-12) for main compression trials. The Deflate compression level (1-12) for main compression trials. The levels here are defined
levels here are defined by the libdeflate compression library. by the libdeflate compression library.
The default value depends on the optimization level preset. The default value depends on the optimization level preset.
@ -147,29 +141,27 @@ Options:
Do not perform any transformations and do not deinterlace by default. Do not perform any transformations and do not deinterlace by default.
--nz --nz
Do not recompress IDAT unless required due to transformations. Do not recompress IDAT unless required due to transformations. Recompression of other
Recompression of other compressed chunks (such as iCCP) will also be compressed chunks (such as iCCP) will also be disabled. Note that the combination of
disabled. Note that the combination of '--nx' and '--nz' will fully '--nx' and '--nz' will fully disable all optimization.
disable all optimization.
--fix --fix
Do not perform checksum validation of PNG chunks. This may allow some Do not perform checksum validation of PNG chunks. This may allow some files with errors to
files with errors to be processed successfully. be processed successfully.
--force --force
Write the output even if it is larger than the input Write the output even if it is larger than the input
-Z, --zopfli -Z, --zopfli
Use the much slower but stronger Zopfli compressor for main Use the much slower but stronger Zopfli compressor for main compression trials.
compression trials. Recommended use is with '-o max' and '--fast'. Recommended use is with '-o max' and '--fast'.
--timeout <secs> --timeout <secs>
Maximum amount of time, in seconds, to spend on optimizations. Oxipng Maximum amount of time, in seconds, to spend on optimizations. Oxipng will check the
will check the timeout before each transformation or compression timeout before each transformation or compression trial, and will stop trying to optimize
trial, and will stop trying to optimize the file if the timeout is the file if the timeout is exceeded. Note that this does not cut short any operations that
exceeded. Note that this does not cut short any operations that are are already in progress, so it is currently of limited effectiveness for large files with
already in progress, so it is currently of limited effectiveness for high compression levels.
large files with high compression levels.
-t, --threads <num> -t, --threads <num>
Set number of threads to use [default: num CPU cores] Set number of threads to use [default: num CPU cores]

View file

@ -35,9 +35,11 @@ use std::process::exit;
use std::time::Duration; use std::time::Duration;
fn main() { fn main() {
// Note: Long help descriptions should wrap at 70 characters (column 71) // Note: clap 'wrap_help' is enabled to automatically wrap lines according to terminal width.
// Indentation is 10 spaces, so this allows it to fit on an 80 character terminal // To keep things tidy though, short help descriptions should be no more than 54 characters,
// Short help descriptions should ideally be no more than 54 characters // so that they can fit on a single line in an 80 character terminal.
// Long help descriptions are soft wrapped here at 90 characters (column 91) but this does not
// affect output, it simply matches what is rendered when help is output to a file.
let matches = Command::new("oxipng") let matches = Command::new("oxipng")
.version(env!("CARGO_PKG_VERSION")) .version(env!("CARGO_PKG_VERSION"))
.author("Joshua Holmer <jholmer.in@gmail.com>") .author("Joshua Holmer <jholmer.in@gmail.com>")
@ -55,10 +57,9 @@ fn main() {
Arg::new("optimization") Arg::new("optimization")
.help("Optimization level (0-6, or max)") .help("Optimization level (0-6, or max)")
.long_help("\ .long_help("\
Set the optimization level preset. The default level 2 is quite fast Set the optimization level preset. The default level 2 is quite fast and provides good \
and provides good compression. Lower levels are faster, higher levels compression. Lower levels are faster, higher levels provide better compression, though \
provide better compression, though with increasingly diminishing with increasingly diminishing returns.
returns.
0 => --zc 5 --fast (1 trial, determined heuristically) 0 => --zc 5 --fast (1 trial, determined heuristically)
1 => --zc 10 --fast (1 trial, determined heuristically) 1 => --zc 10 --fast (1 trial, determined heuristically)
@ -69,9 +70,8 @@ returns.
6 => --zc 12 -f 0-9 (10 trials) 6 => --zc 12 -f 0-9 (10 trials)
max => (stable alias for the max level) max => (stable alias for the max level)
Manually specifying a compression option (zc, f, etc.) will override Manually specifying a compression option (zc, f, etc.) will override the optimization \
the optimization preset, regardless of the order you write the preset, regardless of the order you write the arguments.")
arguments.")
.short('o') .short('o')
.long("opt") .long("opt")
.value_name("level") .value_name("level")
@ -91,8 +91,8 @@ arguments.")
Arg::new("recursive") Arg::new("recursive")
.help("Recurse input directories, optimizing all PNG files") .help("Recurse input directories, optimizing all PNG files")
.long_help("\ .long_help("\
When directories are given as input, traverse the directory trees and When directories are given as input, traverse the directory trees and optimize all PNG \
optimize all PNG files found (files with .png or .apng extension).") files found (files with .png or .apng extension).")
.short('r') .short('r')
.long("recursive") .long("recursive")
.action(ArgAction::SetTrue), .action(ArgAction::SetTrue),
@ -101,9 +101,9 @@ optimize all PNG files found (files with “.png” or “.apng” extension).")
Arg::new("output_dir") Arg::new("output_dir")
.help("Write output file(s) to <directory>") .help("Write output file(s) to <directory>")
.long_help("\ .long_help("\
Write output file(s) to <directory>. If the directory does not exist, Write output file(s) to <directory>. If the directory does not exist, it will be created. \
it will be created. Note that this will not preserve the directory Note that this will not preserve the directory structure of the input files when used with \
structure of the input files when used with '--recursive'.") '--recursive'.")
.long("dir") .long("dir")
.value_name("directory") .value_name("directory")
.value_parser(value_parser!(PathBuf)) .value_parser(value_parser!(PathBuf))
@ -161,8 +161,8 @@ all => Strip all non-critical chunks
CAUTION: 'all' will convert APNGs to standard PNGs. CAUTION: 'all' will convert APNGs to standard PNGs.
Note that 'bKGD', 'sBIT' and 'hIST' will be forcibly stripped if the Note that 'bKGD', 'sBIT' and 'hIST' will be forcibly stripped if the color type or bit \
color type or bit depth is changed, regardless of any options set.", depth is changed, regardless of any options set.",
StripChunks::KEEP_SAFE StripChunks::KEEP_SAFE
.iter() .iter()
.map(|c| String::from_utf8_lossy(c)) .map(|c| String::from_utf8_lossy(c))
@ -184,10 +184,9 @@ color type or bit depth is changed, regardless of any options set.",
Arg::new("alpha") Arg::new("alpha")
.help("Perform additional alpha channel optimization") .help("Perform additional alpha channel optimization")
.long_help("\ .long_help("\
Perform additional optimization on images with an alpha channel, by Perform additional optimization on images with an alpha channel, by altering the color \
altering the color values of fully transparent pixels. This is values of fully transparent pixels. This is generally recommended for better compression, \
generally recommended for better compression, but take care as this is but take care as this is technically a lossy transformation and may be unsuitable for some \
technically a lossy transformation and may be unsuitable for some
applications.") applications.")
.short('a') .short('a')
.long("alpha") .long("alpha")
@ -203,9 +202,8 @@ Set the PNG interlacing type, where <type> is one of:
1 => Apply Adam7 interlacing on all images that are processed 1 => Apply Adam7 interlacing on all images that are processed
keep => Keep the existing interlacing type of each image keep => Keep the existing interlacing type of each image
Note that interlacing can add 25-50% to the size of an optimized Note that interlacing can add 25-50% to the size of an optimized image. Only use it if you \
image. Only use it if you believe the benefits outweigh the costs for believe the benefits outweigh the costs for your use case.")
your use case.")
.short('i') .short('i')
.long("interlace") .long("interlace")
.value_name("type") .value_name("type")
@ -217,9 +215,8 @@ your use case.")
Arg::new("scale16") Arg::new("scale16")
.help("Forcibly reduce 16-bit images to 8-bit") .help("Forcibly reduce 16-bit images to 8-bit")
.long_help("\ .long_help("\
Forcibly reduce 16-bit images to 8-bit. Reduction is performed by Forcibly reduce 16-bit images to 8-bit. Reduction is performed by scaling the values, such \
scaling the values, such that e.g. 0x00FF is reduced to 0x01 rather that e.g. 0x00FF is reduced to 0x01 rather than 0x00.")
than 0x00.")
.long("scale16") .long("scale16")
.action(ArgAction::SetTrue), .action(ArgAction::SetTrue),
) )
@ -243,9 +240,8 @@ than 0x00.")
Arg::new("filters") Arg::new("filters")
.help(format!("Filters to try (0-{}; see '--help' for details)", RowFilter::LAST)) .help(format!("Filters to try (0-{}; see '--help' for details)", RowFilter::LAST))
.long_help("\ .long_help("\
Peform compression trials with each of the given filter types. You can Peform compression trials with each of the given filter types. You can specify a \
specify a comma-separated list, or a range of values. E.g. '-f 0-3' is comma-separated list, or a range of values. E.g. '-f 0-3' is the same as '-f 0,1,2,3'.
the same as '-f 0,1,2,3'.
PNG delta filters (apply the same filter to every line) PNG delta filters (apply the same filter to every line)
0 => None (recommended to always include this filter) 0 => None (recommended to always include this filter)
@ -273,9 +269,9 @@ The default value depends on the optimization level preset.")
Arg::new("fast") Arg::new("fast")
.help("Use fast filter evaluation") .help("Use fast filter evaluation")
.long_help("\ .long_help("\
Perform a fast compression evaluation of each enabled filter, followed Perform a fast compression evaluation of each enabled filter, followed by a single main \
by a single main compression trial of the best result. Recommended compression trial of the best result. Recommended if you have more filters enabled than \
if you have more filters enabled than CPU cores.") CPU cores.")
.long("fast") .long("fast")
.action(ArgAction::SetTrue), .action(ArgAction::SetTrue),
) )
@ -283,8 +279,8 @@ if you have more filters enabled than CPU cores.")
Arg::new("compression") Arg::new("compression")
.help("Deflate compression level (1-12)") .help("Deflate compression level (1-12)")
.long_help("\ .long_help("\
Deflate compression level (1-12) for main compression trials. The Deflate compression level (1-12) for main compression trials. The levels here are defined \
levels here are defined by the libdeflate compression library. by the libdeflate compression library.
The default value depends on the optimization level preset.") The default value depends on the optimization level preset.")
.long("zc") .long("zc")
@ -328,10 +324,9 @@ Do not perform any transformations and do not deinterlace by default.")
Arg::new("no-recoding") Arg::new("no-recoding")
.help("Do not recompress unless transformations occur") .help("Do not recompress unless transformations occur")
.long_help("\ .long_help("\
Do not recompress IDAT unless required due to transformations. Do not recompress IDAT unless required due to transformations. Recompression of other \
Recompression of other compressed chunks (such as iCCP) will also be compressed chunks (such as iCCP) will also be disabled. Note that the combination of \
disabled. Note that the combination of '--nx' and '--nz' will fully '--nx' and '--nz' will fully disable all optimization.")
disable all optimization.")
.long("nz") .long("nz")
.action(ArgAction::SetTrue), .action(ArgAction::SetTrue),
) )
@ -339,8 +334,8 @@ disable all optimization.")
Arg::new("fix") Arg::new("fix")
.help("Disable checksum validation") .help("Disable checksum validation")
.long_help("\ .long_help("\
Do not perform checksum validation of PNG chunks. This may allow some Do not perform checksum validation of PNG chunks. This may allow some files with errors to \
files with errors to be processed successfully.") be processed successfully.")
.long("fix") .long("fix")
.action(ArgAction::SetTrue), .action(ArgAction::SetTrue),
) )
@ -354,8 +349,8 @@ files with errors to be processed successfully.")
Arg::new("zopfli") Arg::new("zopfli")
.help("Use the much slower but stronger Zopfli compressor") .help("Use the much slower but stronger Zopfli compressor")
.long_help("\ .long_help("\
Use the much slower but stronger Zopfli compressor for main Use the much slower but stronger Zopfli compressor for main compression trials. \
compression trials. Recommended use is with '-o max' and '--fast'.") Recommended use is with '-o max' and '--fast'.")
.short('Z') .short('Z')
.long("zopfli") .long("zopfli")
.action(ArgAction::SetTrue), .action(ArgAction::SetTrue),
@ -364,12 +359,11 @@ compression trials. Recommended use is with '-o max' and '--fast'.")
Arg::new("timeout") Arg::new("timeout")
.help("Maximum amount of time to spend on optimizations") .help("Maximum amount of time to spend on optimizations")
.long_help("\ .long_help("\
Maximum amount of time, in seconds, to spend on optimizations. Oxipng Maximum amount of time, in seconds, to spend on optimizations. Oxipng will check the \
will check the timeout before each transformation or compression timeout before each transformation or compression trial, and will stop trying to optimize \
trial, and will stop trying to optimize the file if the timeout is the file if the timeout is exceeded. Note that this does not cut short any operations that \
exceeded. Note that this does not cut short any operations that are are already in progress, so it is currently of limited effectiveness for large files with \
already in progress, so it is currently of limited effectiveness for high compression levels.")
large files with high compression levels.")
.value_name("secs") .value_name("secs")
.long("timeout") .long("timeout")
.value_parser(value_parser!(u64)), .value_parser(value_parser!(u64)),