Latest 2.0.1
Homepage https://github.com/Magic-Unique/CommandLine
License MIT
Platforms osx 10.10
Authors

Version
License
Platform

A command line arguments parser of Objective-C

Demo

See Magic-Unique/MobileProvisionTool

Features

  1. Support subcommands
  2. Support forwarding subcommand
  3. Support Queries
    • key-value (require)
    • key-value (optional)
    • key-value (optional & default-if-nil)
    • key-values (as array, for multi-queries)
  4. Support Flags
  5. Support Abbr and multi-abbrs parsing
  6. Auto create colorful help infomation (just like cocoapods.)
  7. Auto print helping infomation if arguments is invalid
  8. Version command
  9. Output with verbose/success/warning/error/info
  10. Custom colorful text

Installation

CocoaPods

pod 'CommandLine'

Source

Drag CommandLine folder to your project.

Import

#import "CommandLine.h"

Usage

Subcommand

If you want to define the command like:

$ pod spec create

it’s meaning:

binary command subcommand subsubcommand…
pod spec create

you can execute the code before parse.

CLCommand *pod = [CLCommand main];
CLCommand *spec = [pod defineSubcommand:@"spec"];
spec.explain = @"Spec commands"
{
    CLCommand *create = [spec defineSubcommand:@"create"];
    create.explain = @"Create a pod spec";
    [create onHandlerprocess:^int(CLCommand *command, CLProcess *process) {
        // do something to create a cocoapods spec.

        // return an int to main()
        return EXIT_SUCCESS;
    }];
}

Forwarding Subcommand

If you want to define default command like:

$ pod repo

# equals to

$ pod repo list

It’s meaning:

binary command forwarding subcommand
pod repo list

You can execute the code before parse.

CLCommand *pod = [CLCommand main];
CLCommand *repo = [pod defineSubcommand:@"repo"];
repo.explain = @"Repo operator"
{
    CLCommand * list = [spec defineForwardingSubcommand:@"list"];
    list = @"List all local repo";
    [create onHandlerprocess:^int(CLCommand *command, CLProcess *process) {
        // do something to list out local repo
    }];
}

Queries

If you want to define the command like:

$ codesign [--entitlement /path/to/entitlement.plist] --cert "iPhone Developer: XXXX" ...
# or
$ codesign [-e /path/to/entitlement.plist] -c "iPhone Developer: XXXX" ...

It’s meaning:

Binary Query Key 1 Query Value 1 Query Key 2 Query Value 2
codesign entitlement/e (optional) /path/to/entitlement.plist cert/c (require) Cert Name

you can execute the code before parse.

CLCommand *codesign = [CLCommand main]; // get main command (without any command or subcommands)
codesign.setQuery(@"entitlement")
    .setAbbr('e')
    .optional()
    .setExplain("Entitlement.plist file path."); // define a optional query
codesign.setQuery(@"cert")
    .setAbbr('c')
    .require()
    .setExplain("Cert name"); // define a require query
[codesign onHandlerprocess:^CLResponse *(CLCommand *command, CLProcess *process) {
    NSString *cert = process.queries[@"cert"]; // get value with key.
    NSString *entitlement = process.queries[@"entitlement"]; // nonable
    //  to code sign

    return EXIT_SUCCESS;
}];

If you want to get a array value like:

$ demo --input /path/to/input1 --input /path/to/input2

It’s meaning:

Binary Query Key Query Value
demo input path array

you can execute the code before parse.


CLCommand *demo = [CLCommand main];
demo.setQuery(@"input").mutiable().require();
[demo onHandlerprocess: ^CLResponse *(CLCommand *command, CLProcess *process) {
    NSArray *inputs = process.queries[@"input"];

    return EXIT_SUCCESS;
}];

Flags

If you want to define the command like:

$ ls --all
# or
$ ls -a

It’s meaning:

Binary Flag Key
ls all / a

you can execute the code before parse.

CLCommand *ls = [CLCommand main]; // get main command (without any command or subcommands)
ls.setFlag(@"all")
    .setAbbr('a')
    .setExplain(@"Print all contents."); // define a optional query
[ls onHandlerprocess:^CLResponse *(CLCommand *command, CLProcess *process) {
    BOOL all = [process flag:@"all"];

    // list and print
    NSFileManager *fmgr = [NSFileManager defaultManager];
    NSError *error = nil;
    NSArray *contents = [fmgr contentsOfDirectory:[CLIOPath currentDirectory] error:&error];
    if (error) {
        printf("%sn", error.localizedDescription.UTF8String);
        return [CLResponse error:error];
    }
    if (NO == all) {
        NSMutableArray *mContents = [NSMutableArray arrayWithArray:contents];
        //  remove all item with "." prefix in mContents;
        contents = [mContents copy];
    }
    for (NSString *item in contents) {
        printf("%sn", item.UTF8String);
    }
    return EXIT_SUCCESS;
}];

Abbr & Multi-abbrs

For example:

# Multi-abbrs for flags:

$ rm -rf /path/to/directory

# is meaning:

$ rm -r -f /path/to/directory
$ rm --recursive --force /path/to/directory

# 'r' is recursive(flag)'s abbr, 'f' is force(flag)'s abbr.
# Multi-abbrs for flags and a query

