CommandLine
Objective-C 的命令行参数解析器
SwiftyLine (即将到来的 Swift 版本的 CommandLine) 欢迎试用。
示例
特性
- 支持子命令
- 支持转发子命令
- 支持查询
- 键值(必需)
- 键值(可选)
- 键值(可选,且默认为nil时有效)
- 键值数组(用于多查询)
- 支持标志
- 支持缩写和多缩写解析
- 自动创建彩色帮助信息(类似 Cocoapods。)
- 自动打印无效参数的帮助信息
- 版本命令
- 输出详细的/成功/警告/错误/信息
- 自定义彩色文本
- 加载指示器
- 进度条
安装
CocoaPods
pod 'CommandLine'
源
拖拽 命令行 文件夹到您的项目中。
导入
#import "CommandLine.h"
用法
子命令
如果你要定义像这样的命令:
$ pod spec create
它的意义
二进制 | 命令 | 子命令 | 子子命令... |
---|---|---|---|
Pod | 规范 | 创建 | ... |
你可以在解析前执行代码。
@interface MyCommand_Spec : CLCommand @end
@implementation MyCommand_Spec
command_configuration() {
configuration.note = @"Create a pod spec";
}
command_main() {
// do something to create a cocoapods spec.
// return an int to main()
return 0;
}
@end
@interface MyCommand_Pod : CLCommand @end
@implementation MyCommand_Pod
command_subcommands(MyCommand_Spec);
@end
int main(int argc, char **argv) {
return [MyCommand_Pod main];
}
转发子命令
如果你要定义默认命令,像这样:
$ pod repo
# equals to
$ pod repo list
它的意义
二进制 | 命令 | 转发子命令 |
---|---|---|
Pod | repo | list |
你可以在解析前执行代码。
// Will support in feature.
查询
如果你要定义像这样的命令:
$ codesign [--entitlement /path/to/entitlement.plist] --cert "iPhone Developer: XXXX" ...
# or
$ codesign [-e /path/to/entitlement.plist] -c "iPhone Developer: XXXX" ...
它的意义
二进制 | 查询键1 | 查询值1 | 查询键2 | 查询值2 |
---|---|---|---|---|
codesign | entitlement/e(可选) | /path/to/entitlement.plist | cert/c(必需) | 证书名称 |
你可以在解析前执行代码。
@interface MyCommand_Codesign : CLCommand @end
@implementation MyCommand_Codesign
command_option(CLString, entitlement, shortName='e', nullable, note=@"Entitlement.plist path")
command_option(CLString, cert, shortName='c', nonnull, note=@"Cert name")
command_main() {
// You can use getter or static variable to get argument
NSString *_cert = [self cert]; // get value with getter.
NSString *_entitlement = entitlement; // get value with variable
// to code sign
return EXIT_SUCCESS;
}
@end
int main(int argc, char **argv) {
return [MyCommand_Codesign main];
}
如果你想获取一个数组值,像这样:
$ demo /path/to/input1 /path/to/input2
它的意义
二进制 | 查询键 | 查询值 |
---|---|---|
demo | 输入 | 路径数组 |
你可以在解析前执行代码。
CLCommand *demo = [CLCommand main];
demo.setQuery(@"input").mutiable().require();
[demo handleProcess: ^CLResponse *(CLCommand *command, CLProcess *process) {
NSArray *inputs = process.queries[@"input"];
return EXIT_SUCCESS;
}];
标志
如果你要定义像这样的命令:
$ ls --all
# or
$ ls -a
它的意义
二进制 | 标志键 |
---|---|
ls | all / a |
你可以在解析前执行代码。
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 handleProcess:^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("%s\n", 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("%s\n", item.UTF8String);
}
return EXIT_SUCCESS;
}];
缩写 & 多缩写
例如
# 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
命令行支持解析多缩写!
IOPaths
IOPaths 是一种没有键的值。通常用于输入、输出路径。例如
$ cd /change/to/directory/ # inpuut
$ mkdir /create/new/folder # input
$ zip /to/.zip /source/folder # output & input
你可以在解析前执行代码。
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 handleProcess:^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;
}];
解析
在定义完所有命令及其子命令后,您可以处理和传递参数
CLCommandMain(); // return [CLCommand handleProcess];
推荐用法
首先:使用相同的前缀在元类方法中定义所有命令
// In a category.
+ (void)__init_command1 {
// to define you command
}
// In other category
+ (void)__init_command2 {
// to define you command
}
其次:在 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;
}
帮助信息
何时工具应该打印帮助信息?
- 用户输入
--help
或-h
获取帮助 - 用户输入了非法的参数。例如:输入了2个路径但是需要3个,没有输入必要的查询...
命令行将自动创建彩色的帮助信息并自动打印。
彩色的帮助信息?是的!就像CocoaPods。
特殊输出
1. 详细信息
打印更多信息的模式。
它将通过标志--verbose
触发。
可以在任务中使用
CLVerbose(@"Making temp directory: %@", tempDirectory);
// it will be print if the process contains `verbose` flag.
// auto append a '\n' in end.
2. 成功
打印绿色文本。
可以在任务中使用
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. 警告
打印黄色文本。
CLWarning(@"The directory is not exist, it will be ignore.");
// print the text render with yellow color
// auto append a '\n' in end.
4. 错误
打印红色文本。
可以在任务中使用
CLError(@"Error: %@", error);// error is instance of NSError
// print the text render with red color
// auto append a '\n' in end.
5. 更多信息
打印< strong>轻量级 文本。
可以在任务中使用
CLInfo(@"XXXXXX");
// print the text with light font.
// auto append a '\n' in end.
6. --no-ansi标记
如果用户将--no-ansi
标记传递到参数中,所有上述功能将打印纯文本。
7. --silent标记
如果使用将--silent
标记传递到参数中,所有上述功能将失去有效性。
版本
打印此工具或命令的版本。
[CLCommand mainCommand].version = @"1.0.0"; // do once.
$ tool --version
1.0.0
$ tool subcommand --version
1.2.0
终端
NSString *fileList = CLLaunch(nil, @"ls", @"-a", nil);
CLLaunch(@"~", @"zip", @"-qry", @"output.zip", @".", nil);
CLLaunch(nil, @[@"ls", @"-a"], nil);
打印彩色文本
#import "CCText.h"
CCPrintf(CCStyleBord|CCStyleItalic, @"A text with %@ and %@", @"bord", @"italic");
// see more CCStyle in CCText.h
加载与进度
CLLoading *loading = [CLLoading loading];
[loading start];
// do you task
[loading stop];
CLProgress *progress = [CLProgress progress];
[progress start];
// do you task and set progress between 0.0 ~ 1.0
progress.progress = 0.5;
[progress stop];
许可证
MIT.