Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
CreepySkeleton committed Mar 9, 2020
1 parent c192f5e commit bb0eab8
Show file tree
Hide file tree
Showing 14 changed files with 298 additions and 114 deletions.
9 changes: 6 additions & 3 deletions clap_generate/src/generators/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,9 @@ pub trait Generator {
fn flags<'b>(p: &'b App<'b>) -> Vec<Arg> {
debugln!("flags: name={}", p.name);

let mut flags: Vec<_> = flags!(p).cloned().collect();
let mut flags: Vec<_> = p.view().flags().cloned().collect();

if flags.iter().find(|x| x.name == "help").is_none() {
if flags.iter().find(|x| x.view().name() == "help").is_none() {
flags.push(
Arg::with_name("help")
.short('h')
Expand All @@ -189,7 +189,10 @@ pub trait Generator {
}

if !p.is_set(AppSettings::DisableVersion)
&& flags.iter().find(|x| x.name == "version").is_none()
&& flags
.iter()
.find(|x| x.view().name() == "version")
.is_none()
{
flags.push(
Arg::with_name("version")
Expand Down
8 changes: 4 additions & 4 deletions clap_generate/src/generators/shells/elvish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,14 @@ fn generate_inner<'b>(

for option in opts!(p) {
if let Some(data) = option.short {
let tooltip = get_tooltip(option.help, data);
let tooltip = get_tooltip(option.view().help(), data);

completions.push_str(&preamble);
completions.push_str(format!("-{} '{}'", data, tooltip).as_str());
}

if let Some(data) = option.long {
let tooltip = get_tooltip(option.help, data);
let tooltip = get_tooltip(option.view().help(), data);

completions.push_str(&preamble);
completions.push_str(format!("--{} '{}'", data, tooltip).as_str());
Expand All @@ -95,14 +95,14 @@ fn generate_inner<'b>(

for flag in Elvish::flags(p) {
if let Some(data) = flag.short {
let tooltip = get_tooltip(flag.help, data);
let tooltip = get_tooltip(flag.view().help(), data);

completions.push_str(&preamble);
completions.push_str(format!("-{} '{}'", data, tooltip).as_str());
}

if let Some(data) = flag.long {
let tooltip = get_tooltip(flag.help, data);
let tooltip = get_tooltip(flag.view().help(), data);

completions.push_str(&preamble);
completions.push_str(format!("--{} '{}'", data, tooltip).as_str());
Expand Down
4 changes: 2 additions & 2 deletions clap_generate/src/generators/shells/fish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ fn gen_fish_inner(root_command: &str, app: &App, buffer: &mut String) {
template.push_str(format!(" -l {}", data).as_str());
}

if let Some(data) = option.help {
if let Some(data) = option.view().help() {
template.push_str(format!(" -d '{}'", escape_string(data)).as_str());
}

Expand All @@ -88,7 +88,7 @@ fn gen_fish_inner(root_command: &str, app: &App, buffer: &mut String) {
template.push_str(format!(" -l {}", data).as_str());
}

if let Some(data) = flag.help {
if let Some(data) = flag.view().help() {
template.push_str(format!(" -d '{}'", escape_string(data)).as_str());
}

Expand Down
8 changes: 4 additions & 4 deletions clap_generate/src/generators/shells/powershell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ fn generate_inner<'b>(

for option in opts!(p) {
if let Some(data) = option.short {
let tooltip = get_tooltip(option.help, data);
let tooltip = get_tooltip(option.view().help(), data);

completions.push_str(&preamble);
completions.push_str(
Expand All @@ -99,7 +99,7 @@ fn generate_inner<'b>(
}

if let Some(data) = option.long {
let tooltip = get_tooltip(option.help, data);
let tooltip = get_tooltip(option.view().help(), data);

completions.push_str(&preamble);
completions.push_str(
Expand All @@ -114,7 +114,7 @@ fn generate_inner<'b>(

for flag in PowerShell::flags(p) {
if let Some(data) = flag.short {
let tooltip = get_tooltip(flag.help, data);
let tooltip = get_tooltip(flag.view().help(), data);

completions.push_str(&preamble);
completions.push_str(
Expand All @@ -127,7 +127,7 @@ fn generate_inner<'b>(
}

if let Some(data) = flag.long {
let tooltip = get_tooltip(flag.help, data);
let tooltip = get_tooltip(flag.view().help(), data);

completions.push_str(&preamble);
completions.push_str(
Expand Down
13 changes: 7 additions & 6 deletions clap_generate/src/generators/shells/zsh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,8 +360,8 @@ fn write_opts_of(p: &App) -> String {
for o in opts!(p) {
debugln!("Zsh::write_opts_of:iter: o={}", o.name);

let help = o.help.map_or(String::new(), escape_help);
let mut conflicts = get_zsh_arg_conflicts!(p, o, INTERNAL_ERROR_MSG);
let help = o.view().help().map_or(String::new(), escape_help);
let mut conflicts = get_zsh_arg_conflicts!(p, o);

conflicts = if conflicts.is_empty() {
String::new()
Expand Down Expand Up @@ -432,7 +432,7 @@ fn write_flags_of(p: &App) -> String {
for f in Zsh::flags(p) {
debugln!("Zsh::write_flags_of:iter: f={}", f.name);

let help = f.help.map_or(String::new(), escape_help);
let help = f.view().help().map_or(String::new(), escape_help);
let mut conflicts = get_zsh_arg_conflicts!(p, f, INTERNAL_ERROR_MSG);

conflicts = if conflicts.is_empty() {
Expand Down Expand Up @@ -496,10 +496,11 @@ fn write_positionals_of(p: &App) -> String {
let a = format!(
"'{optional}:{name}{help}:{action}' \\",
optional = optional,
name = arg.name,
name = arg.view().name(),
help = arg
.help
.map_or("".to_owned(), |v| " -- ".to_owned() + v)
.view()
.help()
.map_or(String::new(), |v| " -- ".to_owned() + v)
.replace("[", "\\[")
.replace("]", "\\]")
.replace(":", "\\:"),
Expand Down
30 changes: 12 additions & 18 deletions clap_generate/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,21 @@ macro_rules! w {
}

macro_rules! get_zsh_arg_conflicts {
($app:expr, $arg:ident, $msg:ident) => {
if let Some(ref conf_vec) = $arg.blacklist {
let mut v = vec![];
($app:expr, $arg:ident) => {{
let mut v = vec![];

for arg_name in conf_vec {
let arg = find!($app, arg_name).expect($msg);

if let Some(s) = arg.short {
v.push(format!("-{}", s));
}

if let Some(l) = arg.long {
v.push(format!("--{}", l));
}
for arg in $app.view().conflicts_with($arg) {
if let Some(s) = arg.short {
v.push(format!("-{}", s));
}

v.join(" ")
} else {
String::new()
if let Some(l) = arg.long {
v.push(format!("--{}", l));
}
}
};

v.join(" ")
}};
}

#[cfg(feature = "debug")]
Expand Down Expand Up @@ -76,7 +70,7 @@ macro_rules! find {
$what!($app).find(|a| &a.name == $name)
};
($app:expr, $name:expr) => {
$app.args.args.iter().find(|a| {
$app.args.args.iter().find_map(|a| {
if let Some(v) = a.index {
&v == $name
} else {
Expand Down
25 changes: 19 additions & 6 deletions src/build/app/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
mod settings;
pub use self::settings::{AppFlags, AppSettings};
pub mod view;
pub(crate) use self::settings::AppFlags;
pub use self::settings::AppSettings;
pub use self::view::AppView;

// Std
use std::collections::HashMap;
Expand Down Expand Up @@ -1392,6 +1395,11 @@ impl<'b> App<'b> {

self._do_parse(&mut it)
}

/// Build an [`AppView`] instance corresponding to `self`.
pub fn view<'app>(&'app self) -> AppView<'app, 'b> {
AppView::from_ref(self)
}
}

// Internally used only
Expand Down Expand Up @@ -1429,7 +1437,7 @@ impl<'b> App<'b> {
}

#[allow(clippy::debug_assert_with_mut_call)]
// used in clap_generate (https://github.com/clap-rs/clap_generate)
// PUB_HIDDEN: used in clap_generate
#[doc(hidden)]
pub fn _build(&mut self) {
debugln!("App::_build;");
Expand Down Expand Up @@ -1503,6 +1511,7 @@ impl<'b> App<'b> {
panic!(abort_message);
}
}

for sub_app in &app.subcommands {
Self::_panic_on_missing_help(&sub_app, help_required_globally);
}
Expand Down Expand Up @@ -1536,7 +1545,7 @@ impl<'b> App<'b> {
true
}

pub fn _propagate(&mut self, prop: Propagation) {
pub(crate) fn _propagate(&mut self, prop: Propagation) {
macro_rules! propagate_subcmd {
($_self:expr, $sc:expr) => {{
// We have to create a new scope in order to tell rustc the borrow of `sc` is
Expand Down Expand Up @@ -1605,6 +1614,7 @@ impl<'b> App<'b> {

self.args.push(help);
}

if !(self
.args
.args
Expand All @@ -1622,6 +1632,7 @@ impl<'b> App<'b> {

self.args.push(version);
}

if self.has_subcommands()
&& !self.is_set(AppSettings::DisableHelpSubcommand)
&& !subcommands!(self).any(|s| s.id == HELP_HASH)
Expand Down Expand Up @@ -1719,7 +1730,7 @@ impl<'b> App<'b> {
true
}

// used in clap_generate (https://github.com/clap-rs/clap_generate)
// PUB_HIDDEN: used in clap_generate
#[doc(hidden)]
pub fn _build_bin_names(&mut self) {
debugln!("App::_build_bin_names;");
Expand Down Expand Up @@ -1854,7 +1865,8 @@ impl<'b> App<'b> {
}

pub fn has_flags(&self) -> bool {
flags!(self).count() > 0
let view = self.view().flags();
view.count() > 0
}

pub fn has_positionals(&self) -> bool {
Expand All @@ -1866,7 +1878,8 @@ impl<'b> App<'b> {
}

pub fn has_visible_flags(&self) -> bool {
flags!(self).any(|o| !o.is_set(ArgSettings::Hidden))
let view = self.view();
view.flags().any(|o| !o.is_set(ArgSettings::Hidden))
}

pub fn has_visible_positionals(&self) -> bool {
Expand Down
103 changes: 103 additions & 0 deletions src/build/app/view.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//! A shim layer that allows querying certain info about `App`,
//! despite the corresponding fields being private.

use super::*;
use crate::INTERNAL_ERROR_MSG;

#[allow(missing_debug_implementations)]
pub struct AppView<'app, 'help> {
id: Id,
name: &'app String,
bin_name: Option<&'app String>,
author: Option<&'help str>,
version: Option<&'help str>,
long_version: Option<&'help str>,
about: Option<&'help str>,
long_about: Option<&'help str>,
more_help: Option<&'help str>,
pre_help: Option<&'help str>,
aliases: Option<&'app Vec<(&'help str, bool)>>, // (name, visible)
usage_str: Option<&'help str>,
usage: Option<&'app String>,
help_str: Option<&'help str>,
disp_ord: usize,
term_w: Option<usize>,
max_w: Option<usize>,
template: Option<&'help str>,
settings: AppFlags,
g_settings: AppFlags,
args: &'app MKeyMap<'help>,
subcommands: &'app Vec<App<'help>>,
groups: &'app Vec<ArgGroup<'help>>,
help_headings: &'app Vec<Option<&'help str>>,
}

impl<'app, 'help> AppView<'app, 'help> {
pub(crate) fn from_ref(app: &'app App<'help>) -> AppView<'app, 'help> {
AppView {
id: app.id,
name: &app.name,
bin_name: app.bin_name.as_ref(),
author: app.author,
version: app.version,
long_version: app.long_version,
about: app.about,
long_about: app.long_about,
more_help: app.more_help,
pre_help: app.pre_help,
aliases: app.aliases.as_ref(),
usage_str: app.usage_str,
usage: app.usage.as_ref(),
help_str: app.help_str,
disp_ord: app.disp_ord,
term_w: app.term_w,
max_w: app.max_w,
template: app.template,
settings: app.settings,
g_settings: app.g_settings,
args: &app.args,
subcommands: &app.subcommands,
groups: &app.groups,
help_headings: &app.help_headings,
}
}
}

impl<'app, 'help: 'app> AppView<'app, 'help> {
/// The list of args the given arg conflicts with.
///
/// # Panics
///
/// If `arg` conflicts with some args `self` don't know about,
/// it will panic.
pub fn conflicts_with(&self, arg: &'app Arg<'_>) -> Vec<&'app Arg<'help>> {
arg.blacklist.as_ref().map_or(vec![], |conflict_ids| {
conflict_ids
.iter()
.map(|id| {
self.args
.args
.iter()
.find(|arg| arg.id == *id)
.expect(INTERNAL_ERROR_MSG)
})
.collect()
})
}

pub fn flags(&self) -> impl Iterator<Item = &Arg<'help>> {
self.args
.args
.iter()
.filter(|a| !a.is_set(ArgSettings::TakesValue) && !a.view().index().is_some())
.filter(|a| !a.view().help_heading().is_some())
}

pub fn args(&'app self) -> impl Iterator<Item = &'app Arg<'help>> {
self.args.args.iter()
}

// pub fn args_mut(&'app mut self) -> impl Iterator<Item = &'app mut Arg<'help>> {
// self.args.args.iter_mut()
// }
}
Loading

0 comments on commit bb0eab8

Please sign in to comment.