Compare commits
	
		
			18 Commits
		
	
	
		
	
	| 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. | ||||||
							
								
								
									
										189
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										189
									
								
								README.md
									
									
									
									
									
								
							| @@ -5,8 +5,13 @@ C语言易用的命令参数分析 | |||||||
|  |  | ||||||
| # 特性 | # 特性 | ||||||
| - 自动生成帮助信息 | - 自动生成帮助信息 | ||||||
|  | - 命令自动帮助信息 | ||||||
| - 默认值支持 | - 默认值支持 | ||||||
| - 子命令支持 | - 子命令支持 | ||||||
|  | - 命令参数支持 | ||||||
|  | - 全局参数 | ||||||
|  | - 互斥参数(即将) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # 安装 | # 安装 | ||||||
| @@ -29,7 +34,7 @@ conan create . | |||||||
|  |  | ||||||
|  |  | ||||||
| ## 示例程序 | ## 示例程序 | ||||||
| 构建简单的命令行程序 | 构建简单的命令行程序,更多示例请参考`example`目录 | ||||||
| ```c | ```c | ||||||
| #include "ArgParse.h" | #include "ArgParse.h" | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
| @@ -37,11 +42,11 @@ conan create . | |||||||
| #include <string.h> | #include <string.h> | ||||||
|  |  | ||||||
| ArgParse *Init() { | ArgParse *Init() { | ||||||
|     ArgParse *ap = argParseInit("简单的命令行工具示例"); |     ArgParse *ap = argParseInit("简单的命令行工具示例",ArgParseNOVALUE); | ||||||
|  |  | ||||||
|     // 添加第一个命令 |     // 添加第一个命令 | ||||||
|     Command *cmd = argParseAddCommand( |     Command *cmd = argParseAddCommand( | ||||||
|         ap, "list", "列出文件列表", NULL, NULL, NULL, SINGLEVALUE); |         ap, "list", "列出文件列表", NULL, NULL, NULL, ArgParseSINGLEVALUE); | ||||||
|  |  | ||||||
|     // 添加第一个命令的参数 |     // 添加第一个命令的参数 | ||||||
|     argParseAddArg(cmd, |     argParseAddArg(cmd, | ||||||
| @@ -51,7 +56,7 @@ ArgParse *Init() { | |||||||
|                    NULL, |                    NULL, | ||||||
|                    NULL, |                    NULL, | ||||||
|                    false, |                    false, | ||||||
|                    NOVALUE); |                    ArgParseNOVALUE); | ||||||
|  |  | ||||||
|     return ap; |     return ap; | ||||||
| } | } | ||||||
| @@ -78,3 +83,179 @@ int main(int argc, char *argv[]) { | |||||||
| example -h | 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): | class loggingRecipe(ConanFile): | ||||||
|     name = "cargparse" |     name = "cargparse" | ||||||
|     version = "0.2.0" |     version = "0.3.2" | ||||||
|     license = "MIT" |     license = "MIT" | ||||||
|     author = "321640253@qq.com" |     author = "321640253@qq.com" | ||||||
|     url = "https://gitea.youmetme.wang/youmetme/logging" |     url = "https://gitea.youmetme.wang/youmetme/logging" | ||||||
|   | |||||||
| @@ -4,11 +4,11 @@ | |||||||
| #include <string.h> | #include <string.h> | ||||||
|  |  | ||||||
| ArgParse *Init() { | ArgParse *Init() { | ||||||
|     ArgParse *ap = argParseInit("简单的命令行工具示例"); |     ArgParse *ap = argParseInit("简单的命令行工具示例",ArgParseNOVALUE); | ||||||
|  |  | ||||||
|     // 添加第一个命令 |     // 添加第一个命令 | ||||||
|     Command *cmd = argParseAddCommand( |     Command *cmd = argParseAddCommand( | ||||||
|         ap, "list", "列出文件列表", NULL, NULL, NULL, SINGLEVALUE); |         ap, "list", "列出文件列表", NULL, NULL, NULL, ArgParseSINGLEVALUE); | ||||||
|  |  | ||||||
|     // 添加第一个命令的参数 |     // 添加第一个命令的参数 | ||||||
|     argParseAddArg(cmd, |     argParseAddArg(cmd, | ||||||
| @@ -18,7 +18,7 @@ ArgParse *Init() { | |||||||
|                    NULL, |                    NULL, | ||||||
|                    NULL, |                    NULL, | ||||||
|                    false, |                    false, | ||||||
|                    NOVALUE); |                    ArgParseNOVALUE); | ||||||
|  |  | ||||||
|     return ap; |     return ap; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -7,6 +7,12 @@ | |||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #ifdef _MSC_VER | ||||||
|  | #define NORETURN __declspec(noreturn) | ||||||
|  | #else | ||||||
|  | #define NORETURN _Noreturn | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #define ARG_DEFAULT_HELP_FLAG "--help" | #define ARG_DEFAULT_HELP_FLAG "--help" | ||||||
|  |  | ||||||
| typedef struct ArgParse ArgParse; // 解析器 | typedef struct ArgParse ArgParse; // 解析器 | ||||||
| @@ -16,9 +22,9 @@ typedef int (*ArgParseCallback)(ArgParse *argParse, | |||||||
|                                 int       val_len); // 回调函数 |                                 int       val_len); // 回调函数 | ||||||
|  |  | ||||||
| typedef enum { | typedef enum { | ||||||
|     NOVALUE = 0,     // 无值 |     ArgParseNOVALUE = 0, // 无值 | ||||||
|     SINGLEVALUE,     // 单值 例如: -i https://www.baidu.com |     ArgParseSINGLEVALUE, // 单值 例如: -i https://www.baidu.com | ||||||
|     MULTIVALUE,      // 多值 例如: -s a b c 或 -s a -s b -s c等 |     ArgParseMULTIVALUE,  // 多值 例如: -s a b c 或 -s a -s b -s c等 | ||||||
| } ArgParseValueType;     // 值类型 | } ArgParseValueType;     // 值类型 | ||||||
|  |  | ||||||
| typedef struct CommandArgs { | typedef struct CommandArgs { | ||||||
| @@ -69,8 +75,12 @@ typedef struct ArgParse { | |||||||
|     struct CommandArgs **global_args;     // 全局参数 |     struct CommandArgs **global_args;     // 全局参数 | ||||||
|     int                  global_args_len; // 全局参数个数 |     int                  global_args_len; // 全局参数个数 | ||||||
|     char                *documentation;   // 帮助文档 |     char                *documentation;   // 帮助文档 | ||||||
|  |     ArgParseValueType    value_type; // 值类型 程序默认需要的值例如 gcc main.c | ||||||
|  |  | ||||||
|     /* 解析所用到的属性*/ |     /* 解析所用到的属性*/ | ||||||
|     struct Command *current_command; // 当前解析到的命令 |     struct Command *current_command; // 当前解析到的命令 | ||||||
|  |     char          **val; | ||||||
|  |     int             val_len; | ||||||
|     int             argc; // 参数个数 |     int             argc; // 参数个数 | ||||||
|     char          **argv; // 参数列表 |     char          **argv; // 参数列表 | ||||||
| } ArgParse; | } ArgParse; | ||||||
| @@ -79,9 +89,11 @@ typedef struct ArgParse { | |||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @brief 初始化解析器 |  * @brief 初始化解析器 | ||||||
|  |  * @param documentation 帮助文档 | ||||||
|  |  * @param value_type 值类型,程序默认需要的值例如 gcc main.c | ||||||
|  * @return ArgParse* 解析器指针 |  * @return ArgParse* 解析器指针 | ||||||
|  */ |  */ | ||||||
| ArgParse *argParseInit(char *documentation); | ArgParse *argParseInit(char *documentation, ArgParseValueType value_type); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @brief 释放解析器 |  * @brief 释放解析器 | ||||||
| @@ -268,6 +280,9 @@ bool argParseCheckCommandTriggered(ArgParse *argParse, char *command_name); | |||||||
|  */ |  */ | ||||||
| bool argParseCheckGlobalTriggered(ArgParse *argParse, char *opt); | bool argParseCheckGlobalTriggered(ArgParse *argParse, char *opt); | ||||||
|  |  | ||||||
|  | char  *argParseGetVal(ArgParse *argParse); | ||||||
|  | char **argParseGetValList(ArgParse *argParse, int *len); | ||||||
|  |  | ||||||
| /** End----------------解析API---------------- */ | /** End----------------解析API---------------- */ | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -294,10 +309,10 @@ char *argParseGenerateHelp(ArgParse *argParse); | |||||||
| char * | char * | ||||||
| argParseGenerateArgErrorMsg(ArgParse *argParse, char *name, bool short_flag); | argParseGenerateArgErrorMsg(ArgParse *argParse, char *name, bool short_flag); | ||||||
|  |  | ||||||
| _Noreturn void argParseError(ArgParse *argParse, | NORETURN void argParseError(ArgParse   *argParse, | ||||||
|                             Command    *lastCommand, |                             Command    *lastCommand, | ||||||
|                              char     *prefix, |                             const char *prefix, | ||||||
|                              char     *suffix); |                             const char *suffix); | ||||||
|  |  | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										244
									
								
								src/ArgParse.c
									
									
									
									
									
								
							
							
						
						
									
										244
									
								
								src/ArgParse.c
									
									
									
									
									
								
							| @@ -7,12 +7,16 @@ | |||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
|  |  | ||||||
|  | #define RED   "\033[0;31m" | ||||||
|  | #define BLUE  "\033[0;34m" | ||||||
|  | #define RESET "\033[0m" | ||||||
|  |  | ||||||
| static bool _AutoHelp = true; // 是否自动添加帮助信息 | static bool _AutoHelp = true; // 是否自动添加帮助信息 | ||||||
| static bool _COLOR    = true; // 是否启用颜色 | static bool _COLOR    = true; // 是否启用颜色 | ||||||
|  |  | ||||||
| void argParseDisableAutoHelp() { _AutoHelp = false; } | void argParseDisableAutoHelp() { _AutoHelp = false; } | ||||||
|  |  | ||||||
| ArgParse *argParseInit(char *documentation) { | ArgParse *argParseInit(char *documentation, ArgParseValueType value_type) { | ||||||
|     ArgParse *argParse = malloc(sizeof(ArgParse)); |     ArgParse *argParse = malloc(sizeof(ArgParse)); | ||||||
|     if (argParse == NULL) { |     if (argParse == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
| @@ -26,6 +30,9 @@ ArgParse *argParseInit(char *documentation) { | |||||||
|     argParse->argc            = 0; |     argParse->argc            = 0; | ||||||
|     argParse->argv            = NULL; |     argParse->argv            = NULL; | ||||||
|     argParse->documentation   = stringNewCopy(documentation); |     argParse->documentation   = stringNewCopy(documentation); | ||||||
|  |     argParse->value_type      = value_type; | ||||||
|  |     argParse->val             = NULL; | ||||||
|  |     argParse->val_len         = 0; | ||||||
|  |  | ||||||
|     argParseAutoHelp(argParse); |     argParseAutoHelp(argParse); | ||||||
|  |  | ||||||
| @@ -34,15 +41,20 @@ ArgParse *argParseInit(char *documentation) { | |||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @brief 自动帮助信息回调函数 |  * @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) { |     if (argParse == NULL) { | ||||||
|         return -1; |         exit(1); | ||||||
|     } |     } | ||||||
|     char *help_doc = argParseGenerateHelp(argParse); |     char *help_doc = argParseGenerateHelp(argParse); | ||||||
|     printf("%s\n", help_doc); |     printf("%s\n", help_doc); | ||||||
|     free(help_doc); |     free(help_doc); | ||||||
|     return 0; |     argParseFree(argParse); | ||||||
|  |     exit(0); | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -64,7 +76,7 @@ void argParseAutoHelp(ArgParse *argParse) { | |||||||
|                          NULL, |                          NULL, | ||||||
|                          __helpCallback, |                          __helpCallback, | ||||||
|                          false, |                          false, | ||||||
|                          NOVALUE); |                          ArgParseNOVALUE); | ||||||
| } | } | ||||||
|  |  | ||||||
| int __commandHelpCallback(ArgParse *argParse, char **val, int val_len) { | int __commandHelpCallback(ArgParse *argParse, char **val, int val_len) { | ||||||
| @@ -93,7 +105,7 @@ void argParseCommandAutoHelp(Command *command) { | |||||||
|                    NULL, |                    NULL, | ||||||
|                    __commandHelpCallback, |                    __commandHelpCallback, | ||||||
|                    false, |                    false, | ||||||
|                    NOVALUE); |                    ArgParseNOVALUE); | ||||||
| } | } | ||||||
|  |  | ||||||
| Command *argParseAddCommand(ArgParse         *argParse, | Command *argParseAddCommand(ArgParse         *argParse, | ||||||
| @@ -259,7 +271,16 @@ void __freeCommand(Command *command) { | |||||||
|     free(command->sub_commands); |     free(command->sub_commands); | ||||||
|     free(command->name); |     free(command->name); | ||||||
|     free(command->help); |     free(command->help); | ||||||
|  |     free(command->args); | ||||||
|     free(command->default_val); |     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); |     free(command); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -274,7 +295,15 @@ void argParseFree(ArgParse *argParse) { | |||||||
|     for (size_t i = 0; i < argParse->global_args_len; i++) { |     for (size_t i = 0; i < argParse->global_args_len; i++) { | ||||||
|         __freeCommandArgs(argParse->global_args[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->global_args); | ||||||
|  |     free(argParse->documentation); | ||||||
|     free(argParse); |     free(argParse); | ||||||
| } | } | ||||||
| /** End----------------内存释放API---------------- */ | /** End----------------内存释放API---------------- */ | ||||||
| @@ -294,7 +323,7 @@ int __processArgs(ArgParse *argParse, CommandArgs *arg, int arg_index) { | |||||||
|  |  | ||||||
|     int current_index = 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++) { |         for (int i = arg_index + 1; i < argParse->argc; i++) { | ||||||
|             if (checkArgType(argParse->argv[i]) == |             if (checkArgType(argParse->argv[i]) == | ||||||
|                 COMMAND) { // COMMAND是无--或-开头的字符串,也可认定为参数值 |                 COMMAND) { // COMMAND是无--或-开头的字符串,也可认定为参数值 | ||||||
| @@ -305,12 +334,12 @@ int __processArgs(ArgParse *argParse, CommandArgs *arg, int arg_index) { | |||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } else if (arg->value_type == SINGLEVALUE) { |     } else if (arg->value_type == ArgParseSINGLEVALUE) { | ||||||
|         if (arg_index + 1 < argParse->argc) { |         if (arg_index + 1 < argParse->argc) { | ||||||
|             argParseSetArgVal(arg, argParse->argv[arg_index + 1]); |             argParseSetArgVal(arg, argParse->argv[arg_index + 1]); | ||||||
|             current_index = arg_index + 1; |             current_index = arg_index + 1; | ||||||
|         } |         } | ||||||
|     } else if (arg->value_type == NOVALUE) { |     } else if (arg->value_type == ArgParseNOVALUE) { | ||||||
|         current_index = arg_index; |         current_index = arg_index; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -369,27 +398,81 @@ int __processSubCommand(ArgParse *argParse, | |||||||
|     return -1; |     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) { | int __processCommand(ArgParse *argParse, char *name, int command_index) { | ||||||
|     Command *command = argParseFindCommand(argParse, name); |     CommandArgs *arg     = NULL; | ||||||
|     if (command == 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; |         return -1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     command->is_trigged       = true; // 标记命令被触发 |     if (command == NULL && argParse->value_type != ArgParseNOVALUE) { | ||||||
|  |         return __processVal(argParse, command_index); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     CommandArgs *arg          = NULL; |     if (command != NULL) { | ||||||
|  |         command->is_trigged       = true; // 标记命令被触发 | ||||||
|         argParse->current_command = command; |         argParse->current_command = command; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     for (int i = command_index + 1; i < argParse->argc; i++) { |     for (int i = command_index + 1; i < argParse->argc; i++) { | ||||||
|         ArgType argType = checkArgType(argParse->argv[i]); |         ArgType argType = checkArgType(argParse->argv[i]); | ||||||
|         switch (argType) { |         switch (argType) { | ||||||
|         case COMMAND: |         case COMMAND: { | ||||||
|             // 命令无值则处理子命令 |             // 命令无值则处理子命令 | ||||||
|             if (command->value_type == NOVALUE) { |             if (command->value_type == ArgParseNOVALUE) { | ||||||
|                 __processSubCommand(argParse, command, argParse->argv[i], i); |                 __processSubCommand(argParse, command, argParse->argv[i], i); | ||||||
|                 return argParse->argc - 1; |                 return argParse->argc - 1; | ||||||
|             } else { |             } else { | ||||||
| @@ -397,6 +480,7 @@ int __processCommand(ArgParse *argParse, char *name, int command_index) { | |||||||
|                 argParseSetCommandVal(command, argParse->argv[i]); |                 argParseSetCommandVal(command, argParse->argv[i]); | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|  |         } | ||||||
|         case LONG_ARG: |         case LONG_ARG: | ||||||
|             // 处理命令长选项 |             // 处理命令长选项 | ||||||
|             arg = argParseFindCommandArgs(command, argParse->argv[i], false); |             arg = argParseFindCommandArgs(command, argParse->argv[i], false); | ||||||
| @@ -448,6 +532,7 @@ int __processCommand(ArgParse *argParse, char *name, int command_index) { | |||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @brief 解析命令行参数 |  * @brief 解析命令行参数 | ||||||
|  |  * @errors: 错误信息字符串统一又调用方申请,处理函数释放 | ||||||
|  * @param argParse 解析器指针 |  * @param argParse 解析器指针 | ||||||
|  * @param argc 参数个数 |  * @param argc 参数个数 | ||||||
|  * @param argv 参数列表 |  * @param argv 参数列表 | ||||||
| @@ -462,6 +547,7 @@ void argParseParse(ArgParse *argParse, int argc, char *argv[]) { | |||||||
|         ArgType argType = checkArgType(argv[i]); |         ArgType argType = checkArgType(argv[i]); | ||||||
|         switch (argType) { |         switch (argType) { | ||||||
|         case COMMAND: |         case COMMAND: | ||||||
|  |             // 处理命令 | ||||||
|             i = __processCommand(argParse, argv[i], i); |             i = __processCommand(argParse, argv[i], i); | ||||||
|             break; |             break; | ||||||
|         case LONG_ARG: // 处理全局长选项 |         case LONG_ARG: // 处理全局长选项 | ||||||
| @@ -498,6 +584,47 @@ void argParseParse(ArgParse *argParse, int argc, char *argv[]) { | |||||||
|                                             argParse->current_command->val, |                                             argParse->current_command->val, | ||||||
|                                             argParse->current_command->val_len); |                                             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; |     return arg->val; | ||||||
| } | } | ||||||
|  |  | ||||||
| size_t __getStrlen(char *str) { | char **argParseGetValList(ArgParse *argParse, int *len) { | ||||||
|     if (str == NULL) { |     if (argParse == NULL) { | ||||||
|         return 0; |         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, ...) { | char *argParseGetVal(ArgParse *argParse) { | ||||||
|     va_list args; |     if (argParse == NULL) { | ||||||
|     va_start(args, count); |         return NULL; | ||||||
|  |  | ||||||
|     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; // 处理内存分配失败 |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // 拼接字符串 |     if (argParse->val_len == 0) { | ||||||
|     va_start(args, count); |         return NULL; | ||||||
|     temp = NULL; |  | ||||||
|     for (int i = 0; i < count; i++) { |  | ||||||
|         temp = va_arg(args, char *); |  | ||||||
|         strcat(*dst, temp); |  | ||||||
|     } |     } | ||||||
|  |     return argParse->val[0]; | ||||||
|     va_end(args); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| char *argParseGenerateHelpForCommand(Command *command) { | char *argParseGenerateHelpForCommand(Command *command) { | ||||||
| @@ -692,12 +802,12 @@ char *argParseGenerateHelpForCommand(Command *command) { | |||||||
|     __catStr(&help_msg, 2, "\033[1;33mUsage\033[0m: ", command->name); |     __catStr(&help_msg, 2, "\033[1;33mUsage\033[0m: ", command->name); | ||||||
|  |  | ||||||
|     switch (command->value_type) { |     switch (command->value_type) { | ||||||
|     case NOVALUE: |     case ArgParseNOVALUE: | ||||||
|         break; |         break; | ||||||
|     case SINGLEVALUE: |     case ArgParseSINGLEVALUE: | ||||||
|         __catStr(&help_msg, 1, " <value>"); |         __catStr(&help_msg, 1, " <value>"); | ||||||
|         break; |         break; | ||||||
|     case MULTIVALUE: |     case ArgParseMULTIVALUE: | ||||||
|         __catStr(&help_msg, 1, " <value>..."); |         __catStr(&help_msg, 1, " <value>..."); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -759,25 +869,40 @@ bool argParseCheckCommandTriggered(ArgParse *argParse, char *command_name) { | |||||||
|     return command->is_trigged; |     return command->is_trigged; | ||||||
| } | } | ||||||
|  |  | ||||||
| _Noreturn void argParseError(ArgParse *argParse, | NORETURN void argParseError(ArgParse   *argParse, | ||||||
|                             Command    *lastCommand, |                             Command    *lastCommand, | ||||||
|                              char     *prefix, |                             const char *prefix, | ||||||
|                              char     *suffix) { |                             const char *suffix) { | ||||||
|     if (argParse == NULL) { |     if (argParse == NULL) { | ||||||
|         printf("ERROR: Parse is NULL\n"); |         printf("ERROR: Parse is NULL\n"); | ||||||
|         exit(1); |         exit(1); | ||||||
|     } |     } | ||||||
|     if (lastCommand == NULL) { |     if (lastCommand == NULL) { | ||||||
|  |         char *mgs = stringNewCopy(""); | ||||||
|  |         if (prefix != NULL) { | ||||||
|  |             __catStr(&mgs, 1, prefix); | ||||||
|  |         } | ||||||
|         char *help = argParseGenerateHelp(argParse); |         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); |         exit(1); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     char *ErrorMsg = NULL; |     char *ErrorMsg = NULL; | ||||||
|  |  | ||||||
|     if (prefix != NULL) { |     if (prefix != NULL) { | ||||||
|         ErrorMsg = stringNewCopy(prefix); |         ErrorMsg = stringNewCopy((char *)prefix); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     char *command_help_msg     = argParseGenerateHelpForCommand(lastCommand); |     char *command_help_msg     = argParseGenerateHelpForCommand(lastCommand); | ||||||
| @@ -794,8 +919,7 @@ _Noreturn void argParseError(ArgParse *argParse, | |||||||
|     printf("%s\n", ErrorMsg); |     printf("%s\n", ErrorMsg); | ||||||
|     free(ErrorMsg); |     free(ErrorMsg); | ||||||
|     free(command_help_msg); |     free(command_help_msg); | ||||||
|     free(prefix); |     argParseFree(argParse); | ||||||
|     free(suffix); |  | ||||||
|     exit(1); |     exit(1); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +1,7 @@ | |||||||
| #include "ArgParseTools.h" | #include "ArgParseTools.h" | ||||||
| #include "ArgParse.h" | #include "ArgParse.h" | ||||||
|  | #include <stdarg.h> | ||||||
|  | #include <stdbool.h> | ||||||
| #include <stddef.h> | #include <stddef.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
| @@ -177,7 +179,7 @@ argParseFindGlobalArgs(ArgParse *argParse, char *name, bool short_flag) { | |||||||
|  * @return 成功返回true,失败返回false |  * @return 成功返回true,失败返回false | ||||||
|  */ |  */ | ||||||
| bool argParseSetArgVal(CommandArgs *args, char *val) { | 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 *)); |         args->val = realloc(args->val, (args->val_len + 1) * sizeof(char *)); | ||||||
|         if (args->val == NULL) { |         if (args->val == NULL) { | ||||||
|             return false; |             return false; | ||||||
| @@ -188,7 +190,7 @@ bool argParseSetArgVal(CommandArgs *args, char *val) { | |||||||
|         } |         } | ||||||
|         args->val_len++; |         args->val_len++; | ||||||
|         return true; |         return true; | ||||||
|     } else if (args->value_type == SINGLEVALUE) { // 单值 |     } else if (args->value_type == ArgParseSINGLEVALUE) { // 单值 | ||||||
|         if (args->val != NULL) { |         if (args->val != NULL) { | ||||||
|             free(args->val); |             free(args->val); | ||||||
|         } |         } | ||||||
| @@ -203,7 +205,7 @@ bool argParseSetArgVal(CommandArgs *args, char *val) { | |||||||
|         } |         } | ||||||
|         args->val_len = 1; |         args->val_len = 1; | ||||||
|         return true; |         return true; | ||||||
|     } else if (args->value_type == NOVALUE) { // 无值 |     } else if (args->value_type == ArgParseNOVALUE) { // 无值 | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -211,7 +213,7 @@ bool argParseSetArgVal(CommandArgs *args, char *val) { | |||||||
| } | } | ||||||
|  |  | ||||||
| bool argParseSetCommandVal(Command *command, char *val) { | bool argParseSetCommandVal(Command *command, char *val) { | ||||||
|     if (command->value_type == MULTIVALUE) { // 多值 |     if (command->value_type == ArgParseMULTIVALUE) { // 多值 | ||||||
|         command->val = |         command->val = | ||||||
|             realloc(command->val, (command->val_len + 1) * sizeof(char *)); |             realloc(command->val, (command->val_len + 1) * sizeof(char *)); | ||||||
|         if (command->val == NULL) { |         if (command->val == NULL) { | ||||||
| @@ -223,7 +225,7 @@ bool argParseSetCommandVal(Command *command, char *val) { | |||||||
|         } |         } | ||||||
|         command->val_len++; |         command->val_len++; | ||||||
|         return true; |         return true; | ||||||
|     } else if (command->value_type == SINGLEVALUE) { // 单值 |     } else if (command->value_type == ArgParseSINGLEVALUE) { // 单值 | ||||||
|         if (command->val != NULL) { |         if (command->val != NULL) { | ||||||
|             free(command->val); |             free(command->val); | ||||||
|         } |         } | ||||||
| @@ -238,8 +240,89 @@ bool argParseSetCommandVal(Command *command, char *val) { | |||||||
|         } |         } | ||||||
|         command->val_len = 1; |         command->val_len = 1; | ||||||
|         return true; |         return true; | ||||||
|     } else if (command->value_type == NOVALUE) { // 无值 |     } else if (command->value_type == ArgParseNOVALUE) { // 无值 | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|     return false; |     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 "ArgParse.h" | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
|  | #include <stddef.h> | ||||||
|  |  | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| extern "C" { | extern "C" { | ||||||
| @@ -45,6 +46,8 @@ bool argParseSetArgVal(CommandArgs *args, char *val); // 设置命令参数值 | |||||||
|  |  | ||||||
| bool argParseSetCommandVal(Command *command, char *val); // 设置命令值 | bool argParseSetCommandVal(Command *command, char *val); // 设置命令值 | ||||||
|  |  | ||||||
|  | bool argParseSetVal(ArgParse *argParse, char *val); // 设置值 | ||||||
|  |  | ||||||
| ArgType checkArgType(char *arg); // 检查参数类型 | ArgType checkArgType(char *arg); // 检查参数类型 | ||||||
|  |  | ||||||
| Command *argParseFindCommand(ArgParse *argParse, char *name); // 查找命令 | Command *argParseFindCommand(ArgParse *argParse, char *name); // 查找命令 | ||||||
| @@ -60,6 +63,8 @@ CommandArgs *argParseFindGlobalArgs(ArgParse *argParse, | |||||||
|                                     bool      short_flag); // 查找全局参数 |                                     bool      short_flag); // 查找全局参数 | ||||||
|  |  | ||||||
| char  *stringNewCopy(char *str);             // 创建字符串副本 | char  *stringNewCopy(char *str);             // 创建字符串副本 | ||||||
|  | void   __catStr(char **dst, int count, ...); // 字符串拼接 | ||||||
|  | size_t __getStrlen(char *str);               // 获取字符串长度 | ||||||
|  |  | ||||||
| #ifdef __cplusplus | #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) | target_link_libraries(${PROJECT_NAME}unknow_command_arg CArgParse) | ||||||
| add_test(${PROJECT_NAME}unknow_command_arg ${PROJECT_NAME}unknow_command_arg install --unknow) | 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) | 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> | #include <string.h> | ||||||
|  |  | ||||||
| ArgParse *initArgParse() { | ArgParse *initArgParse() { | ||||||
|     ArgParse *argparse    = argParseInit("测试程序"); |     ArgParse *argparse    = argParseInit("测试程序", ArgParseNOVALUE); | ||||||
|     Command  *command     = NULL; |     Command  *command     = NULL; | ||||||
|     Command  *sub_command = NULL; |     Command  *sub_command = NULL; | ||||||
|  |  | ||||||
| @@ -16,13 +16,24 @@ ArgParse *initArgParse() { | |||||||
|                          NULL, |                          NULL, | ||||||
|                          NULL, |                          NULL, | ||||||
|                          false, |                          false, | ||||||
|                          NOVALUE); |                          ArgParseNOVALUE); | ||||||
|     argParseAddGlobalArg( |     argParseAddGlobalArg(argparse, | ||||||
|         argparse, "-q", "--quiet", "Quiet mode", NULL, NULL, false, NOVALUE); |                          "-q", | ||||||
|  |                          "--quiet", | ||||||
|  |                          "Quiet mode", | ||||||
|  |                          NULL, | ||||||
|  |                          NULL, | ||||||
|  |                          false, | ||||||
|  |                          ArgParseNOVALUE); | ||||||
|  |  | ||||||
|     // add arguments |     // add arguments | ||||||
|     command = argParseAddCommand( |     command = argParseAddCommand(argparse, | ||||||
|         argparse, "install", "Install the package", NULL, NULL, NULL, NOVALUE); |                                  "install", | ||||||
|  |                                  "Install the package", | ||||||
|  |                                  NULL, | ||||||
|  |                                  NULL, | ||||||
|  |                                  NULL, | ||||||
|  |                                  ArgParseNOVALUE); | ||||||
|     argParseAddArg(command, |     argParseAddArg(command, | ||||||
|                    "-i", |                    "-i", | ||||||
|                    "--index", |                    "--index", | ||||||
| @@ -30,7 +41,7 @@ ArgParse *initArgParse() { | |||||||
|                    "https://example.com", |                    "https://example.com", | ||||||
|                    NULL, |                    NULL, | ||||||
|                    false, |                    false, | ||||||
|                    SINGLEVALUE); |                    ArgParseSINGLEVALUE); | ||||||
|     argParseAddArg(command, |     argParseAddArg(command, | ||||||
|                    "-f", |                    "-f", | ||||||
|                    "--file", |                    "--file", | ||||||
| @@ -38,7 +49,7 @@ ArgParse *initArgParse() { | |||||||
|                    "package.json", |                    "package.json", | ||||||
|                    NULL, |                    NULL, | ||||||
|                    false, |                    false, | ||||||
|                    MULTIVALUE); |                    ArgParseMULTIVALUE); | ||||||
|     argParseAddArg(command, |     argParseAddArg(command, | ||||||
|                    "-p", |                    "-p", | ||||||
|                    "--package", |                    "--package", | ||||||
| @@ -46,10 +57,15 @@ ArgParse *initArgParse() { | |||||||
|                    "package.json", |                    "package.json", | ||||||
|                    NULL, |                    NULL, | ||||||
|                    false, |                    false, | ||||||
|                    MULTIVALUE); |                    ArgParseMULTIVALUE); | ||||||
|  |  | ||||||
|     sub_command = argParseAddSubCommand( |     sub_command = argParseAddSubCommand(command, | ||||||
|         command, "tools", "Install tools", NULL, NULL, NULL, MULTIVALUE); |                                         "tools", | ||||||
|  |                                         "Install tools", | ||||||
|  |                                         NULL, | ||||||
|  |                                         NULL, | ||||||
|  |                                         NULL, | ||||||
|  |                                         ArgParseMULTIVALUE); | ||||||
|  |  | ||||||
|     argParseAddArg(sub_command, |     argParseAddArg(sub_command, | ||||||
|                    "-t", |                    "-t", | ||||||
| @@ -58,9 +74,14 @@ ArgParse *initArgParse() { | |||||||
|                    "Tool name", |                    "Tool name", | ||||||
|                    NULL, |                    NULL, | ||||||
|                    true, |                    true, | ||||||
|                    MULTIVALUE); |                    ArgParseMULTIVALUE); | ||||||
|     sub_command = argParseAddSubCommand( |     sub_command = argParseAddSubCommand(command, | ||||||
|         command, "tools_sub", "Install tools", NULL, NULL, NULL, MULTIVALUE); |                                         "tools_sub", | ||||||
|  |                                         "Install tools", | ||||||
|  |                                         NULL, | ||||||
|  |                                         NULL, | ||||||
|  |                                         NULL, | ||||||
|  |                                         ArgParseMULTIVALUE); | ||||||
|  |  | ||||||
|     argParseAddArg(sub_command, |     argParseAddArg(sub_command, | ||||||
|                    "-s", |                    "-s", | ||||||
| @@ -69,7 +90,7 @@ ArgParse *initArgParse() { | |||||||
|                    "tools subcommand test", |                    "tools subcommand test", | ||||||
|                    NULL, |                    NULL, | ||||||
|                    true, |                    true, | ||||||
|                    MULTIVALUE); |                    ArgParseMULTIVALUE); | ||||||
|  |  | ||||||
|     command = argParseAddCommand(argparse, |     command = argParseAddCommand(argparse, | ||||||
|                                  "uninstall", |                                  "uninstall", | ||||||
| @@ -77,7 +98,7 @@ ArgParse *initArgParse() { | |||||||
|                                  NULL, |                                  NULL, | ||||||
|                                  NULL, |                                  NULL, | ||||||
|                                  NULL, |                                  NULL, | ||||||
|                                  SINGLEVALUE); |                                  ArgParseSINGLEVALUE); | ||||||
|     argParseAddArg(command, |     argParseAddArg(command, | ||||||
|                    "-p", |                    "-p", | ||||||
|                    "--package", |                    "--package", | ||||||
| @@ -85,7 +106,7 @@ ArgParse *initArgParse() { | |||||||
|                    "Package name", |                    "Package name", | ||||||
|                    NULL, |                    NULL, | ||||||
|                    true, |                    true, | ||||||
|                    MULTIVALUE); |                    ArgParseMULTIVALUE); | ||||||
|  |  | ||||||
|     return argparse; |     return argparse; | ||||||
| } | } | ||||||
| @@ -10,7 +10,6 @@ int main(int argc, char *argv[]) { | |||||||
|  |  | ||||||
|     const char *testv[3] = {"testpackge1", "testpackge2", "testpackge3"}; |     const char *testv[3] = {"testpackge1", "testpackge2", "testpackge3"}; | ||||||
|  |  | ||||||
|  |  | ||||||
|     // Test -p |     // Test -p | ||||||
|     char *val            = argParseGetCurArg(argparse, "-p"); |     char *val            = argParseGetCurArg(argparse, "-p"); | ||||||
|  |  | ||||||
| @@ -27,8 +26,6 @@ int main(int argc, char *argv[]) { | |||||||
|     printf("-i Value: %s\n", val_i); |     printf("-i Value: %s\n", val_i); | ||||||
|     assert(strcmp(val_i, "www.test.com") == 0); |     assert(strcmp(val_i, "www.test.com") == 0); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     // Test -f |     // Test -f | ||||||
|     len                  = 0; |     len                  = 0; | ||||||
|     const char *testf[2] = {"file1.txt", "file2.txt"}; |     const char *testf[2] = {"file1.txt", "file2.txt"}; | ||||||
| @@ -38,7 +35,6 @@ int main(int argc, char *argv[]) { | |||||||
|         assert(strcmp(val_f[i], testf[i]) == 0); |         assert(strcmp(val_f[i], testf[i]) == 0); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     argParseFree(argparse); |     argParseFree(argparse); | ||||||
|  |  | ||||||
|     return 0; |     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; | ||||||
|  | } | ||||||
| @@ -8,12 +8,11 @@ int main(int argc, char *argv[]) { | |||||||
|  |  | ||||||
|     argParseParse(argparse, argc, argv); |     argParseParse(argparse, argc, argv); | ||||||
|  |  | ||||||
|      |  | ||||||
|     char *command_name = argParseGetCurCommandName(argparse); |     char *command_name = argParseGetCurCommandName(argparse); | ||||||
|     printf("command name: %s\n", command_name); |     printf("command name: %s\n", command_name); | ||||||
|     assert(strcmp(command_name, "tools") == 0); |     assert(strcmp(command_name, "tools") == 0); | ||||||
|  |  | ||||||
|     char * val = argParseGetCurArg(argparse, "-t"); |     char *val = argParseGetCurArg(argparse, "-t"); | ||||||
|     printf("tools -t: %s\n", val); |     printf("tools -t: %s\n", val); | ||||||
|  |  | ||||||
|     argParseFree(argparse); |     argParseFree(argparse); | ||||||
|   | |||||||
| @@ -7,7 +7,6 @@ int main(int argc, char *argv[]) { | |||||||
|  |  | ||||||
|     argParseParse(argparse, argc, argv); |     argParseParse(argparse, argc, argv); | ||||||
|  |  | ||||||
|  |  | ||||||
|     argParseFree(argparse); |     argParseFree(argparse); | ||||||
|  |  | ||||||
|     return 0; |     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