Files
scc/libs/argparse/include/argparse.h
zzy 191cdcef53 feat(argparse): 实现高级命令行参数解析库
- 添加完整的参数解析API,支持子命令、选项和参数定义
- 实现多种数据类型支持:字符串、布尔值、整数、浮点数、枚举等
- 添加约束规范结构体,支持必填项、多值、隐藏选项等功能
- 实现国际化支持,包含中英文错误提示和帮助信息
- 添加模糊匹配功能,当用户输入错误参数时提供相似建议
- 实现详细的帮助信息打印功能,包括使用方法、选项说明等
- 修改底层optparse库,优化选项处理和错误报告机制
- 添加向量类型支持用于管理参数、选项和子命令集合
2026-02-12 21:41:57 +08:00

221 lines
7.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#ifndef __SCC_ARGPARSE_H__
#define __SCC_ARGPARSE_H__
#include "optparse.h"
#include <scc_core.h>
// TODO: 实现更多高级功能
// 1. 支持子命令嵌套层级限制
// 2. 支持选项分组显示Grouping
// 3. 支持自动补全脚本生成Bash/Zsh/Fish
// 4. 支持配置文件解析
// 5. 支持国际化i18n
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 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 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;
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__ */