Added required arguments and color
This commit is contained in:
parent
4dfaf08bb8
commit
1f80869191
182
xap.h
182
xap.h
|
@ -24,9 +24,37 @@
|
|||
// originally authored by Alexey Kutepov <reximkut@gmail.com>
|
||||
// All rights reserved by the original creator.
|
||||
|
||||
// Configurable macros:
|
||||
// XAP_DISPLAY_VERSION - If defined enables the version flag
|
||||
// XAP_EXIT_ON_ERROR - If defined the program exits immediately when an error in XAP occurs
|
||||
|
||||
/// # Configurable macros
|
||||
/// | macro name | Description |
|
||||
/// |---------------------|-------------------------------------------------------|
|
||||
/// | XAP_DISPLAY_VERSION | If defined, enables the version flag |
|
||||
/// | XAP_EXIT_ON_ERROR | If defined, the program exits immediately on an error |
|
||||
/// | XAP_USE_COLOR | If defined, enables the use of color and styles |
|
||||
///
|
||||
/// Redefinable macros:
|
||||
/// | Macro name | Description |
|
||||
/// |--------------|-------------|
|
||||
/// | XAP_ASSERT | Assert |
|
||||
/// | XAP_REALLOC | Mem |
|
||||
/// | XAP_ALLOC | Mem |
|
||||
/// | XAP_FREE | Mem |
|
||||
///
|
||||
/// # Public functions
|
||||
///
|
||||
/// Note: s_size_t is a macro of ptrdiff_t
|
||||
///
|
||||
/// | Description | Function Definition |
|
||||
/// |-----------------------------|--------------------------------------------------------------|
|
||||
/// | Main entry func for XAP | xap_result_t xap_parse(xap_t* xap, int argc, char** argv); |
|
||||
/// | Free all allocated memory | void xap_free(xap_t xap); |
|
||||
/// | Get char* value by name | char* xap_get_arg_value_str(xap_t* xap, char* arg_name); |
|
||||
/// | Get size_t* value by name | size_t* xap_get_arg_value_uint(xap_t* xap, char* arg_name); |
|
||||
/// | Get s_size_t* value by name | s_size_t* xap_get_arg_value_int(xap_t* xap, char* arg_name); |
|
||||
/// | Get float* value by name | float* xap_get_arg_value_float(xap_t* xap, char* arg_name); |
|
||||
/// | Get bool* value by name | bool* xap_get_arg_value_bool(xap_t* xap, char* arg_name); |
|
||||
/// | Make all text uppercase | void xap_to_upper(char* str); |
|
||||
/// | Make all text lowercase | void xap_to_lower(char* str); |
|
||||
|
||||
|
||||
#ifndef _H_XAP
|
||||
|
@ -39,14 +67,43 @@
|
|||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define s_size_t ptrdiff_t
|
||||
|
||||
|
||||
|
||||
#ifndef xap_log_error
|
||||
#define xap_log_error(fmt, ...) _xap_log_error(fmt, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifndef XAP_ASSERT
|
||||
#define XAP_ASSERT assert
|
||||
#endif
|
||||
#ifndef XAP_REALLOC
|
||||
#define XAP_REALLOC realloc
|
||||
#endif
|
||||
#ifndef XAP_ALLOC
|
||||
#define XAP_ALLOC malloc
|
||||
#endif
|
||||
#ifndef XAP_FREE
|
||||
#define XAP_FREE free
|
||||
#endif
|
||||
|
||||
#ifdef XAP_USE_COLOR
|
||||
#define XAP_C_UL "\e[4m"
|
||||
#define XAP_C_RED "\e[0;31m"
|
||||
#define XAP_C_RS "\e[0m"
|
||||
#define XAP_C_BL "\e[1m"
|
||||
#else
|
||||
#define XAP_C_UL ""
|
||||
#define XAP_C_RED ""
|
||||
#define XAP_C_RS ""
|
||||
#define XAP_C_BL ""
|
||||
#endif
|
||||
|
||||
|
||||
// From nob, starting from here
|
||||
#define XAP_ASSERT assert
|
||||
#define XAP_REALLOC realloc
|
||||
#define XAP_ALLOC malloc
|
||||
#define XAP_FREE free
|
||||
|
||||
#define XAP_DA_INIT_CAP 256
|
||||
|
||||
|
@ -67,7 +124,7 @@
|
|||
} while (0)
|
||||
|
||||
#define XAP_DA_FREE(da) XAP_FREE((da).items)
|
||||
|
||||
/proc/sys/kernel/core_pattern
|
||||
#define XAP_DA_APPEND(da, new_items, new_items_count) \
|
||||
do { \
|
||||
if ((da)->count + (new_items_count) > (da)->capacity) { \
|
||||
|
@ -103,6 +160,7 @@ typedef struct xap_arg_t {
|
|||
char* description;
|
||||
void* value;
|
||||
void* default_value;
|
||||
bool required;
|
||||
xap_arg_type_e type;
|
||||
} xap_arg_t;
|
||||
|
||||
|
@ -133,6 +191,7 @@ typedef enum xap_result_t {
|
|||
|
||||
|
||||
xap_arg_t* xap_get_arg(xap_t* xap, char* arg_name);
|
||||
xap_result_t _xap_parse(xap_t* xap, int argc, char** argv); // used internally
|
||||
xap_result_t xap_parse(xap_t* xap, int argc, char** argv);
|
||||
char* xap_get_arg_value_str(xap_t* xap, char* arg_name);
|
||||
size_t* xap_get_arg_value_uint(xap_t* xap, char* arg_name);
|
||||
|
@ -140,9 +199,12 @@ s_size_t* xap_get_arg_value_int(xap_t* xap, char* arg_name);
|
|||
float* xap_get_arg_value_float(xap_t* xap, char* arg_name);
|
||||
bool* xap_get_arg_value_bool(xap_t* xap, char* arg_name);
|
||||
xap_result_t xap_parse_arg(xap_arg_t* arg, char* arg_text);
|
||||
void xap_free(xap_t xap);
|
||||
void xap_to_upper(char* str);
|
||||
void xap_to_lower(char* str);
|
||||
void xap_show_help(xap_t* xap);
|
||||
void xap_show_help(xap_t* xap);
|
||||
void _xap_log_error(char* format, ...);
|
||||
|
||||
|
||||
#ifdef XAP_IMPL
|
||||
|
||||
|
@ -177,7 +239,32 @@ xap_result_t xap_pre_parse(xap_t* xap) {
|
|||
#endif
|
||||
}
|
||||
|
||||
xap_result_t xap_post_check(xap_t* xap) {
|
||||
for (size_t i = 0; i < xap->args.count; i++) {
|
||||
xap_arg_t* arg_def = &xap->args.items[i];
|
||||
if (arg_def->required) {
|
||||
if (arg_def->value == NULL) {
|
||||
xap_show_help(xap);
|
||||
xap_log_error("Missing required value --%s\n", arg_def->s_long);
|
||||
return XAP_EXIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
return XAP_OK;
|
||||
}
|
||||
|
||||
xap_result_t xap_parse(xap_t* xap, int argc, char** argv) {
|
||||
xap_result_t res = _xap_parse(xap, argc, argv);
|
||||
|
||||
#ifdef XAP_EXIT_ON_ERROR
|
||||
if (res == XAP_EXIT) {
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
xap_result_t _xap_parse(xap_t* xap, int argc, char** argv) {
|
||||
xap->program = xap_shift_args(&argc, &argv);
|
||||
xap_pre_parse(xap);
|
||||
while (argc > 0) {
|
||||
|
@ -196,7 +283,8 @@ xap_result_t xap_parse(xap_t* xap, int argc, char** argv) {
|
|||
for (size_t i = 0; i < xap->args.count; i++) {
|
||||
xap_arg_t* arg_def = &xap->args.items[i];
|
||||
if (strcmp(arg_def->s_long, arg_str) == 0) {
|
||||
xap_parse_arg(arg_def, arg_str);
|
||||
xap_result_t res = xap_parse_arg(arg_def, arg_str);
|
||||
if (res != XAP_OK) return res;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -213,7 +301,8 @@ xap_result_t xap_parse(xap_t* xap, int argc, char** argv) {
|
|||
}
|
||||
|
||||
if (arg_def->s_short == arg_str[0]) {
|
||||
xap_parse_arg(arg_def, arg_str);
|
||||
xap_result_t res = xap_parse_arg(arg_def, arg_str);
|
||||
if (res != XAP_OK) return res;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -241,43 +330,74 @@ xap_result_t xap_parse(xap_t* xap, int argc, char** argv) {
|
|||
return XAP_EXIT;
|
||||
}
|
||||
#endif
|
||||
return XAP_OK;
|
||||
|
||||
return xap_post_check(xap);
|
||||
}
|
||||
|
||||
void xap_free(xap*) {
|
||||
for (size_t i = 0; i < xap->args.count; i++) {
|
||||
xap_arg_t* arg_def = &xap->args.items[i];
|
||||
XAP_FREE(arg_def->value)
|
||||
}
|
||||
XAP_FREE(xap->args.items);
|
||||
}
|
||||
|
||||
void xap_show_help(xap_t* xap) {
|
||||
// TODO: Formatting
|
||||
|
||||
char buf[256];
|
||||
|
||||
if (xap->description) {
|
||||
printf("%s\n", xap->description);
|
||||
}
|
||||
|
||||
printf("Usage: %s [options] ", xap->program);
|
||||
printf(XAP_C_UL "" XAP_C_BL "Usage" XAP_C_RS "" XAP_C_BL ": %s " XAP_C_RS "[options] ", xap->program);
|
||||
size_t indent_size = 0;
|
||||
|
||||
|
||||
for (size_t i = 0; i < xap->args.count; i++) {
|
||||
xap_arg_t* arg_def = &xap->args.items[i];
|
||||
|
||||
size_t len = strlen(arg_def->s_long);
|
||||
if (arg_def->required) {
|
||||
memcpy(buf, arg_def->s_long, 256);
|
||||
xap_to_upper(buf);
|
||||
|
||||
printf(XAP_C_BL "--%s" XAP_C_RS " <%s> ", arg_def->s_long, buf);
|
||||
len = (len * 2) + 3;
|
||||
if (len > indent_size) indent_size = len;
|
||||
} else {
|
||||
if (len > indent_size) indent_size = len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (xap->post_args_name != NULL) {
|
||||
printf("[args]");
|
||||
}
|
||||
printf("...\n\n");
|
||||
|
||||
if (xap->post_args_name && xap->post_args_description) {
|
||||
printf("Arguments:\n");
|
||||
printf(XAP_C_UL "" XAP_C_BL "Arguments:\n" XAP_C_RS);
|
||||
printf(" [%s]... %s\n\n",xap->post_args_name, xap->post_args_description);
|
||||
}
|
||||
|
||||
size_t indent_size = 0;
|
||||
|
||||
for (size_t i = 0; i < xap->args.count; i++) {
|
||||
xap_arg_t* arg_def = &xap->args.items[i];
|
||||
|
||||
size_t len = strlen(arg_def->s_long);
|
||||
if (len > indent_size) indent_size = len;
|
||||
}
|
||||
|
||||
|
||||
if (xap->args.count > 0) {
|
||||
printf("Options:\n");
|
||||
printf(XAP_C_UL "" XAP_C_BL "Options:\n" XAP_C_RS);
|
||||
|
||||
for (size_t i = 0; i < xap->args.count; i++) {
|
||||
xap_arg_t* arg_def = &xap->args.items[i];
|
||||
printf(" -%c, --%s", arg_def->s_short, arg_def->s_long);
|
||||
printf(" " XAP_C_BL "-%c" XAP_C_RS ", " XAP_C_BL "--%s" XAP_C_RS, arg_def->s_short, arg_def->s_long);
|
||||
|
||||
size_t len = strlen(arg_def->s_long);
|
||||
|
||||
if (arg_def->required) {
|
||||
memcpy(buf, arg_def->s_long, 256);
|
||||
xap_to_upper(buf);
|
||||
len = (len * 2) + 3;
|
||||
printf(" <%s>", buf);
|
||||
}
|
||||
|
||||
for (size_t y = 0; y <= indent_size - len; y++) {
|
||||
printf(" ");
|
||||
}
|
||||
|
@ -315,6 +435,14 @@ void xap_show_help(xap_t* xap) {
|
|||
}
|
||||
}
|
||||
|
||||
void _xap_log_error(char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
fprintf(stderr, XAP_C_BL"[" XAP_C_RED "ERROR" XAP_C_RS "" XAP_C_BL "] " XAP_C_RS);
|
||||
vfprintf(stderr, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void xap_print_args(xap_t* xap) {
|
||||
for (size_t i = 0; i < xap->args.count; i++) {
|
||||
xap_arg_t* arg_def = &xap->args.items[i];
|
||||
|
|
28
xap_test.c
28
xap_test.c
|
@ -1,4 +1,5 @@
|
|||
#define XAP_DISPLAY_VERSION
|
||||
#define XAP_USE_COLOR
|
||||
#define XAP_IMPL
|
||||
#include "xap.h"
|
||||
#include <stdio.h>
|
||||
|
@ -14,7 +15,9 @@ int main(int argc, char** argv) {
|
|||
xap_t xap = {
|
||||
.description = "Testing program for XAP :3",
|
||||
.version = "0.0.1",
|
||||
.footer = "This pogram is licenced under blah blah blah"
|
||||
.footer = "This pogram is licenced under blah blah blah",
|
||||
.post_args_name = "files",
|
||||
.post_args_description = "Files to blah blah :3"
|
||||
};
|
||||
|
||||
|
||||
|
@ -66,22 +69,35 @@ int main(int argc, char** argv) {
|
|||
.default_value = NULL // XAP_ARG_STR doesnt accept default values
|
||||
};
|
||||
|
||||
xap_arg_t a_req = {
|
||||
.s_long = "required",
|
||||
.s_short = 'r',
|
||||
.description = "A required value",
|
||||
.type = XAP_ARG_STR,
|
||||
.default_value = NULL,
|
||||
.required = true
|
||||
};
|
||||
|
||||
|
||||
xap_arg_add(&xap, a_str);
|
||||
xap_arg_add(&xap, a_uint);
|
||||
xap_arg_add(&xap, a_int);
|
||||
xap_arg_add(&xap, a_float);
|
||||
xap_arg_add(&xap, a_bool);
|
||||
xap_arg_add(&xap, a_bool);
|
||||
xap_arg_add(&xap, a_toggle);
|
||||
xap_arg_add(&xap, a_req);
|
||||
|
||||
xap_parse(&xap, argc, argv);
|
||||
|
||||
|
||||
// bool* v_str = xap_get_arg_value_str(&xap, "str");
|
||||
bool* v_str = xap_get_arg_value_str(&xap, "str");
|
||||
size_t* v_uint = xap_get_arg_value_uint(&xap, "uint");
|
||||
// bool* v_int = xap_get_arg_value_int(&xap, "int");
|
||||
// bool* v_float = xap_get_arg_value_float(&xap, "float");
|
||||
// bool* v_bool = xap_get_arg_value_bool(&xap, "bool");
|
||||
// s_size_t is a macro for ptrdiff_t aka signed size_t
|
||||
s_size_t* v_int = xap_get_arg_value_int(&xap, "int");
|
||||
float* v_float = xap_get_arg_value_float(&xap, "float");
|
||||
bool* v_bool = xap_get_arg_value_bool(&xap, "bool");
|
||||
|
||||
// xap_print_args(&xap);
|
||||
|
||||
// printf("Did not exit\n");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user