Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8ac8d3b

Browse files
committed
fix(clap): generate command data structure
We do this in the hopes to circumvent a stack overflow. This means we will setup the parser entirely at runtime, which actually saves a little bit of code.
1 parent 9a8ae4b commit 8ac8d3b

4 files changed

Lines changed: 51 additions & 27 deletions

File tree

src/mako/cli/lib/argparse.mako

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@
77
88
def rust_boolean(v):
99
return v and 'true' or 'false'
10+
11+
def rust_optional(v):
12+
if v is None:
13+
return 'None'
14+
if isinstance(v, bool):
15+
v = v and 'true' or 'false'
16+
elif isinstance(v, basestring):
17+
v = '"%s"' % v
18+
return 'Some(%s)' % v
1019
%>\
1120
<%def name="grammar(c)">\
1221
% for resource in sorted(c.rta_map.keys()):
@@ -109,7 +118,7 @@ Configuration:
109118
None
110119
))
111120
%>\
112-
App::new("${util.program_name()}")
121+
let mut app = App::new("${util.program_name()}")
113122
<%block filter="indent_by(7)">\
114123
.author("${', '.join(cargo.authors)}")
115124
.version("${cargo.build_version}")
@@ -121,11 +130,17 @@ App::new("${util.program_name()}")
121130
.arg(Arg::with_name("${arg_name or flag}")
122131
.long("${flag}")
123132
.help("${desc}")
124-
.takes_value(${rust_boolean(arg_name)}))
133+
.takes_value(${rust_boolean(arg_name)}))\
134+
% if loop.last:
135+
;
136+
% else:
137+
138+
% endif
125139
% endfor
140+
let arg_data = [
126141
% for resource in sorted(c.rta_map.keys()):
127-
.subcommand(
128-
SubCommand::new("${mangle_subcommand(resource)}")
142+
<%block filter="indent_by(4)">\
143+
("${mangle_subcommand(resource)}", vec![
129144
% for method in sorted(c.rta_map[resource]):
130145
<%
131146
mc = new_method_context(resource, method, c)
@@ -193,30 +208,23 @@ App::new("${util.program_name()}")
193208
))
194209
# handle output
195210
%>\
196-
.subcommand(
197-
SubCommand::new("${mangle_subcommand(method)}")
198-
% if mc.m.get('description') is not None:
199-
.about("${mc.m.description}")
200-
% endif
211+
("${mangle_subcommand(method)}", ${rust_optional(mc.m.get('description'))},
212+
vec![
201213
% for flag, desc, arg_name, required, multi in args:
202-
.arg(
203-
Arg::with_name("${arg_name or flag}")
204-
% if flag:
205-
.short("${flag}")
206-
% endif
207-
% if desc:
208-
.help("${desc}")
209-
% endif
210-
% if flag is not None:
211-
.takes_value(${rust_boolean(arg_name)})
212-
% endif
213-
.required(${rust_boolean(required)})
214-
.multiple(${rust_boolean(multi)}))
214+
(${rust_optional(arg_name)},
215+
${rust_optional(flag)},
216+
${rust_optional(desc)},
217+
${rust_optional(required)},
218+
${rust_optional(multi)}),
219+
% if not loop.last:
220+
221+
% endif
215222
% endfor
216-
)
223+
]),
217224
% endfor # each method
218-
)
225+
]),
226+
</%block>
219227
% endfor # end for each resource
220-
.get_matches();
228+
];
221229
</%block>
222230
</%def>

src/mako/cli/lib/engine.mako

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
%>\
3030
mod cmn;
3131
use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg,
32-
input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError};
32+
input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, make_subcommand};
3333
3434
use std::default::Default;
3535
use std::str::FromStr;

src/mako/cli/main.rs.mako

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ use clap::{App, SubCommand, Arg};
3030
## ${engine.new(c)}\
3131

3232
fn main() {
33-
let matches =
3433
${argparse.new(c) | indent_all_but_first_by(1)}\
3534

3635
## let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit());

src/rust/cli/cmn.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token};
22
use rustc_serialize::json;
33
use mime::Mime;
4+
use clap::{App, SubCommand};
45

56
use std::fs;
67
use std::env;
@@ -15,6 +16,22 @@ use std::default::Default;
1516

1617
const FIELD_SEP: char = '.';
1718

19+
20+
fn make_subcommand(command_name: &str, desc: Option<&str>,
21+
args: &Vec<(Option<&str>, Option<&str>, Option<&str>,
22+
Option<bool>, Option<bool>)>)
23+
-> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
24+
// arg_name: Option<&str>,
25+
// short_name: Option<&str>,
26+
// help: Option<&str>,
27+
// % if flag is not None:
28+
// .takes_value(${rust_boolean(arg_name)})
29+
// required: Option<bool>,
30+
// multiple: Option<bool>
31+
SubCommand::new(command_name)
32+
}
33+
34+
1835
#[derive(Clone, Default)]
1936
pub struct FieldCursor(Vec<String>);
2037

0 commit comments

Comments
 (0)