impl<'app> App<'app> {
fn _build_helper(&mut self) {
if self.helper.is_built {
return;
} else {
self.helper.is_built = true;
}
self.helper.helps.version = self._ver(1);
self.helper.helps.author = self._help_author(3);
self.helper.helps.addrs = self._help_address(3);
let sub_cmds = self._help_sub_cmds(3, 5);
self.helper.helps.sub_cmds = if sub_cmds.is_empty() {
sub_cmds
} else {
format!("CAMMANDS:\n{}", sub_cmds)
};
for (k, v) in &self.cmds {
let cmd_name = v.name.map(|s| s.to_string());
let info = self._help_info(v.name, k, 1);
self.helper.helps.cmd_infos.insert(cmd_name.clone(), info);
let usage = self._help_usage(v.name, k, 3);
self.helper.helps.cmd_usages.insert(cmd_name.clone(), usage);
if !v.opts.is_empty() {
self.helper.helps.cmd_options.insert(
cmd_name.clone(),
format!("OPTIONS:\n{}", v.to_opts_info().to_string(3, 5)),
);
}
if !v.args.is_empty() {
self.helper.helps.cmd_args.insert(
cmd_name.clone(),
format!("ARGS:\n{}", v.to_args_info().to_string(3, 5)),
);
}
}
}
fn _ver(&self, blanks0: usize) -> String {
format!(
"{}{}{}",
self.helper.name.trim(),
blanks_fix(blanks0),
self.helper.version.trim()
)
}
fn _help_info(&self, cmd_name: Option<&str>, cmd_key: &Option<String>, blanks0: usize) -> String {
let version_or_subcmd = cmd_name.unwrap_or_else(|| self.helper.version()).trim();
format!(
"{}{}{}\n{}",
self.helper.name.trim(),
blanks_fix(blanks0),
version_or_subcmd,
self.cmds[cmd_key].desc.trim()
)
}
fn _help_author(&self, blanks0: usize) -> String {
let mut authors = String::new();
for &(ref author, ref email) in &self.helper.authors {
authors.push_str(&format!("{}{} <{}>\n", blanks_fix(blanks0), author, email));
}
authors
}
fn _help_address(&self, blanks0: usize) -> String {
let mut authors = String::new();
for &(ref author, ref email) in &self.helper.addrs {
authors.push_str(&format!("{}{}: {}\n", blanks_fix(blanks0), author, email));
}
authors
}
fn _help_sub_cmds(&self, blanks0: usize, blanks1: usize) -> String {
let mut cammands = String::new();
let mut max_len = 0;
let mut vs: Vec<String> = vec![];
self.cmds
.values()
.map(|cmd| if cmd.name != None {
let s = cmd.name.unwrap().to_string() + &cmd.short.map(|ss| ", ".to_owned() + ss).unwrap_or_default();
if s.len() > max_len {
max_len = s.len()
}
vs.push(s);
})
.count();
let mut it = vs.iter();
self.cmds
.values()
.map(|cmd| if cmd.name != None {
let name_ = it.next().unwrap();
let mut s_tmp = String::default();
for (idx, line) in cmd.desc.lines().enumerate() {
if idx == 0 {
s_tmp.push_str(&format!(
"{}{}{}{}\n",
blanks_fix(blanks0),
name_,
blanks_fix(blanks1 + max_len - name_.len()),
line
));
} else {
s_tmp.push_str(&format!("{}{}\n", blanks_fix(blanks0+blanks1+max_len), line));
}
}
cammands.push_str(&s_tmp);
})
.count();
cammands
}
fn _help_usage(&self, cmd_name: Option<&str>, cmd_key: &Option<String>, blanks0: usize) -> String {
let pkg = &self.helper.name;
let none_or_cmdname = cmd_name.map(|s| " ".to_owned() + s).unwrap_or_default();
let cmd = &self.cmds[cmd_key];
let mut usages = Vec::new();
let mut option_optional = false;
let mut argss = " ".to_owned();
cmd.opts
.values()
.map(|opt| if opt.optional ||
opt.value.as_ref().default().is_some()
{
option_optional = true;
})
.count();
cmd.args
.as_slice()
.iter()
.map(|args| {
let mut fmt_ = if args.len == Some(1) {
format!("<{}>", args.name)
} else if args.len == Some(2) {
format!("<{}> <{}>", args.name, args.name)
} else if args.len == None {
format!("<{}>...", args.name)
} else {
format!("<{}>{{{}}}", args.name, args.len.as_ref().unwrap())
};
if args.optional || args.value.as_ref().default().is_some() {
fmt_ = format!("[{}] ", fmt_);
} else {
fmt_.push(' ');
}
argss.push_str(&fmt_);
})
.count();
if option_optional {
usages.push(format!(
"{}{} [options] {}",
pkg,
none_or_cmdname,
argss.trim()
));
} else {
usages.push(format!(
"{}{} options {}",
pkg,
none_or_cmdname,
argss.trim()
));
}
if cmd_name == None && self.cmds.len() > 1 {
usages.push(format!("{} <command> [args]", pkg));
}
usages.as_mut_slice().sort_by(|a, b| a.len().cmp(&b.len()));
let mut help = "USAGE:\n".to_owned();
usages
.as_slice()
.iter()
.map(|s| {
help.push_str(&format!("{}{}\n", blanks_fix(blanks0), s))
})
.count();
help
}
}
struct OptInfo(String, String);
impl<'app> Opt<'app> {
fn to_info(&self) -> OptInfo {
let optional_or_dafault = if self.is_optional() {
statics::optional_get().to_owned()
} else {
self.value
.as_ref()
.default()
.map(|s| format!("[{}]", s))
.unwrap_or_else(String::new)
};
let s = self.short_get().unwrap_or_else(String::new);
let long = self.long_get().unwrap_or_else(String::new);
let tmp_ = if self.is_bool() {
if s != "" && long != "" {
format!("{}, {} ", s, long)
} else {
format!("{}{} ", long, s)
}
} else if s != "" && long != "" {
format!("{}, {} <{}>{} ", s, long, self.name, optional_or_dafault)
} else {
format!("{}{} <{}>{} ", s, long, self.name, optional_or_dafault)
};
OptInfo(tmp_, self.help.to_string())
}
}
struct OptsInfo(Vec<OptInfo>);
impl<'app> Cmd<'app> {
fn to_opts_info(&self) -> OptsInfo {
let mut vs = Vec::new();
for v in self.opts.values() {
vs.push(v.to_info());
}
OptsInfo(vs)
}
}
impl OptsInfo {
fn to_string(&self, blanks0: usize, mut blanks1: usize) -> String {
let mut max_len = 0;
for val in &self.0 {
if val.0.len() > max_len {
max_len = val.0.len();
}
}
blanks1 += max_len;
let blanks0 = blanks_fix(blanks0);
let mut s_tmp = String::new();
for val in &self.0 {
for (idx, line) in val.1.lines().enumerate() {
if idx == 0 {
s_tmp.push_str(&format!(
"{}{}{}{}\n",
blanks0,
val.0,
blanks_fix(blanks1 - val.0.len()),
line
));
} else {
s_tmp.push_str(&format!("{}{}{}\n", blanks0, blanks_fix(blanks1), line));
}
}
}
s_tmp
}
}
fn blanks_fix(len: usize) -> String {
let mut s_tmp = String::new();
for _ in 0..len {
s_tmp.push(' ');
}
s_tmp
}
struct ArgsInfo(String, String);
struct ArgssInfo(Vec<ArgsInfo>);
impl<'app> Cmd<'app> {
fn to_args_info(&self) -> ArgssInfo {
let mut vs = Vec::new();
for v in &self.args {
let optional_or_dafault = if v.is_optional() {
statics::optional_get().to_owned()
} else {
v.value
.as_ref()
.default()
.clone()
.unwrap_or_else(String::new)
};
vs.push(ArgsInfo(
format!("<{}>{}", v.name, optional_or_dafault),
v.help.to_string(),
));
}
ArgssInfo(vs)
}
}
impl ArgssInfo {
fn to_string(&self, blanks0: usize, mut blanks1: usize) -> String {
let mut max_len = 0;
for val in &self.0 {
if val.0.len() > max_len {
max_len = val.0.len();
}
}
blanks1 += max_len;
let blanks0 = blanks_fix(blanks0);
let mut s_tmp = String::new();
for val in &self.0 {
for (idx, line) in val.1.lines().enumerate() {
if idx == 0 {
s_tmp.push_str(&format!(
"{}{}{}{}\n",
blanks0,
val.0,
blanks_fix(blanks1 - val.0.len()),
line
));
} else {
s_tmp.push_str(&format!("{}{}{}\n", blanks0, blanks_fix(blanks1), line));
}
}
}
s_tmp
}
}