Compare commits
18 Commits
v0.2.0
...
5879273771
| Author | SHA1 | Date | |
|---|---|---|---|
| 5879273771 | |||
| f58d83b4ee | |||
| 85a219126d | |||
| 1345a0514e | |||
| 0a7179380a | |||
| 56a50201fe | |||
| 7b2acabfd6 | |||
| ad655041dd | |||
| e9dd39f53b | |||
| cffe8bfe4a | |||
| b4663a01e8 | |||
| b1eaae793e | |||
| ce4d0fc423 | |||
| f6ee49f85e | |||
| 924f9662b5 | |||
| 5df2e31973 | |||
| c71c9b6d15 | |||
| 3ade1fd1aa |
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 youmetme
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
191
README.md
191
README.md
@@ -5,8 +5,13 @@ C语言易用的命令参数分析
|
||||
|
||||
# 特性
|
||||
- 自动生成帮助信息
|
||||
- 命令自动帮助信息
|
||||
- 默认值支持
|
||||
- 子命令支持
|
||||
- 命令参数支持
|
||||
- 全局参数
|
||||
- 互斥参数(即将)
|
||||
|
||||
|
||||
|
||||
# 安装
|
||||
@@ -29,7 +34,7 @@ conan create .
|
||||
|
||||
|
||||
## 示例程序
|
||||
构建简单的命令行程序
|
||||
构建简单的命令行程序,更多示例请参考`example`目录
|
||||
```c
|
||||
#include "ArgParse.h"
|
||||
#include <stdbool.h>
|
||||
@@ -37,11 +42,11 @@ conan create .
|
||||
#include <string.h>
|
||||
|
||||
ArgParse *Init() {
|
||||
ArgParse *ap = argParseInit("简单的命令行工具示例");
|
||||
ArgParse *ap = argParseInit("简单的命令行工具示例",ArgParseNOVALUE);
|
||||
|
||||
// 添加第一个命令
|
||||
Command *cmd = argParseAddCommand(
|
||||
ap, "list", "列出文件列表", NULL, NULL, NULL, SINGLEVALUE);
|
||||
ap, "list", "列出文件列表", NULL, NULL, NULL, ArgParseSINGLEVALUE);
|
||||
|
||||
// 添加第一个命令的参数
|
||||
argParseAddArg(cmd,
|
||||
@@ -51,7 +56,7 @@ ArgParse *Init() {
|
||||
NULL,
|
||||
NULL,
|
||||
false,
|
||||
NOVALUE);
|
||||
ArgParseNOVALUE);
|
||||
|
||||
return ap;
|
||||
}
|
||||
@@ -77,4 +82,180 @@ int main(int argc, char *argv[]) {
|
||||
```bash
|
||||
example -h
|
||||
```
|
||||

|
||||

|
||||
|
||||
|
||||
# API
|
||||
该API将分为两类,一类是用于构造解析器,另一类将用于解析参数
|
||||
|
||||
## 构造解析器
|
||||
|
||||
1. 初始化解析器
|
||||
```c
|
||||
ArgParse *argParseInit(char *documentation,ArgParseValueType value_type);
|
||||
```
|
||||
- `documentation` 解析器的文档信息
|
||||
- `valueType` 程序本身需要的值类型
|
||||
|
||||
2. 添加命令
|
||||
```c
|
||||
Command *argParseAddCommand(ArgParse *argParse,
|
||||
char *name,
|
||||
char *help,
|
||||
char *default_val,
|
||||
ArgParseCallback callback,
|
||||
CommandGroup *group,
|
||||
ArgParseValueType value_type);
|
||||
```
|
||||
- `argParse` 解析器
|
||||
- `name` 命令名称
|
||||
- `help` 命令帮助信息
|
||||
- `defaultVal` 默认值
|
||||
- `callback` 命令回调函数(可选)
|
||||
- `group` 命令组(可选)
|
||||
- `valueType` 命令参数类型
|
||||
|
||||
3. 添加命令参数
|
||||
```c
|
||||
CommandArgs *argParseAddArg(Command *command,
|
||||
char *short_opt,
|
||||
char *long_opt,
|
||||
char *help,
|
||||
char *default_val,
|
||||
ArgParseCallback callback,
|
||||
bool required,
|
||||
ArgParseValueType value_type);
|
||||
```
|
||||
- `command` 命令
|
||||
- `shortOpt` 短选项
|
||||
- `longOpt` 长选项
|
||||
- `help` 帮助信息
|
||||
- `defaultVal` 默认值
|
||||
- `callback` 回调函数(可选)
|
||||
- `required` 是否必须
|
||||
- `valueType` 参数类型
|
||||
|
||||
4. 添加子命令
|
||||
```c
|
||||
Command *argParseAddSubCommand(Command *Parent,
|
||||
char *name,
|
||||
char *help,
|
||||
char *default_val,
|
||||
ArgParseCallback callback,
|
||||
CommandGroup *group,
|
||||
ArgParseValueType value_type);
|
||||
```
|
||||
- `Parent` 父命令
|
||||
- `name` 命令名称
|
||||
- `help` 命令帮助信息
|
||||
- `defaultVal` 默认值
|
||||
- `callback` 回调函数(可选)
|
||||
- `group` 命令组(可选)
|
||||
- `valueType` 命令参数类型
|
||||
|
||||
5. 添加全局参数
|
||||
```c
|
||||
CommandArgs *argParseAddGlobalArg(ArgParse *argParse,
|
||||
char *short_opt,
|
||||
char *long_opt,
|
||||
char *help,
|
||||
char *default_val,
|
||||
ArgParseCallback callback,
|
||||
bool required,
|
||||
ArgParseValueType value_type);
|
||||
```
|
||||
- `argParse` 解析器
|
||||
- `shortOpt` 短选项
|
||||
- `longOpt` 长选项
|
||||
- `help` 帮助信息
|
||||
- `defaultVal` 默认值
|
||||
- `callback` 回调函数(可选)
|
||||
- `required` 是否必须
|
||||
- `valueType` 参数类型
|
||||
|
||||
## 解析参数API
|
||||
1. 解析参数
|
||||
```c
|
||||
void argParseParse(ArgParse *argParse, int argc, char *argv[]);
|
||||
```
|
||||
- `argParse` 解析器
|
||||
- `argc` 参数个数
|
||||
- `argv` 参数列表
|
||||
|
||||
2. 获取当前解析到的命令名字
|
||||
```c
|
||||
char *argParseGetCurCommandName(ArgParse *argParse);
|
||||
```
|
||||
- `argParse` 解析器
|
||||
> 注意,解析到的命令为最后一次出现的命令,也可能是子命令
|
||||
|
||||
|
||||
3. 获取当前命令的值
|
||||
```c
|
||||
char *argParseGetCurCommandValue(ArgParse *argParse);
|
||||
```
|
||||
- `argParse` 解析器
|
||||
> 注意,解析到的命令为最后一次出现的命令,也可能是子命令
|
||||
|
||||
4. 获取当前命令的某个参数的值
|
||||
```c
|
||||
char *argParseGetCurArg(ArgParse *argParse, char *opt);
|
||||
```
|
||||
- `argParse` 解析器
|
||||
- `opt` 参数选项
|
||||
|
||||
5. 获取当前命令的某个选项的值列表(当为多值类型时使用该函数)
|
||||
```c
|
||||
char **argParseGetCurArgList(ArgParse *argParse, char *opt, int *len);
|
||||
```
|
||||
- `argParse` 解析器
|
||||
- `opt` 参数选项
|
||||
- `len` 参数个数
|
||||
|
||||
6. 获取全局选项的值
|
||||
```c
|
||||
char *argParseGetGlobalArg(ArgParse *argParse, char *opt);
|
||||
```
|
||||
- `argParse` 解析器
|
||||
- `opt` 参数选项
|
||||
|
||||
7. 获取全局选项的值列表
|
||||
```c
|
||||
char **argParseGetGlobalArgList(ArgParse *argParse, char *opt, int *len);
|
||||
```
|
||||
- `argParse` 解析器
|
||||
- `opt` 参数选项
|
||||
- `len` 参数个数
|
||||
|
||||
8. 获取程序值
|
||||
该值为非命令的值,类似`gcc main.c`,该类程序没有使用命令,因此该值就是`main.c`
|
||||
```c
|
||||
char *argParseGetVal(ArgParse *argParse);
|
||||
char **argParseGetValList(ArgParse *argParse, int *len);
|
||||
```
|
||||
- `argParse` 解析器
|
||||
- `len` 参数个数
|
||||
|
||||
|
||||
### 触发检测API
|
||||
1. 检测当前检测的命令的某个选项是否触发
|
||||
```c
|
||||
bool argParseCheckCurArgTriggered(ArgParse *argParse, char *opt);
|
||||
```
|
||||
- `argParse` 解析器
|
||||
- `opt` 参数选项
|
||||
|
||||
|
||||
2. 检测某个命令是否被触发
|
||||
```c
|
||||
bool argParseCheckCommandTriggered(ArgParse *argParse, char *command_name);
|
||||
```
|
||||
- `argParse` 解析器
|
||||
- `command_name` 命令名称
|
||||
|
||||
3. 检测某个全局选项是否被触发
|
||||
```c
|
||||
bool argParseCheckGlobalTriggered(ArgParse *argParse, char *opt);
|
||||
```
|
||||
- `argParse` 解析器
|
||||
- `opt` 参数选项
|
||||
@@ -6,7 +6,7 @@ import os
|
||||
|
||||
class loggingRecipe(ConanFile):
|
||||
name = "cargparse"
|
||||
version = "0.2.0"
|
||||
version = "0.3.2"
|
||||
license = "MIT"
|
||||
author = "321640253@qq.com"
|
||||
url = "https://gitea.youmetme.wang/youmetme/logging"
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
#include <string.h>
|
||||
|
||||
ArgParse *Init() {
|
||||
ArgParse *ap = argParseInit("简单的命令行工具示例");
|
||||
ArgParse *ap = argParseInit("简单的命令行工具示例",ArgParseNOVALUE);
|
||||
|
||||
// 添加第一个命令
|
||||
Command *cmd = argParseAddCommand(
|
||||
ap, "list", "列出文件列表", NULL, NULL, NULL, SINGLEVALUE);
|
||||
ap, "list", "列出文件列表", NULL, NULL, NULL, ArgParseSINGLEVALUE);
|
||||
|
||||
// 添加第一个命令的参数
|
||||
argParseAddArg(cmd,
|
||||
@@ -18,7 +18,7 @@ ArgParse *Init() {
|
||||
NULL,
|
||||
NULL,
|
||||
false,
|
||||
NOVALUE);
|
||||
ArgParseNOVALUE);
|
||||
|
||||
return ap;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define NORETURN __declspec(noreturn)
|
||||
#else
|
||||
#define NORETURN _Noreturn
|
||||
#endif
|
||||
|
||||
#define ARG_DEFAULT_HELP_FLAG "--help"
|
||||
|
||||
typedef struct ArgParse ArgParse; // 解析器
|
||||
@@ -16,10 +22,10 @@ typedef int (*ArgParseCallback)(ArgParse *argParse,
|
||||
int val_len); // 回调函数
|
||||
|
||||
typedef enum {
|
||||
NOVALUE = 0, // 无值
|
||||
SINGLEVALUE, // 单值 例如: -i https://www.baidu.com
|
||||
MULTIVALUE, // 多值 例如: -s a b c 或 -s a -s b -s c等
|
||||
} ArgParseValueType; // 值类型
|
||||
ArgParseNOVALUE = 0, // 无值
|
||||
ArgParseSINGLEVALUE, // 单值 例如: -i https://www.baidu.com
|
||||
ArgParseMULTIVALUE, // 多值 例如: -s a b c 或 -s a -s b -s c等
|
||||
} ArgParseValueType; // 值类型
|
||||
|
||||
typedef struct CommandArgs {
|
||||
/* 构造属性 */
|
||||
@@ -69,19 +75,25 @@ typedef struct ArgParse {
|
||||
struct CommandArgs **global_args; // 全局参数
|
||||
int global_args_len; // 全局参数个数
|
||||
char *documentation; // 帮助文档
|
||||
ArgParseValueType value_type; // 值类型 程序默认需要的值例如 gcc main.c
|
||||
|
||||
/* 解析所用到的属性*/
|
||||
struct Command *current_command; // 当前解析到的命令
|
||||
int argc; // 参数个数
|
||||
char **argv; // 参数列表
|
||||
char **val;
|
||||
int val_len;
|
||||
int argc; // 参数个数
|
||||
char **argv; // 参数列表
|
||||
} ArgParse;
|
||||
|
||||
/** Start---------------构造API---------------- */
|
||||
|
||||
/**
|
||||
* @brief 初始化解析器
|
||||
* @param documentation 帮助文档
|
||||
* @param value_type 值类型,程序默认需要的值例如 gcc main.c
|
||||
* @return ArgParse* 解析器指针
|
||||
*/
|
||||
ArgParse *argParseInit(char *documentation);
|
||||
ArgParse *argParseInit(char *documentation, ArgParseValueType value_type);
|
||||
|
||||
/**
|
||||
* @brief 释放解析器
|
||||
@@ -268,6 +280,9 @@ bool argParseCheckCommandTriggered(ArgParse *argParse, char *command_name);
|
||||
*/
|
||||
bool argParseCheckGlobalTriggered(ArgParse *argParse, char *opt);
|
||||
|
||||
char *argParseGetVal(ArgParse *argParse);
|
||||
char **argParseGetValList(ArgParse *argParse, int *len);
|
||||
|
||||
/** End----------------解析API---------------- */
|
||||
|
||||
/**
|
||||
@@ -294,10 +309,10 @@ char *argParseGenerateHelp(ArgParse *argParse);
|
||||
char *
|
||||
argParseGenerateArgErrorMsg(ArgParse *argParse, char *name, bool short_flag);
|
||||
|
||||
_Noreturn void argParseError(ArgParse *argParse,
|
||||
Command *lastCommand,
|
||||
char *prefix,
|
||||
char *suffix);
|
||||
NORETURN void argParseError(ArgParse *argParse,
|
||||
Command *lastCommand,
|
||||
const char *prefix,
|
||||
const char *suffix);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
248
src/ArgParse.c
248
src/ArgParse.c
@@ -7,12 +7,16 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define RED "\033[0;31m"
|
||||
#define BLUE "\033[0;34m"
|
||||
#define RESET "\033[0m"
|
||||
|
||||
static bool _AutoHelp = true; // 是否自动添加帮助信息
|
||||
static bool _COLOR = true; // 是否启用颜色
|
||||
|
||||
void argParseDisableAutoHelp() { _AutoHelp = false; }
|
||||
|
||||
ArgParse *argParseInit(char *documentation) {
|
||||
ArgParse *argParseInit(char *documentation, ArgParseValueType value_type) {
|
||||
ArgParse *argParse = malloc(sizeof(ArgParse));
|
||||
if (argParse == NULL) {
|
||||
return NULL;
|
||||
@@ -26,6 +30,9 @@ ArgParse *argParseInit(char *documentation) {
|
||||
argParse->argc = 0;
|
||||
argParse->argv = NULL;
|
||||
argParse->documentation = stringNewCopy(documentation);
|
||||
argParse->value_type = value_type;
|
||||
argParse->val = NULL;
|
||||
argParse->val_len = 0;
|
||||
|
||||
argParseAutoHelp(argParse);
|
||||
|
||||
@@ -34,15 +41,20 @@ ArgParse *argParseInit(char *documentation) {
|
||||
|
||||
/**
|
||||
* @brief 自动帮助信息回调函数
|
||||
* @param argParse ArgParse结构体指针
|
||||
* @param val 参数值
|
||||
* @param val_len 参数值长度
|
||||
* @return 无返回值,将直接结束程序
|
||||
*/
|
||||
int __helpCallback(ArgParse *argParse, char **val, int val_len) {
|
||||
NORETURN int __helpCallback(ArgParse *argParse, char **val, int val_len) {
|
||||
if (argParse == NULL) {
|
||||
return -1;
|
||||
exit(1);
|
||||
}
|
||||
char *help_doc = argParseGenerateHelp(argParse);
|
||||
printf("%s\n", help_doc);
|
||||
free(help_doc);
|
||||
return 0;
|
||||
argParseFree(argParse);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,7 +76,7 @@ void argParseAutoHelp(ArgParse *argParse) {
|
||||
NULL,
|
||||
__helpCallback,
|
||||
false,
|
||||
NOVALUE);
|
||||
ArgParseNOVALUE);
|
||||
}
|
||||
|
||||
int __commandHelpCallback(ArgParse *argParse, char **val, int val_len) {
|
||||
@@ -93,7 +105,7 @@ void argParseCommandAutoHelp(Command *command) {
|
||||
NULL,
|
||||
__commandHelpCallback,
|
||||
false,
|
||||
NOVALUE);
|
||||
ArgParseNOVALUE);
|
||||
}
|
||||
|
||||
Command *argParseAddCommand(ArgParse *argParse,
|
||||
@@ -259,7 +271,16 @@ void __freeCommand(Command *command) {
|
||||
free(command->sub_commands);
|
||||
free(command->name);
|
||||
free(command->help);
|
||||
free(command->args);
|
||||
free(command->default_val);
|
||||
|
||||
if (command->val_len > 0) {
|
||||
for (size_t i = 0; i < command->val_len; i++) {
|
||||
free(command->val[i]);
|
||||
}
|
||||
free(command->val);
|
||||
}
|
||||
|
||||
free(command);
|
||||
}
|
||||
|
||||
@@ -274,7 +295,15 @@ void argParseFree(ArgParse *argParse) {
|
||||
for (size_t i = 0; i < argParse->global_args_len; i++) {
|
||||
__freeCommandArgs(argParse->global_args[i]);
|
||||
}
|
||||
if (argParse->val_len > 0) {
|
||||
for (size_t i = 0; i < argParse->val_len; i++) {
|
||||
free(argParse->val[i]);
|
||||
}
|
||||
free(argParse->val);
|
||||
}
|
||||
|
||||
free(argParse->global_args);
|
||||
free(argParse->documentation);
|
||||
free(argParse);
|
||||
}
|
||||
/** End----------------内存释放API---------------- */
|
||||
@@ -294,7 +323,7 @@ int __processArgs(ArgParse *argParse, CommandArgs *arg, int arg_index) {
|
||||
|
||||
int current_index = arg_index;
|
||||
|
||||
if (arg->value_type == MULTIVALUE) {
|
||||
if (arg->value_type == ArgParseMULTIVALUE) {
|
||||
for (int i = arg_index + 1; i < argParse->argc; i++) {
|
||||
if (checkArgType(argParse->argv[i]) ==
|
||||
COMMAND) { // COMMAND是无--或-开头的字符串,也可认定为参数值
|
||||
@@ -305,12 +334,12 @@ int __processArgs(ArgParse *argParse, CommandArgs *arg, int arg_index) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (arg->value_type == SINGLEVALUE) {
|
||||
} else if (arg->value_type == ArgParseSINGLEVALUE) {
|
||||
if (arg_index + 1 < argParse->argc) {
|
||||
argParseSetArgVal(arg, argParse->argv[arg_index + 1]);
|
||||
current_index = arg_index + 1;
|
||||
}
|
||||
} else if (arg->value_type == NOVALUE) {
|
||||
} else if (arg->value_type == ArgParseNOVALUE) {
|
||||
current_index = arg_index;
|
||||
}
|
||||
|
||||
@@ -369,27 +398,81 @@ int __processSubCommand(ArgParse *argParse,
|
||||
return -1;
|
||||
}
|
||||
|
||||
int __processVal(ArgParse *argParse, int index) {
|
||||
CommandArgs *arg = NULL;
|
||||
|
||||
for (int i = index; i < argParse->argc; i++) {
|
||||
ArgType argType = checkArgType(argParse->argv[i]);
|
||||
switch (argType) {
|
||||
case COMMAND:
|
||||
argParseSetVal(argParse, argParse->argv[i]);
|
||||
break;
|
||||
case LONG_ARG:
|
||||
// 处理全局命令长选项
|
||||
arg = argParseFindGlobalArgs(argParse, argParse->argv[i], false);
|
||||
if (arg == NULL) {
|
||||
char *msg = argParseGenerateArgErrorMsg(
|
||||
argParse, argParse->argv[i], false);
|
||||
argParseError(argParse, argParse->current_command, msg, NULL);
|
||||
return -1;
|
||||
}
|
||||
i = __processArgs(argParse, arg, i);
|
||||
break;
|
||||
case SHORT_ARG:
|
||||
// 处理全局命令短选项
|
||||
arg = argParseFindGlobalArgs(argParse, argParse->argv[i], true);
|
||||
if (arg == NULL) {
|
||||
char *msg = argParseGenerateArgErrorMsg(
|
||||
argParse, argParse->argv[i], true);
|
||||
argParseError(argParse, argParse->current_command, msg, NULL);
|
||||
return -1; // 错误处理
|
||||
}
|
||||
i = __processArgs(
|
||||
argParse, arg, i); // 解析参数值并返回以解析到的索引位置
|
||||
break;
|
||||
default:
|
||||
argParseError(
|
||||
argParse, argParse->current_command, "unknown error", NULL);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return argParse->argc - 1;
|
||||
}
|
||||
|
||||
// 处理命令参数
|
||||
|
||||
int __processCommand(ArgParse *argParse, char *name, int command_index) {
|
||||
Command *command = argParseFindCommand(argParse, name);
|
||||
if (command == NULL) {
|
||||
CommandArgs *arg = NULL;
|
||||
Command *command = NULL;
|
||||
|
||||
argParseError(argParse, command, "Command not found", NULL);
|
||||
command = argParseFindCommand(argParse, name); // 查找命令
|
||||
|
||||
if (command == NULL && argParse->value_type == ArgParseNOVALUE) {
|
||||
char *msg = NULL;
|
||||
if (name != NULL) {
|
||||
msg = stringNewCopy("\033[1;31mERROR\033[0m:");
|
||||
__catStr(&msg, 1, name);
|
||||
__catStr(&msg, 1, " is not a valid command");
|
||||
}
|
||||
|
||||
argParseError(argParse, command, msg, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
command->is_trigged = true; // 标记命令被触发
|
||||
if (command == NULL && argParse->value_type != ArgParseNOVALUE) {
|
||||
return __processVal(argParse, command_index);
|
||||
}
|
||||
|
||||
CommandArgs *arg = NULL;
|
||||
argParse->current_command = command;
|
||||
if (command != NULL) {
|
||||
command->is_trigged = true; // 标记命令被触发
|
||||
argParse->current_command = command;
|
||||
}
|
||||
|
||||
for (int i = command_index + 1; i < argParse->argc; i++) {
|
||||
ArgType argType = checkArgType(argParse->argv[i]);
|
||||
switch (argType) {
|
||||
case COMMAND:
|
||||
case COMMAND: {
|
||||
// 命令无值则处理子命令
|
||||
if (command->value_type == NOVALUE) {
|
||||
if (command->value_type == ArgParseNOVALUE) {
|
||||
__processSubCommand(argParse, command, argParse->argv[i], i);
|
||||
return argParse->argc - 1;
|
||||
} else {
|
||||
@@ -397,6 +480,7 @@ int __processCommand(ArgParse *argParse, char *name, int command_index) {
|
||||
argParseSetCommandVal(command, argParse->argv[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LONG_ARG:
|
||||
// 处理命令长选项
|
||||
arg = argParseFindCommandArgs(command, argParse->argv[i], false);
|
||||
@@ -448,6 +532,7 @@ int __processCommand(ArgParse *argParse, char *name, int command_index) {
|
||||
|
||||
/**
|
||||
* @brief 解析命令行参数
|
||||
* @errors: 错误信息字符串统一又调用方申请,处理函数释放
|
||||
* @param argParse 解析器指针
|
||||
* @param argc 参数个数
|
||||
* @param argv 参数列表
|
||||
@@ -462,6 +547,7 @@ void argParseParse(ArgParse *argParse, int argc, char *argv[]) {
|
||||
ArgType argType = checkArgType(argv[i]);
|
||||
switch (argType) {
|
||||
case COMMAND:
|
||||
// 处理命令
|
||||
i = __processCommand(argParse, argv[i], i);
|
||||
break;
|
||||
case LONG_ARG: // 处理全局长选项
|
||||
@@ -498,6 +584,47 @@ void argParseParse(ArgParse *argParse, int argc, char *argv[]) {
|
||||
argParse->current_command->val,
|
||||
argParse->current_command->val_len);
|
||||
}
|
||||
|
||||
// 检查全局参数必填参数是否已设置
|
||||
for (int i = 0; i < argParse->global_args_len; i++) {
|
||||
if (argParse->global_args[i]->required &&
|
||||
argParse->global_args[i]->is_trigged == false) {
|
||||
// 错误处理,必填全局参数未设置
|
||||
char *msg =
|
||||
stringNewCopy(RED "ERROR" RESET ": Global Option " BLUE);
|
||||
if (argParse->global_args[i]->short_opt != NULL) {
|
||||
__catStr(&msg, 1, argParse->global_args[i]->short_opt);
|
||||
} else {
|
||||
__catStr(&msg, 1, argParse->global_args[i]->long_opt);
|
||||
}
|
||||
__catStr(&msg, 1, RESET " is required");
|
||||
argParseError(argParse, NULL, msg,
|
||||
NULL); // 错误处理
|
||||
}
|
||||
}
|
||||
|
||||
// 检查当前命令的必填参数是否已设置
|
||||
if (argParse->current_command != NULL) {
|
||||
for (int i = 0; i < argParse->current_command->args_len; i++) {
|
||||
if (argParse->current_command->args[i]->required &&
|
||||
argParse->current_command->args[i]->is_trigged == false) {
|
||||
// 错误处理,必填参数未设置
|
||||
char *msg = stringNewCopy(RED "ERROR" RESET ": Command " BLUE);
|
||||
__catStr(&msg, 1, argParse->current_command->name);
|
||||
__catStr(&msg, 1, RESET " Option " BLUE);
|
||||
if (argParse->current_command->args[i]->short_opt != NULL) {
|
||||
__catStr(
|
||||
&msg, 1, argParse->current_command->args[i]->short_opt);
|
||||
} else {
|
||||
__catStr(
|
||||
&msg, 1, argParse->current_command->args[i]->long_opt);
|
||||
}
|
||||
__catStr(&msg, 1, RESET " is required");
|
||||
argParseError(
|
||||
argParse, argParse->current_command, msg, NULL); // 错误处理
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -638,44 +765,27 @@ char **argParseGetGlobalArgList(ArgParse *argParse, char *opt, int *len) {
|
||||
return arg->val;
|
||||
}
|
||||
|
||||
size_t __getStrlen(char *str) {
|
||||
if (str == NULL) {
|
||||
return 0;
|
||||
char **argParseGetValList(ArgParse *argParse, int *len) {
|
||||
if (argParse == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return strlen(str);
|
||||
|
||||
if (argParse->val_len == 0) {
|
||||
return NULL;
|
||||
}
|
||||
*len = argParse->val_len;
|
||||
return argParse->val;
|
||||
}
|
||||
|
||||
void __catStr(char **dst, int count, ...) {
|
||||
va_list args;
|
||||
va_start(args, count);
|
||||
|
||||
size_t total_len = 0;
|
||||
total_len = __getStrlen(*dst);
|
||||
|
||||
// 计算总长度
|
||||
char *temp = NULL;
|
||||
for (int i = 0; i < count; i++) {
|
||||
temp = va_arg(args, char *);
|
||||
total_len += __getStrlen(temp);
|
||||
}
|
||||
va_end(args);
|
||||
|
||||
// 分配内存
|
||||
*dst = realloc(*dst, total_len + 1); // +1 是为了存储字符串结束符 '\0'
|
||||
if (*dst == NULL) {
|
||||
va_end(args);
|
||||
return; // 处理内存分配失败
|
||||
char *argParseGetVal(ArgParse *argParse) {
|
||||
if (argParse == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// 拼接字符串
|
||||
va_start(args, count);
|
||||
temp = NULL;
|
||||
for (int i = 0; i < count; i++) {
|
||||
temp = va_arg(args, char *);
|
||||
strcat(*dst, temp);
|
||||
if (argParse->val_len == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
return argParse->val[0];
|
||||
}
|
||||
|
||||
char *argParseGenerateHelpForCommand(Command *command) {
|
||||
@@ -692,12 +802,12 @@ char *argParseGenerateHelpForCommand(Command *command) {
|
||||
__catStr(&help_msg, 2, "\033[1;33mUsage\033[0m: ", command->name);
|
||||
|
||||
switch (command->value_type) {
|
||||
case NOVALUE:
|
||||
case ArgParseNOVALUE:
|
||||
break;
|
||||
case SINGLEVALUE:
|
||||
case ArgParseSINGLEVALUE:
|
||||
__catStr(&help_msg, 1, " <value>");
|
||||
break;
|
||||
case MULTIVALUE:
|
||||
case ArgParseMULTIVALUE:
|
||||
__catStr(&help_msg, 1, " <value>...");
|
||||
}
|
||||
|
||||
@@ -759,25 +869,40 @@ bool argParseCheckCommandTriggered(ArgParse *argParse, char *command_name) {
|
||||
return command->is_trigged;
|
||||
}
|
||||
|
||||
_Noreturn void argParseError(ArgParse *argParse,
|
||||
Command *lastCommand,
|
||||
char *prefix,
|
||||
char *suffix) {
|
||||
NORETURN void argParseError(ArgParse *argParse,
|
||||
Command *lastCommand,
|
||||
const char *prefix,
|
||||
const char *suffix) {
|
||||
if (argParse == NULL) {
|
||||
printf("ERROR: Parse is NULL\n");
|
||||
exit(1);
|
||||
}
|
||||
if (lastCommand == NULL) {
|
||||
char *mgs = stringNewCopy("");
|
||||
if (prefix != NULL) {
|
||||
__catStr(&mgs, 1, prefix);
|
||||
}
|
||||
char *help = argParseGenerateHelp(argParse);
|
||||
printf("\033[1;31mERROR\033[0m: Last command is unknown\n");
|
||||
printf("%s\n", help);
|
||||
|
||||
if (help != NULL) {
|
||||
__catStr(&mgs, 2, "\n", help);
|
||||
}
|
||||
|
||||
if (suffix != NULL) {
|
||||
__catStr(&mgs, 2, "\n", suffix);
|
||||
}
|
||||
|
||||
printf("%s\n", mgs);
|
||||
free(mgs);
|
||||
free(help);
|
||||
argParseFree(argParse);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *ErrorMsg = NULL;
|
||||
|
||||
if (prefix != NULL) {
|
||||
ErrorMsg = stringNewCopy(prefix);
|
||||
ErrorMsg = stringNewCopy((char *)prefix);
|
||||
}
|
||||
|
||||
char *command_help_msg = argParseGenerateHelpForCommand(lastCommand);
|
||||
@@ -794,8 +919,7 @@ _Noreturn void argParseError(ArgParse *argParse,
|
||||
printf("%s\n", ErrorMsg);
|
||||
free(ErrorMsg);
|
||||
free(command_help_msg);
|
||||
free(prefix);
|
||||
free(suffix);
|
||||
argParseFree(argParse);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "ArgParseTools.h"
|
||||
#include "ArgParse.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -177,7 +179,7 @@ argParseFindGlobalArgs(ArgParse *argParse, char *name, bool short_flag) {
|
||||
* @return 成功返回true,失败返回false
|
||||
*/
|
||||
bool argParseSetArgVal(CommandArgs *args, char *val) {
|
||||
if (args->value_type == MULTIVALUE) { // 多值
|
||||
if (args->value_type == ArgParseMULTIVALUE) { // 多值
|
||||
args->val = realloc(args->val, (args->val_len + 1) * sizeof(char *));
|
||||
if (args->val == NULL) {
|
||||
return false;
|
||||
@@ -188,7 +190,7 @@ bool argParseSetArgVal(CommandArgs *args, char *val) {
|
||||
}
|
||||
args->val_len++;
|
||||
return true;
|
||||
} else if (args->value_type == SINGLEVALUE) { // 单值
|
||||
} else if (args->value_type == ArgParseSINGLEVALUE) { // 单值
|
||||
if (args->val != NULL) {
|
||||
free(args->val);
|
||||
}
|
||||
@@ -203,7 +205,7 @@ bool argParseSetArgVal(CommandArgs *args, char *val) {
|
||||
}
|
||||
args->val_len = 1;
|
||||
return true;
|
||||
} else if (args->value_type == NOVALUE) { // 无值
|
||||
} else if (args->value_type == ArgParseNOVALUE) { // 无值
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -211,7 +213,7 @@ bool argParseSetArgVal(CommandArgs *args, char *val) {
|
||||
}
|
||||
|
||||
bool argParseSetCommandVal(Command *command, char *val) {
|
||||
if (command->value_type == MULTIVALUE) { // 多值
|
||||
if (command->value_type == ArgParseMULTIVALUE) { // 多值
|
||||
command->val =
|
||||
realloc(command->val, (command->val_len + 1) * sizeof(char *));
|
||||
if (command->val == NULL) {
|
||||
@@ -223,7 +225,7 @@ bool argParseSetCommandVal(Command *command, char *val) {
|
||||
}
|
||||
command->val_len++;
|
||||
return true;
|
||||
} else if (command->value_type == SINGLEVALUE) { // 单值
|
||||
} else if (command->value_type == ArgParseSINGLEVALUE) { // 单值
|
||||
if (command->val != NULL) {
|
||||
free(command->val);
|
||||
}
|
||||
@@ -238,8 +240,89 @@ bool argParseSetCommandVal(Command *command, char *val) {
|
||||
}
|
||||
command->val_len = 1;
|
||||
return true;
|
||||
} else if (command->value_type == NOVALUE) { // 无值
|
||||
} else if (command->value_type == ArgParseNOVALUE) { // 无值
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置解析值,该值为程序所需的无命令值例如`gcc mian.c`的`main.c`
|
||||
* @param argParse 解析器
|
||||
* @param val 值
|
||||
* @return 成功返回true,失败返回false
|
||||
*/
|
||||
bool argParseSetVal(ArgParse *argParse, char *val) {
|
||||
|
||||
if (argParse->value_type == ArgParseMULTIVALUE) { // 多值
|
||||
argParse->val =
|
||||
realloc(argParse->val, (argParse->val_len + 1) * sizeof(char *));
|
||||
if (argParse->val == NULL) {
|
||||
return false;
|
||||
}
|
||||
argParse->val[argParse->val_len] = stringNewCopy(val);
|
||||
if (argParse->val[argParse->val_len] == NULL) {
|
||||
return false;
|
||||
}
|
||||
argParse->val_len++;
|
||||
return true;
|
||||
} else if (argParse->value_type == ArgParseSINGLEVALUE) { // 单值
|
||||
if (argParse->val != NULL) {
|
||||
free(argParse->val);
|
||||
}
|
||||
argParse->val = malloc(sizeof(char *));
|
||||
|
||||
if (argParse->val == NULL) {
|
||||
return false;
|
||||
}
|
||||
argParse->val[0] = stringNewCopy(val); // 分配内存
|
||||
if (argParse->val[0] == NULL) {
|
||||
return false;
|
||||
}
|
||||
argParse->val_len = 1;
|
||||
return true;
|
||||
} else if (argParse->value_type == ArgParseNOVALUE) { // 无值
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t __getStrlen(char *str) {
|
||||
if (str == NULL) {
|
||||
return 0;
|
||||
}
|
||||
return strlen(str);
|
||||
}
|
||||
|
||||
void __catStr(char **dst, int count, ...) {
|
||||
va_list args;
|
||||
va_start(args, count);
|
||||
|
||||
size_t total_len = 0;
|
||||
total_len = __getStrlen(*dst);
|
||||
|
||||
// 计算总长度
|
||||
char *temp = NULL;
|
||||
for (int i = 0; i < count; i++) {
|
||||
temp = va_arg(args, char *);
|
||||
total_len += __getStrlen(temp);
|
||||
}
|
||||
va_end(args);
|
||||
|
||||
// 分配内存
|
||||
*dst = realloc(*dst, total_len + 1); // +1 是为了存储字符串结束符 '\0'
|
||||
if (*dst == NULL) {
|
||||
va_end(args);
|
||||
return; // 处理内存分配失败
|
||||
}
|
||||
|
||||
// 拼接字符串
|
||||
va_start(args, count);
|
||||
temp = NULL;
|
||||
for (int i = 0; i < count; i++) {
|
||||
temp = va_arg(args, char *);
|
||||
strcat(*dst, temp);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "ArgParse.h"
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -25,14 +26,14 @@ Command *createCommand(char *name,
|
||||
CommandGroup *createCommandGroup(char *name, char *help); // 创建命令组
|
||||
|
||||
CommandGroup *addCommandToGroup(CommandGroup *group,
|
||||
Command *command); // 添加命令到命令组
|
||||
Command *command); // 添加命令到命令组
|
||||
|
||||
CommandArgs *createCommandArgs(char *short_opt,
|
||||
char *long_opt,
|
||||
char *default_val,
|
||||
char *help,
|
||||
ArgParseCallback callback,
|
||||
bool required,
|
||||
CommandArgs *createCommandArgs(char *short_opt,
|
||||
char *long_opt,
|
||||
char *default_val,
|
||||
char *help,
|
||||
ArgParseCallback callback,
|
||||
bool required,
|
||||
ArgParseValueType value_type); // 创建命令参数
|
||||
|
||||
/**
|
||||
@@ -45,6 +46,8 @@ bool argParseSetArgVal(CommandArgs *args, char *val); // 设置命令参数值
|
||||
|
||||
bool argParseSetCommandVal(Command *command, char *val); // 设置命令值
|
||||
|
||||
bool argParseSetVal(ArgParse *argParse, char *val); // 设置值
|
||||
|
||||
ArgType checkArgType(char *arg); // 检查参数类型
|
||||
|
||||
Command *argParseFindCommand(ArgParse *argParse, char *name); // 查找命令
|
||||
@@ -59,7 +62,9 @@ CommandArgs *argParseFindGlobalArgs(ArgParse *argParse,
|
||||
char *name,
|
||||
bool short_flag); // 查找全局参数
|
||||
|
||||
char *stringNewCopy(char *str); // 创建字符串副本
|
||||
char *stringNewCopy(char *str); // 创建字符串副本
|
||||
void __catStr(char **dst, int count, ...); // 字符串拼接
|
||||
size_t __getStrlen(char *str); // 获取字符串长度
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -32,3 +32,17 @@ add_executable(${PROJECT_NAME}unknow_command_arg test_unknow_command.c)
|
||||
target_link_libraries(${PROJECT_NAME}unknow_command_arg CArgParse)
|
||||
add_test(${PROJECT_NAME}unknow_command_arg ${PROJECT_NAME}unknow_command_arg install --unknow)
|
||||
set_tests_properties(${PROJECT_NAME}unknow_command_arg PROPERTIES WILL_FAIL TRUE)
|
||||
|
||||
# 未知命令选项测试,预期打印该命令的帮助信息
|
||||
add_executable(${PROJECT_NAME}val test_val.c)
|
||||
target_link_libraries(${PROJECT_NAME}val CArgParse)
|
||||
add_test(${PROJECT_NAME}val ${PROJECT_NAME}val file1.txt file2.txt file3.txt -v -q)
|
||||
|
||||
# 必填参数测试
|
||||
add_executable(${PROJECT_NAME}required test_required.c)
|
||||
target_link_libraries(${PROJECT_NAME}required CArgParse)
|
||||
add_test(${PROJECT_NAME}required_1 ${PROJECT_NAME}required -f)
|
||||
add_test(${PROJECT_NAME}required_2 ${PROJECT_NAME}required)
|
||||
set_tests_properties(${PROJECT_NAME}required_2 PROPERTIES WILL_FAIL TRUE)
|
||||
add_test(${PROJECT_NAME}required_3 ${PROJECT_NAME}required -h)
|
||||
add_test(${PROJECT_NAME}required_4 ${PROJECT_NAME}required -f install -h)
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <string.h>
|
||||
|
||||
ArgParse *initArgParse() {
|
||||
ArgParse *argparse = argParseInit("测试程序");
|
||||
ArgParse *argparse = argParseInit("测试程序", ArgParseNOVALUE);
|
||||
Command *command = NULL;
|
||||
Command *sub_command = NULL;
|
||||
|
||||
@@ -16,13 +16,24 @@ ArgParse *initArgParse() {
|
||||
NULL,
|
||||
NULL,
|
||||
false,
|
||||
NOVALUE);
|
||||
argParseAddGlobalArg(
|
||||
argparse, "-q", "--quiet", "Quiet mode", NULL, NULL, false, NOVALUE);
|
||||
ArgParseNOVALUE);
|
||||
argParseAddGlobalArg(argparse,
|
||||
"-q",
|
||||
"--quiet",
|
||||
"Quiet mode",
|
||||
NULL,
|
||||
NULL,
|
||||
false,
|
||||
ArgParseNOVALUE);
|
||||
|
||||
// add arguments
|
||||
command = argParseAddCommand(
|
||||
argparse, "install", "Install the package", NULL, NULL, NULL, NOVALUE);
|
||||
command = argParseAddCommand(argparse,
|
||||
"install",
|
||||
"Install the package",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
ArgParseNOVALUE);
|
||||
argParseAddArg(command,
|
||||
"-i",
|
||||
"--index",
|
||||
@@ -30,7 +41,7 @@ ArgParse *initArgParse() {
|
||||
"https://example.com",
|
||||
NULL,
|
||||
false,
|
||||
SINGLEVALUE);
|
||||
ArgParseSINGLEVALUE);
|
||||
argParseAddArg(command,
|
||||
"-f",
|
||||
"--file",
|
||||
@@ -38,7 +49,7 @@ ArgParse *initArgParse() {
|
||||
"package.json",
|
||||
NULL,
|
||||
false,
|
||||
MULTIVALUE);
|
||||
ArgParseMULTIVALUE);
|
||||
argParseAddArg(command,
|
||||
"-p",
|
||||
"--package",
|
||||
@@ -46,10 +57,15 @@ ArgParse *initArgParse() {
|
||||
"package.json",
|
||||
NULL,
|
||||
false,
|
||||
MULTIVALUE);
|
||||
ArgParseMULTIVALUE);
|
||||
|
||||
sub_command = argParseAddSubCommand(
|
||||
command, "tools", "Install tools", NULL, NULL, NULL, MULTIVALUE);
|
||||
sub_command = argParseAddSubCommand(command,
|
||||
"tools",
|
||||
"Install tools",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
ArgParseMULTIVALUE);
|
||||
|
||||
argParseAddArg(sub_command,
|
||||
"-t",
|
||||
@@ -58,9 +74,14 @@ ArgParse *initArgParse() {
|
||||
"Tool name",
|
||||
NULL,
|
||||
true,
|
||||
MULTIVALUE);
|
||||
sub_command = argParseAddSubCommand(
|
||||
command, "tools_sub", "Install tools", NULL, NULL, NULL, MULTIVALUE);
|
||||
ArgParseMULTIVALUE);
|
||||
sub_command = argParseAddSubCommand(command,
|
||||
"tools_sub",
|
||||
"Install tools",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
ArgParseMULTIVALUE);
|
||||
|
||||
argParseAddArg(sub_command,
|
||||
"-s",
|
||||
@@ -69,7 +90,7 @@ ArgParse *initArgParse() {
|
||||
"tools subcommand test",
|
||||
NULL,
|
||||
true,
|
||||
MULTIVALUE);
|
||||
ArgParseMULTIVALUE);
|
||||
|
||||
command = argParseAddCommand(argparse,
|
||||
"uninstall",
|
||||
@@ -77,7 +98,7 @@ ArgParse *initArgParse() {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
SINGLEVALUE);
|
||||
ArgParseSINGLEVALUE);
|
||||
argParseAddArg(command,
|
||||
"-p",
|
||||
"--package",
|
||||
@@ -85,7 +106,7 @@ ArgParse *initArgParse() {
|
||||
"Package name",
|
||||
NULL,
|
||||
true,
|
||||
MULTIVALUE);
|
||||
ArgParseMULTIVALUE);
|
||||
|
||||
return argparse;
|
||||
}
|
||||
@@ -10,12 +10,11 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
const char *testv[3] = {"testpackge1", "testpackge2", "testpackge3"};
|
||||
|
||||
|
||||
// Test -p
|
||||
char *val = argParseGetCurArg(argparse, "-p");
|
||||
char *val = argParseGetCurArg(argparse, "-p");
|
||||
|
||||
int len = 0;
|
||||
char **vals = argParseGetCurArgList(argparse, "-p", &len);
|
||||
int len = 0;
|
||||
char **vals = argParseGetCurArgList(argparse, "-p", &len);
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
printf("-p Value: %s\n", vals[i]);
|
||||
@@ -27,18 +26,15 @@ int main(int argc, char *argv[]) {
|
||||
printf("-i Value: %s\n", val_i);
|
||||
assert(strcmp(val_i, "www.test.com") == 0);
|
||||
|
||||
|
||||
|
||||
// Test -f
|
||||
len = 0;
|
||||
len = 0;
|
||||
const char *testf[2] = {"file1.txt", "file2.txt"};
|
||||
char **val_f = argParseGetCurArgList(argparse, "-f", &len);
|
||||
char **val_f = argParseGetCurArgList(argparse, "-f", &len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
printf("-f Value: %s\n", val_f[i]);
|
||||
assert(strcmp(val_f[i], testf[i]) == 0);
|
||||
}
|
||||
|
||||
|
||||
argParseFree(argparse);
|
||||
|
||||
return 0;
|
||||
|
||||
144
tests/test_required.c
Normal file
144
tests/test_required.c
Normal file
@@ -0,0 +1,144 @@
|
||||
#include "ArgParse.h"
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
ArgParse *initArgParse() {
|
||||
ArgParse *argparse = argParseInit("测试程序", ArgParseNOVALUE);
|
||||
Command *command = NULL;
|
||||
Command *sub_command = NULL;
|
||||
|
||||
// add global arguments
|
||||
argParseAddGlobalArg(argparse,
|
||||
"-v",
|
||||
"--version",
|
||||
"Show version",
|
||||
NULL,
|
||||
NULL,
|
||||
false,
|
||||
ArgParseNOVALUE);
|
||||
argParseAddGlobalArg(argparse,
|
||||
"-f",
|
||||
"--file",
|
||||
"File name",
|
||||
NULL,
|
||||
NULL,
|
||||
true,
|
||||
ArgParseNOVALUE);
|
||||
|
||||
// add arguments
|
||||
command = argParseAddCommand(argparse,
|
||||
"install",
|
||||
"Install the package",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
ArgParseNOVALUE);
|
||||
argParseAddArg(command,
|
||||
"-i",
|
||||
"--index",
|
||||
"Index URL",
|
||||
"https://example.com",
|
||||
NULL,
|
||||
false,
|
||||
ArgParseSINGLEVALUE);
|
||||
argParseAddArg(command,
|
||||
"-f",
|
||||
"--file",
|
||||
"Package file",
|
||||
"package.json",
|
||||
NULL,
|
||||
true,
|
||||
ArgParseMULTIVALUE);
|
||||
argParseAddArg(command,
|
||||
"-p",
|
||||
"--package",
|
||||
"Package file",
|
||||
"package.json",
|
||||
NULL,
|
||||
false,
|
||||
ArgParseMULTIVALUE);
|
||||
|
||||
sub_command = argParseAddSubCommand(command,
|
||||
"tools",
|
||||
"Install tools",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
ArgParseMULTIVALUE);
|
||||
|
||||
argParseAddArg(sub_command,
|
||||
"-t",
|
||||
"--tool",
|
||||
"Tool name",
|
||||
"Tool name",
|
||||
NULL,
|
||||
true,
|
||||
ArgParseMULTIVALUE);
|
||||
sub_command = argParseAddSubCommand(command,
|
||||
"tools_sub",
|
||||
"Install tools",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
ArgParseMULTIVALUE);
|
||||
|
||||
argParseAddArg(sub_command,
|
||||
"-s",
|
||||
"--source",
|
||||
"test_source",
|
||||
"tools subcommand test",
|
||||
NULL,
|
||||
true,
|
||||
ArgParseMULTIVALUE);
|
||||
|
||||
command = argParseAddCommand(argparse,
|
||||
"uninstall",
|
||||
"Uninstall the package",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
ArgParseSINGLEVALUE);
|
||||
argParseAddArg(command,
|
||||
"-p",
|
||||
"--package",
|
||||
"Package name",
|
||||
"Package name",
|
||||
NULL,
|
||||
true,
|
||||
ArgParseMULTIVALUE);
|
||||
|
||||
return argparse;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
ArgParse *argparse = initArgParse();
|
||||
|
||||
argParseParse(argparse, argc, argv);
|
||||
|
||||
char *val = argParseGetVal(argparse);
|
||||
if (val) {
|
||||
printf("val: %s\n", val);
|
||||
}
|
||||
|
||||
// int len = 0;
|
||||
// char **vals = argParseGetValList(argparse, &len);
|
||||
|
||||
// char *test_val[3] = {"file1.txt", "file2.txt", "file3.txt"};
|
||||
|
||||
// if (vals) {
|
||||
// for (int i = 0; i < len; i++) {
|
||||
// printf("vals: %s\n", vals[i]);
|
||||
// assert(strcmp(vals[i], test_val[i]) == 0);
|
||||
// }
|
||||
// }
|
||||
|
||||
// assert(argParseCheckGlobalTriggered(argparse, "-v"));
|
||||
// assert(argParseCheckGlobalTriggered(argparse, "-f"));
|
||||
|
||||
argParseFree(argparse);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -10,10 +10,10 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
const char *testv[3] = {"testpackge1", "testpackge2", "testpackge3"};
|
||||
|
||||
char *val = argParseGetCurArg(argparse, "-p");
|
||||
char *val = argParseGetCurArg(argparse, "-p");
|
||||
|
||||
int len = 0;
|
||||
char **vals = argParseGetCurArgList(argparse, "-p", &len);
|
||||
int len = 0;
|
||||
char **vals = argParseGetCurArgList(argparse, "-p", &len);
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
printf("-p Value: %s\n", vals[i]);
|
||||
|
||||
@@ -8,12 +8,11 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
argParseParse(argparse, argc, argv);
|
||||
|
||||
|
||||
char *command_name = argParseGetCurCommandName(argparse);
|
||||
printf("command name: %s\n", command_name);
|
||||
assert(strcmp(command_name, "tools") == 0);
|
||||
|
||||
char * val = argParseGetCurArg(argparse, "-t");
|
||||
char *val = argParseGetCurArg(argparse, "-t");
|
||||
printf("tools -t: %s\n", val);
|
||||
|
||||
argParseFree(argparse);
|
||||
|
||||
@@ -7,7 +7,6 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
argParseParse(argparse, argc, argv);
|
||||
|
||||
|
||||
argParseFree(argparse);
|
||||
|
||||
return 0;
|
||||
|
||||
143
tests/test_val.c
Normal file
143
tests/test_val.c
Normal file
@@ -0,0 +1,143 @@
|
||||
#include "ArgParse.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
ArgParse *initArgParse() {
|
||||
ArgParse *argparse = argParseInit("测试程序", ArgParseMULTIVALUE);
|
||||
Command *command = NULL;
|
||||
Command *sub_command = NULL;
|
||||
|
||||
// add global arguments
|
||||
argParseAddGlobalArg(argparse,
|
||||
"-v",
|
||||
"--version",
|
||||
"Show version",
|
||||
NULL,
|
||||
NULL,
|
||||
false,
|
||||
ArgParseNOVALUE);
|
||||
argParseAddGlobalArg(argparse,
|
||||
"-q",
|
||||
"--quiet",
|
||||
"Quiet mode",
|
||||
NULL,
|
||||
NULL,
|
||||
false,
|
||||
ArgParseNOVALUE);
|
||||
|
||||
// add arguments
|
||||
command = argParseAddCommand(argparse,
|
||||
"install",
|
||||
"Install the package",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
ArgParseNOVALUE);
|
||||
argParseAddArg(command,
|
||||
"-i",
|
||||
"--index",
|
||||
"Index URL",
|
||||
"https://example.com",
|
||||
NULL,
|
||||
false,
|
||||
ArgParseSINGLEVALUE);
|
||||
argParseAddArg(command,
|
||||
"-f",
|
||||
"--file",
|
||||
"Package file",
|
||||
"package.json",
|
||||
NULL,
|
||||
false,
|
||||
ArgParseMULTIVALUE);
|
||||
argParseAddArg(command,
|
||||
"-p",
|
||||
"--package",
|
||||
"Package file",
|
||||
"package.json",
|
||||
NULL,
|
||||
false,
|
||||
ArgParseMULTIVALUE);
|
||||
|
||||
sub_command = argParseAddSubCommand(command,
|
||||
"tools",
|
||||
"Install tools",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
ArgParseMULTIVALUE);
|
||||
|
||||
argParseAddArg(sub_command,
|
||||
"-t",
|
||||
"--tool",
|
||||
"Tool name",
|
||||
"Tool name",
|
||||
NULL,
|
||||
true,
|
||||
ArgParseMULTIVALUE);
|
||||
sub_command = argParseAddSubCommand(command,
|
||||
"tools_sub",
|
||||
"Install tools",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
ArgParseMULTIVALUE);
|
||||
|
||||
argParseAddArg(sub_command,
|
||||
"-s",
|
||||
"--source",
|
||||
"test_source",
|
||||
"tools subcommand test",
|
||||
NULL,
|
||||
true,
|
||||
ArgParseMULTIVALUE);
|
||||
|
||||
command = argParseAddCommand(argparse,
|
||||
"uninstall",
|
||||
"Uninstall the package",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
ArgParseSINGLEVALUE);
|
||||
argParseAddArg(command,
|
||||
"-p",
|
||||
"--package",
|
||||
"Package name",
|
||||
"Package name",
|
||||
NULL,
|
||||
true,
|
||||
ArgParseMULTIVALUE);
|
||||
|
||||
return argparse;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
ArgParse *argparse = initArgParse();
|
||||
|
||||
argParseParse(argparse, argc, argv);
|
||||
|
||||
char *val = argParseGetVal(argparse);
|
||||
if (val) {
|
||||
printf("val: %s\n", val);
|
||||
}
|
||||
|
||||
int len = 0;
|
||||
char **vals = argParseGetValList(argparse, &len);
|
||||
|
||||
char *test_val[3] = {"file1.txt", "file2.txt", "file3.txt"};
|
||||
|
||||
if (vals) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
printf("vals: %s\n", vals[i]);
|
||||
assert(strcmp(vals[i], test_val[i]) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
assert(argParseCheckGlobalTriggered(argparse, "-v"));
|
||||
assert(argParseCheckGlobalTriggered(argparse, "-q"));
|
||||
|
||||
argParseFree(argparse);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user