Compare commits

3 Commits

Author SHA1 Message Date
85a219126d fix: 修复必填参数未做检测 2025-09-30 13:35:19 +08:00
1345a0514e style: 优化代码格式和测试用例 2025-09-30 11:20:33 +08:00
0a7179380a style: 格式化代码对齐和参数布局 2025-09-30 10:16:42 +08:00
10 changed files with 288 additions and 49 deletions

View File

@@ -7,6 +7,10 @@
#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; // 是否启用颜色
@@ -37,15 +41,20 @@ ArgParse *argParseInit(char *documentation, ArgParseValueType value_type) {
/**
* @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);
}
/**
@@ -523,6 +532,7 @@ int __processCommand(ArgParse *argParse, char *name, int command_index) {
/**
* @brief 解析命令行参数
* @errors: 错误信息字符串统一又调用方申请,处理函数释放
* @param argParse 解析器指针
* @param argc 参数个数
* @param argv 参数列表
@@ -574,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); // 错误处理
}
}
}
}
/**
@@ -819,9 +870,9 @@ bool argParseCheckCommandTriggered(ArgParse *argParse, char *command_name) {
}
NORETURN void argParseError(ArgParse *argParse,
Command *lastCommand,
const char *prefix,
const char *suffix) {
Command *lastCommand,
const char *prefix,
const char *suffix) {
if (argParse == NULL) {
printf("ERROR: Parse is NULL\n");
exit(1);
@@ -841,7 +892,6 @@ NORETURN void argParseError(ArgParse *argParse,
__catStr(&mgs, 2, "\n", suffix);
}
// printf("\033[1;31mERROR\033[0m: Last command is unknown\n");
printf("%s\n", mgs);
free(mgs);
free(help);

View File

@@ -26,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); // 创建命令参数
/**

View File

@@ -37,3 +37,12 @@ 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)

View File

@@ -4,7 +4,7 @@
#include <string.h>
ArgParse *initArgParse() {
ArgParse *argparse = argParseInit("测试程序",ArgParseNOVALUE);
ArgParse *argparse = argParseInit("测试程序", ArgParseNOVALUE);
Command *command = NULL;
Command *sub_command = NULL;
@@ -17,12 +17,23 @@ ArgParse *initArgParse() {
NULL,
false,
ArgParseNOVALUE);
argParseAddGlobalArg(
argparse, "-q", "--quiet", "Quiet mode", 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);
command = argParseAddCommand(argparse,
"install",
"Install the package",
NULL,
NULL,
NULL,
ArgParseNOVALUE);
argParseAddArg(command,
"-i",
"--index",
@@ -48,8 +59,13 @@ ArgParse *initArgParse() {
false,
ArgParseMULTIVALUE);
sub_command = argParseAddSubCommand(
command, "tools", "Install tools", NULL, NULL, NULL, ArgParseMULTIVALUE);
sub_command = argParseAddSubCommand(command,
"tools",
"Install tools",
NULL,
NULL,
NULL,
ArgParseMULTIVALUE);
argParseAddArg(sub_command,
"-t",
@@ -59,8 +75,13 @@ ArgParse *initArgParse() {
NULL,
true,
ArgParseMULTIVALUE);
sub_command = argParseAddSubCommand(
command, "tools_sub", "Install tools", NULL, NULL, NULL, ArgParseMULTIVALUE);
sub_command = argParseAddSubCommand(command,
"tools_sub",
"Install tools",
NULL,
NULL,
NULL,
ArgParseMULTIVALUE);
argParseAddArg(sub_command,
"-s",

View File

@@ -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
View 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;
}

View File

@@ -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]);

View File

@@ -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);

View File

@@ -7,7 +7,6 @@ int main(int argc, char *argv[]) {
argParseParse(argparse, argc, argv);
argParseFree(argparse);
return 0;

View File

@@ -18,12 +18,23 @@ ArgParse *initArgParse() {
NULL,
false,
ArgParseNOVALUE);
argParseAddGlobalArg(
argparse, "-q", "--quiet", "Quiet mode", 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);
command = argParseAddCommand(argparse,
"install",
"Install the package",
NULL,
NULL,
NULL,
ArgParseNOVALUE);
argParseAddArg(command,
"-i",
"--index",
@@ -49,8 +60,13 @@ ArgParse *initArgParse() {
false,
ArgParseMULTIVALUE);
sub_command = argParseAddSubCommand(
command, "tools", "Install tools", NULL, NULL, NULL, ArgParseMULTIVALUE);
sub_command = argParseAddSubCommand(command,
"tools",
"Install tools",
NULL,
NULL,
NULL,
ArgParseMULTIVALUE);
argParseAddArg(sub_command,
"-t",
@@ -60,8 +76,13 @@ ArgParse *initArgParse() {
NULL,
true,
ArgParseMULTIVALUE);
sub_command = argParseAddSubCommand(
command, "tools_sub", "Install tools", NULL, NULL, NULL, ArgParseMULTIVALUE);
sub_command = argParseAddSubCommand(command,
"tools_sub",
"Install tools",
NULL,
NULL,
NULL,
ArgParseMULTIVALUE);
argParseAddArg(sub_command,
"-s",
@@ -101,8 +122,8 @@ int main(int argc, char *argv[]) {
printf("val: %s\n", val);
}
int len = 0;
char **vals = argParseGetValList(argparse, &len);
int len = 0;
char **vals = argParseGetValList(argparse, &len);
char *test_val[3] = {"file1.txt", "file2.txt", "file3.txt"};