Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stop the leaks #867

Merged
merged 11 commits into from
Feb 21, 2017
24 changes: 14 additions & 10 deletions src/app/help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,18 +384,21 @@ impl<'a> Help<'a> {
debugln!("Help::write_before_after_help;");
let mut help = String::new();
// determine if our help fits or needs to wrap
debugln!("Help::write_before_after_help: Term width...{}", self.term_w);
debugln!("Help::write_before_after_help: Term width...{}",
self.term_w);
let too_long = str_width(h) >= self.term_w;

debug!("Help::write_before_after_help: Too long...");
if too_long || h.contains("{n}") {
sdebugln!("Yes");
help.push_str(h);
debugln!("Help::write_before_after_help: help: {}", help);
debugln!("Help::write_before_after_help: help width: {}", str_width(&*help));
debugln!("Help::write_before_after_help: help width: {}",
str_width(&*help));
// Determine how many newlines we need to insert
debugln!("Help::write_before_after_help: Usable space: {}", self.term_w);
let longest_w = find_longest!(help);
debugln!("Help::write_before_after_help: Usable space: {}",
self.term_w);
let longest_w = find_longest!(help);
help = help.replace("{n}", "\n");
wrap_help(&mut help, longest_w, self.term_w);
} else {
Expand Down Expand Up @@ -451,7 +454,7 @@ impl<'a> Help<'a> {
// Determine how many newlines we need to insert
let avail_chars = self.term_w - spcs;
debugln!("Help::help: Usable space...{}", avail_chars);
let longest_w = find_longest!(help);
let longest_w = find_longest!(help);
help = help.replace("{n}", "\n");
wrap_help(&mut help, longest_w, avail_chars);
} else {
Expand Down Expand Up @@ -491,12 +494,12 @@ impl<'a> Help<'a> {
debugln!("Help::spec_vals: a={}", a);
let mut spec_vals = vec![];
if let Some(pv) = a.default_val() {
debugln!("Help::spec_vals: Found default value...[{}]", pv);
debugln!("Help::spec_vals: Found default value...[{:?}]", pv);
spec_vals.push(format!(" [default: {}]",
if self.color {
self.cizer.good(pv)
self.cizer.good(pv.to_string_lossy())
} else {
Format::None(pv)
Format::None(pv.to_string_lossy())
}));
}
if let Some(ref aliases) = a.aliases() {
Expand Down Expand Up @@ -938,7 +941,8 @@ fn wrap_help(help: &mut String, longest_w: usize, avail_chars: usize) {
debugln!("Help::wrap_help:iter: idx={}, g={}", idx, g);
if g == "\n" {
debugln!("Help::wrap_help:iter: Newline found...");
debugln!("Help::wrap_help:iter: Still space...{:?}", str_width(&help[j..idx]) < avail_chars);
debugln!("Help::wrap_help:iter: Still space...{:?}",
str_width(&help[j..idx]) < avail_chars);
if str_width(&help[j..idx]) < avail_chars {
j = idx;
continue;
Expand All @@ -957,7 +961,7 @@ fn wrap_help(help: &mut String, longest_w: usize, avail_chars: usize) {
j = prev_space;
debugln!("Help::wrap_help:iter: prev_space={}, j={}", prev_space, j);
debugln!("Help::wrap_help:iter: Removing...{}", j);
debugln!("Help::wrap_help:iter: Char at {}: {:?}", j, &help[j..j+1]);
debugln!("Help::wrap_help:iter: Char at {}: {:?}", j, &help[j..j + 1]);
help.remove(j);
help.insert(j, '\n');
prev_space = idx;
Expand Down
47 changes: 22 additions & 25 deletions src/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ use yaml_rust::Yaml;
// Internal
use app::help::Help;
use app::parser::Parser;
use args::{ArgKind, AnyArg, Arg, ArgGroup, ArgMatcher, ArgMatches, ArgSettings};
use errors::Error;
use args::{AnyArg, Arg, ArgGroup, ArgMatcher, ArgMatches, ArgSettings};
use errors::Result as ClapResult;
pub use self::settings::AppSettings;
use completions::Shell;
Expand Down Expand Up @@ -1268,7 +1267,21 @@ impl<'a, 'b> App<'a, 'b> {
{
self.get_matches_from_safe_borrow(itr).unwrap_or_else(|e| {
// Otherwise, write to stderr and exit
self.maybe_wait_for_exit(e);
if e.use_stderr() {
wlnerr!("{}", e.message);
if self.p.is_set(AppSettings::WaitOnError) {
wlnerr!("\nPress [ENTER] / [RETURN] to continue...");
let mut s = String::new();
let i = io::stdin();
i.lock().read_line(&mut s).unwrap();
}
drop(self);
drop(e);
process::exit(1);
}

drop(self);
e.exit()
})
}

Expand Down Expand Up @@ -1373,29 +1386,12 @@ impl<'a, 'b> App<'a, 'b> {

if self.p.is_set(AppSettings::PropagateGlobalValuesDown) {
for a in &self.p.global_args {
matcher.propagate(a.name);
matcher.propagate(a.b.name);
}
}

Ok(matcher.into())
}

// Re-implements ClapError::exit except it checks if we should wait for input before exiting
// since ClapError doesn't have that info and the error message must be printed before exiting
fn maybe_wait_for_exit(&self, e: Error) -> ! {
if e.use_stderr() {
wlnerr!("{}", e.message);
if self.p.is_set(AppSettings::WaitOnError) {
wlnerr!("\nPress [ENTER] / [RETURN] to continue...");
let mut s = String::new();
let i = io::stdin();
i.lock().read_line(&mut s).unwrap();
}
process::exit(1);
}

e.exit()
}
}

#[cfg(feature = "yaml")]
Expand Down Expand Up @@ -1536,14 +1532,13 @@ impl<'n, 'e> AnyArg<'n, 'e> for App<'n, 'e> {
unreachable!("App struct does not support AnyArg::name, this is a bug!")
}
fn id(&self) -> usize { self.p.id }
fn kind(&self) -> ArgKind { ArgKind::Subcmd }
fn overrides(&self) -> Option<&[&'e str]> { None }
fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]> { None }
fn blacklist(&self) -> Option<&[&'e str]> { None }
fn required_unless(&self) -> Option<&[&'e str]> { None }
fn val_names(&self) -> Option<&VecMap<&'e str>> { None }
fn is_set(&self, _: ArgSettings) -> bool { false }
fn val_terminator(&self) -> Option<&'e str> {None}
fn val_terminator(&self) -> Option<&'e str> { None }
fn set(&mut self, _: ArgSettings) {
unreachable!("App struct does not support AnyArg::set, this is a bug!")
}
Expand All @@ -1559,8 +1554,10 @@ impl<'n, 'e> AnyArg<'n, 'e> for App<'n, 'e> {
fn val_delim(&self) -> Option<char> { None }
fn takes_value(&self) -> bool { true }
fn help(&self) -> Option<&'e str> { self.p.meta.about }
fn default_val(&self) -> Option<&'n str> { None }
fn default_vals_ifs(&self) -> Option<vec_map::Values<(&'n str, Option<&'e str>, &'e str)>> {None}
fn default_val(&self) -> Option<&'e OsStr> { None }
fn default_vals_ifs(&self) -> Option<vec_map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>> {
None
}
fn longest_filter(&self) -> bool { true }
fn aliases(&self) -> Option<Vec<&'e str>> {
if let Some(ref aliases) = self.p.meta.aliases {
Expand Down
Loading