$ codesign -fs 'iPhone Developer: XXXX (XXXX)' /path/to/Application.app

# is meaning:

$ codesign -f -s 'iPhone Developer: XXXX (XXXX)' /path/to/Application.app

# 'f' is replacing-exist-sign(flag)'s abbr
# 's' is signature(query)'s abbr 

CommandLine is supporting parse multi-abbrs!

IOPaths

IOPaths is a type of value without any key. It’s usually used in input, output path. Such as:

$ cd /change/to/directory/      # inpuut
$ mkdir /create/new/folder      # input
$ zip /to/.zip /source/folder   # output & input

you can execute the code before parse.

CLCommand *zip = [CLCommand main]; // get main command (without any command or subcommands)

/*
    User must type in an output path and one or more input path(s)
*/
zip.addRequirePath(@"output")
    .setExplain(@"output key");
zip.addRequirePath(@"input1")
    .setExplain(@"Input path");
zip.addOptionalPath(@"input2")
    .setExplain(@"Input path");

[zip onHandlerprocess:^CLResponse *(CLCommand *command, CLProcess *process) {
    NSArray *paths = process.paths; // paths.count >= 2
    NSString *output = paths.firstObject;
    NSArray *inputs = ({
        NSMutableArray *inputs = paths.mutableCopy;
        [input removeObjectAtIndex:0];
        inputs.copy;
    });

    NSString *fullOutput = [CLIOPath abslutePath:output]; // replace `~` with $HOME and append current directory if needs.
    //  to zip
    return EXIT_SUCCESS;
}];

Parse

After you defined all commands and their subcommands, you can handle and process the arguments

CLCommandMain(); // return [CLCommand handleProcess];

Recommand Usage

Frist: Define all command in meta-class method with same prefix:

//  In a category.
+ (void)__init_command1 {
    // to define you command
}

//  In other category
+ (void)__init_command2 {
    //  to define you command
}

Second: Coding in main():

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        CLMainExplain = @"Description for this command line tool"; // set description
        CLMakeSubcommand(CLCommand, __init_); // define your command. The second argument is the prefix in first step.
        CLCommandMain(); // handle and process arguments
    }
    return 0;
}

Helping Infomations

When should the tool print helping infomation ?

  1. User type in --help or -h for helping
  2. User type in illegal arguments. Such as: inputed 2 paths but 3 required, didnot input required query…

CommandLine will auto create a colorfull helping infomation and print automatically.

Colorfull helping infomation ? Yes ! Just like CocoaPods.

CocoaPods Helping Infomations

Special output

1. Verbose

Print more infomations mode.

It will be triggered by flag --verbose.

You can use in task:

CLVerbose(@"Making temp directory: %@", tempDirectory);
//  it will be print if the process contains `verbose` flag.
//  auto append a 'n' in end.

2. Success

Print green text.

You can use in task:

CLSuccess(@"Done! There are %lu devices in the mobileprovision", devices.count);
//  devices is instance of NSArray
//  print the text render with green color
//  auto append a 'n' in end.

3. Warning

Pring yellow text.

CLWarning(@"The directory is not exist, it will be ignore.");
//  print the text render with yellow color
//  auto append a 'n' in end.

4. Error

Print red text.

You can use in task:

CLError(@"Error: %@", error);// error is instance of NSError
//  print the text render with red color
//  auto append a 'n' in end.

5. More Info

Print light text.

You can use in task:

CLInfo(@"XXXXXX");
//  print the text with light font.
//  auto append a 'n' in end.

6. –no-ansi flag

If user pass --no-ansi flag into arguments, all above function will print plain text.

7. –silent flag

If use pass --silent flag into arguments, all above function will be invalid.

Version

Print version of this tool or command.

[CLCommand mainCommand].version = @"1.0.0"; // do once.
$ tool --version
1.0.0

$ tool subcommand --version
1.2.0

Terminal

NSString *fileList = CLLaunch(nil, @"ls", @"-a", nil);
CLLaunch(@"~", @"zip", @"-qry", @"output.zip", @".", nil);
CLLaunch(nil, @[@"ls", @"-a"], nil);

Print colorful text

#import "CCText.h"
CCPrintf(CCStyleBord|CCStyleItalic, @"A text with %@ and %@", @"bord", @"italic");
// see more CCStyle in CCText.h

LICENCE

MIT.

Latest podspec

{
    "name": "CommandLine",
    "version": "2.0.1",
    "summary": "A command line arguments parser of Objective-C",
    "description": "If you want to build a command line tool and require some arguments when running it.nYou can link CommandLine, and dont warry about the arguments-parsing. CommandLinencan complete it for you.",
    "homepage": "https://github.com/Magic-Unique/CommandLine",
    "license": "MIT",
    "authors": {
        "u51b7u79cb": "[email protected]"
    },
    "platforms": {
        "osx": "10.10"
    },
    "source": {
        "git": "https://github.com/Magic-Unique/CommandLine.git",
        "tag": "2.0.1"
    },
    "source_files": "CommandLine/**/*.{h,m}",
    "public_header_files": "CommandLine/Public/*.h"
}

Pin It on Pinterest

Share This