These are chat archives for kbknapp/clap-rs

31st
Jul 2015
Severen Redwood
@severen
Jul 31 2015 05:35
I've made a start, how does this look?:
#![feature(test)]

extern crate test;
extern crate clap;

use test::Bencher;
use clap::{Arg, App, SubCommand};

// Define version and author constants to reduce repetitiveness.
const VERSION: &'static str = "0.1.0";
const AUTHOR: &'static str = "Lorem Ipsum <lorem.ipsum@foo.bar";

#[bench]
// Benchmarks the creation of a simple `cp` clone that only utilises arguments and does not support
// subcommands.
fn simple_cli(b: &mut Bencher) {
    b.iter(|| {
        App::new("cp")
            .version(VERSION)
            .about("Copy files")
            .author(AUTHOR)
            .args(vec![
                Arg::from_usage("-o, --output 'Specify the output file'"),
                Arg::from_usage("-f, --force 'If destination file exists, overwrite it'"),
            ])
    });
}
Output:
running 1 test
test simple_cli ... bench:       2,192 ns/iter (+/- 35)
Severen Redwood
@severen
Jul 31 2015 06:00
How do I define a function that returns a clap::App?

Want to do something like this:

#[inline(always)]
fn simple_cli() -> clap::App {
    App::new("cp")
        .version(VERSION)
        .about("Copy files")
        .author(AUTHOR)
        .args(vec![
            Arg::from_usage("-f, --force 'If destination file exists, overwrite it'"),
            Arg::from_usage("-i, --interactive 'Prompt before overwrite'"),
            Arg::from_usage("-v, --verbose 'Enable verbose output'"),
        ])
}

This allows me to reuse this function in benchmarks for the creation and parsing of a simple CLI application.
For example:

#[bench]
fn simple_cli_creation(b: &mut Bencher) {
    b.iter(|| {
        simple_cli();
    });
}

#[bench]
fn simple_cli_parse(b: &mut Bencher) {
    b.iter(|| {
        simple_cli().get_matches();
    });
}
Severen Redwood
@severen
Jul 31 2015 06:48
I'm also working on advanced_cli_creation() and advanced_cli_parsing() which benchmarks the creation and parsing of a Git clone in Clap.
You can view my current work as of now at http://pastebin.com/cZnF3bXR
Kevin K.
@kbknapp
Jul 31 2015 14:55
Looks great thanks! Some small changes I'd make are the -o, --output 'Specify the output file' needs a [file] otherwise it's just a flag (-o, --output [file] 'Specify the output file')
Also, I'd change the .args( vec![ ... ] ) to
.args_from_usage("-f, --force 'If destination file exists, overwrite it'
                  -i, --interactive 'Prompt before overwrite'
                  -v, --verbose 'Enable verbose output'")
This doesn't allocate a vec, and is a little shorter to type. There are times where you may want to use args( vec![ ... ] ) but it's mainly only when you want to use settings for an Arg that you can't do in the "usage" such as groups, min/max values, specific values, conflicts, requirements, etc.
Kevin K.
@kbknapp
Jul 31 2015 15:01
The final is I don't think you can't call .get_matches() in a benchmark because that uses env::args(). You'll have to do something like:
let argv = vec!["cli", "-f", "-o", "value"];
// Create the app the same...
app.get_matches_from(argv.iter());
I'm excited about this PR, since it's something that I've been thinking about for a while and just never done. So I'm super appreciative! :D
Severen Redwood
@severen
Jul 31 2015 17:02
Thanks for the feedback, I'll get back to it ;)