feat(argparse): 实现高级命令行参数解析库
- 添加完整的参数解析API,支持子命令、选项和参数定义 - 实现多种数据类型支持:字符串、布尔值、整数、浮点数、枚举等 - 添加约束规范结构体,支持必填项、多值、隐藏选项等功能 - 实现国际化支持,包含中英文错误提示和帮助信息 - 添加模糊匹配功能,当用户输入错误参数时提供相似建议 - 实现详细的帮助信息打印功能,包括使用方法、选项说明等 - 修改底层optparse库,优化选项处理和错误报告机制 - 添加向量类型支持用于管理参数、选项和子命令集合
This commit is contained in:
@@ -2,30 +2,219 @@
|
||||
#define __SCC_ARGPARSE_H__
|
||||
|
||||
#include "optparse.h"
|
||||
#include <scc_core.h>
|
||||
|
||||
typedef enum {
|
||||
SCC_ARGPARSE_ERROR_NONE,
|
||||
} scc_argparse_error_t;
|
||||
// TODO: 实现更多高级功能
|
||||
// 1. 支持子命令嵌套层级限制
|
||||
// 2. 支持选项分组显示(Grouping)
|
||||
// 3. 支持自动补全脚本生成(Bash/Zsh/Fish)
|
||||
// 4. 支持配置文件解析
|
||||
// 5. 支持国际化(i18n)
|
||||
|
||||
typedef struct {
|
||||
} scc_argparse_cmd_t;
|
||||
typedef struct scc_argparse_spec scc_argparse_spec_t;
|
||||
typedef struct scc_argparse_arg scc_argparse_arg_t;
|
||||
typedef struct scc_argparse_opt scc_argparse_opt_t;
|
||||
typedef struct scc_argparse_cmd scc_argparse_cmd_t;
|
||||
|
||||
typedef struct {
|
||||
} scc_argparse_arg_t;
|
||||
typedef SCC_VEC(scc_argparse_arg_t) scc_argparse_arg_vec_t;
|
||||
typedef SCC_VEC(scc_argparse_opt_t) scc_argparse_opt_vec_t;
|
||||
typedef SCC_VEC(scc_argparse_cmd_t) scc_argparse_cmd_vec_t;
|
||||
|
||||
typedef struct {
|
||||
typedef enum scc_argparse_val_type {
|
||||
SCC_ARGPARSE_VAL_TYPE_UNKNOWN,
|
||||
SCC_ARGPARSE_VAL_TYPE_STRING,
|
||||
SCC_ARGPARSE_VAL_TYPE_BOOL,
|
||||
SCC_ARGPARSE_VAL_TYPE_INT,
|
||||
SCC_ARGPARSE_VAL_TYPE_FLOAT,
|
||||
SCC_ARGPARSE_VAL_TYPE_ENUM,
|
||||
SCC_ARGPARSE_VAL_TYPE_LIST,
|
||||
SCC_ARGPARSE_VAL_TYPE_COUNT,
|
||||
} scc_argparse_val_type_t;
|
||||
|
||||
typedef enum scc_argparse_err {
|
||||
SCC_ARGPARSE_ERR_NONE,
|
||||
SCC_ARGPARSE_ERR_UNKNOWN_ERR,
|
||||
SCC_ARGPARSE_ERR_INVALID_ARG,
|
||||
SCC_ARGPARSE_ERR_INVALID_VALUE,
|
||||
SCC_ARGPARSE_ERR_MISSING_ARG,
|
||||
SCC_ARGPARSE_ERR_MISSING_VALUE,
|
||||
SCC_ARGPARSE_ERR_UNKNOWN_ARG,
|
||||
SCC_ARGPARSE_ERR_UNKNOWN_VALUE,
|
||||
} scc_argparse_err_t;
|
||||
|
||||
// 约束规范结构体
|
||||
struct scc_argparse_spec {
|
||||
scc_argparse_val_type_t value_type; // 值类型
|
||||
const char *raw_value;
|
||||
|
||||
// 存储位置
|
||||
union {
|
||||
cbool *bool_store; // 布尔值存储
|
||||
int *int_store; // 整数存储
|
||||
float *float_store; // 浮点数存储
|
||||
const char **str_store; // 字符串存储
|
||||
char **str_alloc_store; // 字符串存储(使用alloc,需要free)
|
||||
void **ptr_store; // 通用指针存储
|
||||
} store;
|
||||
|
||||
// 枚举值约束
|
||||
struct {
|
||||
const char **values; // 枚举值数组
|
||||
int count; // 枚举值数量
|
||||
} choices;
|
||||
|
||||
// 其他约束标志
|
||||
cbool flag_required; // 是否必须
|
||||
cbool flag_store_as_count; // 是否存储为计数(如 -vvv 返回3)
|
||||
cbool flag_allow_empty; // 是否允许空字符串
|
||||
cbool flag_hidden; // 是否隐藏(不显示在帮助)
|
||||
cbool flag_takes_multiple; // 是否接受多个值(如 -I dir1 -I dir2)
|
||||
cbool flag_parse_complex; // 是否进行复杂解析(如 1K, 2M, 3G)
|
||||
};
|
||||
|
||||
struct scc_argparse_arg {
|
||||
scc_argparse_spec_t spec;
|
||||
const char *name;
|
||||
const char *description;
|
||||
};
|
||||
|
||||
struct scc_argparse_opt {
|
||||
scc_argparse_spec_t spec;
|
||||
char short_name;
|
||||
const char *long_name;
|
||||
const char *description;
|
||||
};
|
||||
|
||||
struct scc_argparse_cmd {
|
||||
const char *name;
|
||||
const char *description;
|
||||
scc_argparse_arg_vec_t args;
|
||||
scc_argparse_opt_vec_t opts;
|
||||
scc_argparse_cmd_vec_t subcmds;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
SCC_ARGPARSE_LANG_EN,
|
||||
SCC_ARGPARSE_LANG_ZH,
|
||||
} scc_argparse_lang_t;
|
||||
|
||||
typedef struct {
|
||||
const char *prog_name;
|
||||
const char *version;
|
||||
const char *description;
|
||||
const char *epilog;
|
||||
const char *usage;
|
||||
const char *help;
|
||||
scc_optparse_t optparse;
|
||||
int usage_margin;
|
||||
int usage_max_width;
|
||||
int help_vertical_space;
|
||||
int help_usage_margin;
|
||||
int help_description_margin;
|
||||
int help_max_width;
|
||||
scc_argparse_cmd_t root_cmd;
|
||||
scc_argparse_lang_t lang;
|
||||
cbool need_help;
|
||||
cbool need_version;
|
||||
cbool need_debug;
|
||||
} scc_argparse_t;
|
||||
|
||||
typedef SCC_VEC(scc_optparse_opt_t) scc_optparse_opt_vec_t;
|
||||
|
||||
typedef struct {
|
||||
scc_argparse_cmd_t *current_cmd; // 当前正在解析的命令
|
||||
scc_optparse_t optparse; // 底层解析器
|
||||
scc_optparse_opt_vec_t opts; // 当前命令的选项列表
|
||||
scc_optparse_result_t result;
|
||||
int positional_index; // 当前处理的位置参数索引
|
||||
cbool parsing_done; // 是否已完成解析
|
||||
scc_argparse_lang_t lang;
|
||||
} scc_argparse_context_t;
|
||||
|
||||
void scc_argparse_init(scc_argparse_t *parser, const char *program_name,
|
||||
const char *description);
|
||||
scc_argparse_cmd_t *scc_argparse_get_root(scc_argparse_t *parser);
|
||||
void scc_argparse_drop(scc_argparse_t *parser);
|
||||
int scc_argparse_parse(scc_argparse_t *parser, int argc, const char **argv);
|
||||
|
||||
void scc_argparse_cmd_init(scc_argparse_cmd_t *cmd, const char *name,
|
||||
const char *description);
|
||||
void scc_argparse_cmd_drop(scc_argparse_cmd_t *cmd);
|
||||
|
||||
void scc_argparse_cmd_add_arg(scc_argparse_cmd_t *cmd,
|
||||
const scc_argparse_arg_t *arg);
|
||||
void scc_argparse_cmd_add_opt(scc_argparse_cmd_t *cmd,
|
||||
const scc_argparse_opt_t *opt);
|
||||
void scc_argparse_cmd_add_subcmd(scc_argparse_cmd_t *cmd,
|
||||
const scc_argparse_cmd_t *subcmd);
|
||||
|
||||
void scc_argparse_print_help(scc_argparse_t *parser, scc_argparse_cmd_t *cmd);
|
||||
void scc_argparse_print_error(scc_argparse_context_t *ctx,
|
||||
scc_argparse_err_t err);
|
||||
|
||||
static inline void scc_argparse_spec_init(scc_argparse_spec_t *spec) {
|
||||
spec->value_type = SCC_ARGPARSE_VAL_TYPE_STRING;
|
||||
spec->raw_value = null;
|
||||
spec->store.ptr_store = null;
|
||||
|
||||
spec->choices.count = 0;
|
||||
spec->choices.values = null;
|
||||
|
||||
spec->flag_required = false;
|
||||
spec->flag_store_as_count = false;
|
||||
spec->flag_allow_empty = false;
|
||||
spec->flag_hidden = false;
|
||||
spec->flag_takes_multiple = false;
|
||||
spec->flag_parse_complex = false;
|
||||
}
|
||||
|
||||
static inline void scc_argparse_opt_init(scc_argparse_opt_t *opt,
|
||||
char short_name, const char *long_name,
|
||||
const char *desc) {
|
||||
opt->short_name = short_name;
|
||||
opt->long_name = long_name;
|
||||
opt->description = desc;
|
||||
scc_argparse_spec_init(&opt->spec);
|
||||
}
|
||||
|
||||
static inline void scc_argparse_arg_init(scc_argparse_arg_t *arg,
|
||||
const char *name, const char *desc) {
|
||||
arg->name = name;
|
||||
arg->description = desc;
|
||||
scc_argparse_spec_init(&arg->spec);
|
||||
}
|
||||
|
||||
static inline void scc_argparse_spec_setup_bool(scc_argparse_spec_t *spec,
|
||||
cbool *store) {
|
||||
spec->value_type = SCC_ARGPARSE_VAL_TYPE_BOOL;
|
||||
spec->store.bool_store = store;
|
||||
}
|
||||
|
||||
static inline void scc_argparse_spec_setup_count(scc_argparse_spec_t *spec,
|
||||
int *store) {
|
||||
spec->value_type = SCC_ARGPARSE_VAL_TYPE_COUNT;
|
||||
spec->flag_store_as_count = true; // 自动设为计数模式
|
||||
spec->store.int_store = store;
|
||||
}
|
||||
|
||||
static inline void scc_argparse_spec_setup_string(scc_argparse_spec_t *spec,
|
||||
const char **store) {
|
||||
spec->value_type = SCC_ARGPARSE_VAL_TYPE_STRING;
|
||||
spec->store.str_store = store;
|
||||
}
|
||||
|
||||
static inline void scc_argparse_spec_setup_int(scc_argparse_spec_t *spec,
|
||||
int *store) {
|
||||
spec->value_type = SCC_ARGPARSE_VAL_TYPE_INT;
|
||||
spec->store.int_store = store;
|
||||
}
|
||||
|
||||
static inline void scc_argparse_spec_setup_float(scc_argparse_spec_t *spec,
|
||||
float *store) {
|
||||
spec->value_type = SCC_ARGPARSE_VAL_TYPE_FLOAT;
|
||||
spec->store.float_store = store;
|
||||
}
|
||||
|
||||
#define SCC_ARGPARSE_MACRO_SETTER(attr) \
|
||||
static inline void scc_argparse_spec_set_##attr(scc_argparse_spec_t *spec, \
|
||||
cbool flag) { \
|
||||
spec->flag_##attr = flag; \
|
||||
}
|
||||
SCC_ARGPARSE_MACRO_SETTER(required)
|
||||
SCC_ARGPARSE_MACRO_SETTER(allow_empty)
|
||||
SCC_ARGPARSE_MACRO_SETTER(hidden)
|
||||
SCC_ARGPARSE_MACRO_SETTER(takes_multiple)
|
||||
SCC_ARGPARSE_MACRO_SETTER(parse_complex)
|
||||
|
||||
#endif /* __SCC_ARGPARSE_H__ */
|
||||
|
||||
@@ -5,15 +5,14 @@ typedef struct scc_optparse_opt {
|
||||
char prefix;
|
||||
char short_name;
|
||||
const char *long_name;
|
||||
const char *default_value;
|
||||
void (*invoke)(void *value);
|
||||
void (*handle)(void *user_data);
|
||||
void *user_data;
|
||||
int min_args;
|
||||
int max_args;
|
||||
} scc_optparse_opt_t;
|
||||
|
||||
#define SCC_OPTPARSE_OPT(prefix, short_name, long_name, min_args, max_args, \
|
||||
default_value, invoke) \
|
||||
{prefix, short_name, long_name, default_value, invoke, min_args, max_args}
|
||||
#define SCC_OPTPARSE_OPT(prefix, short_name, long_name, min_args, max_args) \
|
||||
{prefix, short_name, long_name, 0, 0, min_args, max_args}
|
||||
#define SCC_OPTPARSE_OPT_END() {0}
|
||||
|
||||
typedef enum scc_optparse_error {
|
||||
@@ -24,10 +23,18 @@ typedef enum scc_optparse_error {
|
||||
SCC_OPT_ERROR_TOO_MANY_ARGS,
|
||||
} scc_optparse_error_t;
|
||||
|
||||
typedef struct {
|
||||
const scc_optparse_opt_t *opt;
|
||||
int count; // check for min_args <= count <= max_args
|
||||
int arg_pos; // for argv pos
|
||||
int opt_pos; // for short pos
|
||||
} scc_optparse_state_t;
|
||||
|
||||
typedef struct scc_optparse_result {
|
||||
const scc_optparse_opt_t *opt;
|
||||
const char *value;
|
||||
int error;
|
||||
const char *raw_arg;
|
||||
} scc_optparse_result_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -36,12 +43,7 @@ typedef struct {
|
||||
const scc_optparse_opt_t *opts;
|
||||
int handle_positional;
|
||||
int greedy_mode;
|
||||
struct {
|
||||
const scc_optparse_opt_t *opt;
|
||||
int count; // check for min_args <= count <= max_args
|
||||
int arg_pos; // for argv pos
|
||||
int opt_pos; // for short pos
|
||||
} current;
|
||||
scc_optparse_state_t current;
|
||||
} scc_optparse_t;
|
||||
|
||||
void scc_optparse_init(scc_optparse_t *parser, int argc, const char **argv);
|
||||
|
||||
Reference in New Issue
Block a user