mirror of
https://github.com/clap-rs/clap
synced 2024-11-10 14:54:15 +00:00
commit
bd704e0d4f
7 changed files with 142 additions and 41 deletions
17
CHANGELOG.md
17
CHANGELOG.md
|
@ -1,3 +1,20 @@
|
|||
<a name="v2.10.3"></a>
|
||||
### v2.10.3 (2016-08-25)
|
||||
|
||||
#### Features
|
||||
|
||||
* **Help:** adds new short hand way to use source formatting and ignore term width in help messages ([7dfdaf20](https://github.com/kbknapp/clap-rs/commit/7dfdaf200ebb5c431351a045b48f5e0f0d3f31db), closes [#625](https://github.com/kbknapp/clap-rs/issues/625))
|
||||
|
||||
#### Documentation
|
||||
|
||||
* **Term Width:** adds details about set_term_width(0) ([00b8205d](https://github.com/kbknapp/clap-rs/commit/00b8205d22639d1b54b9c453c55c785aace52cb2))
|
||||
|
||||
#### Bug Fixes
|
||||
|
||||
* **Unicode:** fixes two bugs where non-English characters were stripped or caused a panic with help wrapping ([763a5c92](https://github.com/kbknapp/clap-rs/commit/763a5c920e23efc74d190af0cb8b5dd714b2d67a), closes [#626](https://github.com/kbknapp/clap-rs/issues/626))
|
||||
|
||||
|
||||
|
||||
<a name="v2.10.2"></a>
|
||||
### v2.10.2 (2016-08-22)
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
|
||||
name = "clap"
|
||||
version = "2.10.2"
|
||||
version = "2.10.3"
|
||||
authors = ["Kevin K. <kbknapp@gmail.com>"]
|
||||
exclude = ["examples/*", "clap-test/*", "tests/*", "benches/*", "*.png", "clap-perf/*", "*.dot"]
|
||||
description = "A simple to use, efficient, and full featured Command Line Argument Parser"
|
||||
|
@ -19,7 +19,8 @@ ansi_term = { version = "~0.8.0", optional = true }
|
|||
strsim = { version = "~0.5.1", optional = true }
|
||||
yaml-rust = { version = "~0.3.2", optional = true }
|
||||
clippy = { version = "~0.0.79", optional = true }
|
||||
unicode-width = { version = "~0.1.3", optional = true }
|
||||
unicode-width = "~0.1.3"
|
||||
unicode-segmentation = "~0.1.2"
|
||||
term_size = { version = "~0.1.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
|
@ -30,7 +31,7 @@ default = ["suggestions", "color", "wrap_help"]
|
|||
suggestions = ["strsim"]
|
||||
color = ["ansi_term", "libc"]
|
||||
yaml = ["yaml-rust"]
|
||||
wrap_help = ["libc", "unicode-width", "term_size"]
|
||||
wrap_help = ["libc", "term_size"]
|
||||
lints = ["clippy", "nightly"]
|
||||
nightly = [] # for building with nightly and unstable features
|
||||
unstable = [] # for building with unstable features on stable Rust
|
||||
|
|
14
README.md
14
README.md
|
@ -39,6 +39,12 @@ Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc)
|
|||
|
||||
## What's New
|
||||
|
||||
Here's the highlights for v2.10.3
|
||||
|
||||
* Fixes a bug with non-English characters in help text wrapping, where the character is stripped or causes a panic
|
||||
* Fixes an issue with `strsim` which caused a panic in some scenarios
|
||||
* Adds a shorthand way to ignore help text wrapping and use source formatting (i.e. `App::set_term_width(0)`)
|
||||
|
||||
Here's the highlights for v2.10.2
|
||||
|
||||
* Fixes a critical bug where the help message is printed twice
|
||||
|
@ -59,9 +65,9 @@ Here's the highlights for v2.10.0
|
|||
|
||||
Here's the highlights for v2.9.3
|
||||
|
||||
* Adds the ability to generate completions to an `io::Write` object
|
||||
* Adds an `App::unset_setting` and `App::unset_settings`
|
||||
* Fixes bug where only first arg in list of `required_unless_one` is recognized
|
||||
* Adds the ability to generate completions to an `io::Write` object
|
||||
* Adds an `App::unset_setting` and `App::unset_settings`
|
||||
* Fixes bug where only first arg in list of `required_unless_one` is recognized
|
||||
* Fixes a typo bug `SubcommandsRequired`->`SubcommandRequired`
|
||||
|
||||
|
||||
|
@ -547,7 +553,7 @@ The following is a list of optional `clap` features:
|
|||
|
||||
* **"suggestions"**: Turns on the `Did you mean '--myoption'?` feature for when users make typos. (builds dependency `strsim`)
|
||||
* **"color"**: Turns on colored error messages. This feature only works on non-Windows OSs. (builds dependency `ansi-term` and `libc`)
|
||||
* **"wrap_help"**: Automatically detects terminal width and wraps long help text lines with proper indentation alignment (builds dependency `libc` and 'unicode-width')
|
||||
* **"wrap_help"**: Automatically detects terminal width and wraps long help text lines with proper indentation alignment (builds dependency `libc`, and `term_size`)
|
||||
* **"lints"**: This is **not** included by default and should only be used while developing to run basic lints against changes. This can only be used on Rust nightly. (builds dependency `clippy`)
|
||||
* **"debug"**: This is **not** included by default and should only be used while developing to display debugging information.
|
||||
* **"yaml"**: This is **not** included by default. Enables building CLIs from YAML documents. (builds dependency `yaml-rust`)
|
||||
|
|
|
@ -2,8 +2,10 @@ use std::io::{self, Cursor, Read, Write};
|
|||
use std::collections::BTreeMap;
|
||||
use std::fmt::Display;
|
||||
use std::cmp;
|
||||
use std::usize;
|
||||
|
||||
use vec_map::VecMap;
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
use errors::{Error, Result as ClapResult};
|
||||
|
||||
|
@ -21,17 +23,10 @@ mod term_size {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "wrap_help", not(target_os = "windows")))]
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
|
||||
use strext::_StrExt;
|
||||
|
||||
#[cfg(any(not(feature = "wrap_help"), target_os = "windows"))]
|
||||
fn str_width(s: &str) -> usize {
|
||||
s.len()
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "wrap_help", not(target_os = "windows")))]
|
||||
fn str_width(s: &str) -> usize {
|
||||
UnicodeWidthStr::width(s)
|
||||
}
|
||||
|
@ -102,7 +97,11 @@ impl<'a> Help<'a> {
|
|||
next_line_help: next_line_help,
|
||||
hide_pv: hide_pv,
|
||||
term_w: match term_w {
|
||||
Some(width) => width,
|
||||
Some(width) => if width == 0 {
|
||||
usize::MAX
|
||||
} else {
|
||||
width
|
||||
},
|
||||
None => term_size::dimensions().map_or(120, |(w, _)| w),
|
||||
},
|
||||
color: color,
|
||||
|
@ -458,33 +457,27 @@ impl<'a> Help<'a> {
|
|||
debug!("Enough space to wrap...");
|
||||
if longest_w < avail_chars {
|
||||
sdebugln!("Yes");
|
||||
let mut indices = vec![];
|
||||
let mut idx = 0;
|
||||
loop {
|
||||
idx += avail_chars - 1;
|
||||
if idx >= help.len() {
|
||||
break;
|
||||
let mut prev_space = 0;
|
||||
let mut j = 0;
|
||||
let mut i = 0;
|
||||
for (idx, g) in (&*help.clone()).grapheme_indices(true) {
|
||||
debugln!("iter;idx={},g={}", idx, g);
|
||||
if g != " " { continue; }
|
||||
if str_width(&help[j..idx]) < avail_chars {
|
||||
debugln!("Still enough space...");
|
||||
prev_space = idx;
|
||||
continue;
|
||||
}
|
||||
// 'a' arbitrary non space char
|
||||
if help.chars().nth(idx).unwrap_or('a') != ' ' {
|
||||
idx = find_idx_of_space(&*help, idx);
|
||||
}
|
||||
debugln!("Adding idx: {}", idx);
|
||||
debugln!("At {}: {:?}", idx, help.chars().nth(idx));
|
||||
indices.push(idx);
|
||||
if str_width(&help[idx..]) <= avail_chars {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i, idx) in indices.iter().enumerate() {
|
||||
debugln!("iter;i={},idx={}", i, idx);
|
||||
let j = idx + (2 * i);
|
||||
debugln!("Adding Newline...");
|
||||
j = prev_space + (2 * i);
|
||||
debugln!("i={},prev_space={},j={}", i, prev_space, j);
|
||||
debugln!("removing: {}", j);
|
||||
debugln!("at {}: {:?}", j, help.chars().nth(j));
|
||||
debugln!("char at {}: {}", j, &help[j..j]);
|
||||
help.remove(j);
|
||||
help.insert(j, '{');
|
||||
help.insert(j + 1, 'n');
|
||||
help.insert(j + 2, '}');
|
||||
i += 1;
|
||||
}
|
||||
} else {
|
||||
sdebugln!("No");
|
||||
|
|
|
@ -485,7 +485,7 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
}
|
||||
|
||||
/// Disables a single command, or [`SubCommand`], level setting.
|
||||
///
|
||||
///
|
||||
/// See [`AppSettings`] for a full list of possibilities and examples.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -522,10 +522,11 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
for s in settings {
|
||||
self.p.unset(*s);
|
||||
}
|
||||
self
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the terminal width at which to wrap help messages. Defaults to `120`.
|
||||
/// Sets the terminal width at which to wrap help messages. Defaults to `120`. Using `0` will
|
||||
/// ignore terminal widths and use source formatting.
|
||||
///
|
||||
/// `clap` automatically tries to determine the terminal width on Unix, Linux, and OSX if the
|
||||
/// `wrap_help` cargo "feature" has been used while compiling. If the terminal width cannot be
|
||||
|
|
|
@ -409,13 +409,13 @@ extern crate ansi_term;
|
|||
extern crate yaml_rust;
|
||||
#[cfg(any(feature = "wrap_help", feature = "color"))]
|
||||
extern crate libc;
|
||||
#[cfg(all(feature = "wrap_help", not(target_os = "windows")))]
|
||||
extern crate unicode_width;
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
extern crate vec_map;
|
||||
#[cfg(feature = "wrap_help")]
|
||||
extern crate term_size;
|
||||
extern crate unicode_segmentation;
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
pub use yaml_rust::YamlLoader;
|
||||
|
|
|
@ -3,7 +3,7 @@ extern crate regex;
|
|||
|
||||
include!("../clap-test.rs");
|
||||
|
||||
use clap::{App, SubCommand, ErrorKind};
|
||||
use clap::{App, SubCommand, ErrorKind, Arg};
|
||||
|
||||
static HELP: &'static str = "clap-test v1.4.8
|
||||
Kevin K. <kbknapp@gmail.com>
|
||||
|
@ -81,6 +81,45 @@ FLAGS:
|
|||
OPTIONS:
|
||||
-o, --option <scoption>... tests options";
|
||||
|
||||
static ISSUE_626_CUTOFF: &'static str = "ctest 0.1
|
||||
|
||||
USAGE:
|
||||
ctest [OPTIONS]
|
||||
|
||||
FLAGS:
|
||||
-h, --help Prints help information
|
||||
-V, --version Prints version information
|
||||
|
||||
OPTIONS:
|
||||
-c, --cafe <FILE> A coffeehouse, coffee shop, or café is an
|
||||
establishment which primarily serves hot
|
||||
coffee, related coffee beverages (e.g., café
|
||||
latte, cappuccino, espresso), tea, and other
|
||||
hot beverages. Some coffeehouses also serve cold
|
||||
beverages such as iced coffee and iced tea. Many
|
||||
cafés also serve some type of food, such as light
|
||||
snacks, muffins, or pastries.";
|
||||
|
||||
static ISSUE_626_PANIC: &'static str = "ctest 0.1
|
||||
|
||||
USAGE:
|
||||
ctest [OPTIONS]
|
||||
|
||||
FLAGS:
|
||||
-h, --help Prints help information
|
||||
-V, --version Prints version information
|
||||
|
||||
OPTIONS:
|
||||
-c, --cafe <FILE> La culture du café est très
|
||||
développée dans de
|
||||
nombreux pays à climat chaud
|
||||
d'Amérique, d'Afrique et
|
||||
d'Asie, dans des plantations qui
|
||||
sont cultivées pour les marchés
|
||||
d'exportation. Le café est souvent
|
||||
une contribution majeure aux
|
||||
exportations des régions productrices.";
|
||||
|
||||
#[test]
|
||||
fn help_short() {
|
||||
let m = App::new("test")
|
||||
|
@ -189,6 +228,14 @@ fn multi_level_sc_help() {
|
|||
test::check_err_output(app, "ctest help subcmd multi", MULTI_SC_HELP, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_wrap_help() {
|
||||
let app = App::new("ctest")
|
||||
.set_term_width(0)
|
||||
.help(MULTI_SC_HELP);
|
||||
test::check_err_output(app, "ctest --help", MULTI_SC_HELP, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn complex_subcommand_help_output() {
|
||||
let mut a = test::complex_app();
|
||||
|
@ -199,3 +246,39 @@ fn complex_subcommand_help_output() {
|
|||
sc.write_help(&mut help).ok().expect("failed to print help");
|
||||
assert_eq!(&*String::from_utf8(help).unwrap(), SC_HELP);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn issue_626_unicode_cutoff() {
|
||||
let app = App::new("ctest")
|
||||
.version("0.1")
|
||||
.set_term_width(70)
|
||||
.arg(Arg::with_name("cafe")
|
||||
.short("c")
|
||||
.long("cafe")
|
||||
.value_name("FILE")
|
||||
.help("A coffeehouse, coffee shop, or café is an establishment \
|
||||
which primarily serves hot coffee, related coffee beverages \
|
||||
(e.g., café latte, cappuccino, espresso), tea, and other hot \
|
||||
beverages. Some coffeehouses also serve cold beverages such as \
|
||||
iced coffee and iced tea. Many cafés also serve some type of \
|
||||
food, such as light snacks, muffins, or pastries.")
|
||||
.takes_value(true));
|
||||
test::check_err_output(app, "ctest --help", ISSUE_626_CUTOFF, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_626_panic() {
|
||||
let app = App::new("ctest")
|
||||
.version("0.1")
|
||||
.set_term_width(53)
|
||||
.arg(Arg::with_name("cafe")
|
||||
.short("c")
|
||||
.long("cafe")
|
||||
.value_name("FILE")
|
||||
.help("La culture du café est très développée dans de nombreux pays à climat chaud d'Amérique, \
|
||||
d'Afrique et d'Asie, dans des plantations qui sont cultivées pour les marchés d'exportation. \
|
||||
Le café est souvent une contribution majeure aux exportations des régions productrices.")
|
||||
.takes_value(true));
|
||||
test::check_err_output(app, "ctest --help", ISSUE_626_PANIC, false);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue