Fixed duplicative nature of config parser, added X macro to handle various versions of config parsed functions, also added 6 functions that werent handled.

This commit is contained in:
tonybtw 2025-11-11 12:39:08 -08:00
parent 64d8764f58
commit 859e9a91de
3 changed files with 224 additions and 304 deletions

View file

@ -851,253 +851,168 @@ unsigned int parse_num_type(char *str) {
} }
} }
typedef struct {
const char *name;
FuncType func;
int parser_type;
} FuncEntry;
#define PARSE_NONE 0
#define PARSE_INT 1
#define PARSE_FLOAT 2
#define PARSE_STR 3
#define PARSE_UINT 4
#define PARSE_TAG 5
#define PARSE_DIR 6
#define PARSE_CIRCLE_DIR 7
#define PARSE_MOUSE_ACTION 8
#define PARSE_TAG_INT2 9
#define PARSE_TAG_STR2 10
#define PARSE_DIR_OR_STR 11
#define PARSE_DIR_OR_STR_INT2 12
#define PARSE_STR_TAG2 13
#define PARSE_OPTION 14
#define PARSE_NUMTYPE_NUMTYPE 15
#define PARSE_STR_STR2_STR3 16
#define REGISTER_FUNC(name, parser) {#name, name, parser},
#define REGISTER_FUNC_ALIAS(alias, name, parser) {#alias, name, parser},
static const FuncEntry func_registry[] = {
#include "../dispatch/function_registry.def"
};
#undef REGISTER_FUNC
#undef REGISTER_FUNC_ALIAS
static const size_t func_registry_size = sizeof(func_registry) / sizeof(func_registry[0]);
FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value, FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value,
char *arg_value2, char *arg_value3, char *arg_value4, char *arg_value2, char *arg_value3, char *arg_value4,
char *arg_value5) { char *arg_value5) {
FuncType func = NULL;
(*arg).v = NULL; (*arg).v = NULL;
(*arg).v2 = NULL; (*arg).v2 = NULL;
(*arg).v3 = NULL; (*arg).v3 = NULL;
if (strcmp(func_name, "focusstack") == 0) { for (size_t i = 0; i < func_registry_size; i++) {
func = focusstack; if (strcmp(func_name, func_registry[i].name) == 0) {
(*arg).i = parse_circle_direction(arg_value); FuncType func = func_registry[i].func;
} else if (strcmp(func_name, "focusdir") == 0) { int parser = func_registry[i].parser_type;
func = focusdir;
(*arg).i = parse_direction(arg_value);
} else if (strcmp(func_name, "incnmaster") == 0) {
func = incnmaster;
(*arg).i = atoi(arg_value);
} else if (strcmp(func_name, "setmfact") == 0) {
func = setmfact;
(*arg).f = atof(arg_value);
} else if (strcmp(func_name, "zoom") == 0) {
func = zoom;
} else if (strcmp(func_name, "exchange_client") == 0) {
func = exchange_client;
(*arg).i = parse_direction(arg_value);
} else if (strcmp(func_name, "exchange_stack_client") == 0) {
func = exchange_stack_client;
(*arg).i = parse_circle_direction(arg_value);
} else if (strcmp(func_name, "toggleglobal") == 0) {
func = toggleglobal;
} else if (strcmp(func_name, "toggleoverview") == 0) {
func = toggleoverview;
(*arg).i = atoi(arg_value);
} else if (strcmp(func_name, "set_proportion") == 0) {
func = set_proportion;
(*arg).f = atof(arg_value);
} else if (strcmp(func_name, "switch_proportion_preset") == 0) {
func = switch_proportion_preset;
} else if (strcmp(func_name, "viewtoleft") == 0) {
func = viewtoleft;
(*arg).i = atoi(arg_value);
} else if (strcmp(func_name, "viewtoright") == 0) {
func = viewtoright;
(*arg).i = atoi(arg_value);
} else if (strcmp(func_name, "tagsilent") == 0) {
func = tagsilent;
(*arg).ui = 1 << (atoi(arg_value) - 1);
} else if (strcmp(func_name, "tagtoleft") == 0) {
func = tagtoleft;
(*arg).i = atoi(arg_value);
} else if (strcmp(func_name, "tagtoright") == 0) {
func = tagtoright;
(*arg).i = atoi(arg_value);
} else if (strcmp(func_name, "killclient") == 0) {
func = killclient;
} else if (strcmp(func_name, "centerwin") == 0) {
func = centerwin;
} else if (strcmp(func_name, "focuslast") == 0) {
func = focuslast;
} else if (strcmp(func_name, "toggle_trackpad_enable") == 0) {
func = toggle_trackpad_enable;
} else if (strcmp(func_name, "setoption") == 0) {
func = setoption;
(*arg).v = strdup(arg_value); switch (parser) {
case PARSE_NONE:
// 收集需要拼接的参数 break;
const char *non_empty_params[4] = {NULL}; case PARSE_INT:
int param_index = 0; (*arg).i = atoi(arg_value);
break;
if (arg_value2 && arg_value2[0] != '\0') case PARSE_FLOAT:
non_empty_params[param_index++] = arg_value2; (*arg).f = atof(arg_value);
if (arg_value3 && arg_value3[0] != '\0') break;
non_empty_params[param_index++] = arg_value3; case PARSE_STR:
if (arg_value4 && arg_value4[0] != '\0') (*arg).v = strdup(arg_value);
non_empty_params[param_index++] = arg_value4; break;
if (arg_value5 && arg_value5[0] != '\0') case PARSE_UINT:
non_empty_params[param_index++] = arg_value5; (*arg).ui = atoi(arg_value);
break;
// 处理拼接 case PARSE_TAG:
if (param_index == 0) { (*arg).ui = 1 << (atoi(arg_value) - 1);
(*arg).v2 = strdup(""); break;
} else { case PARSE_DIR:
// 计算总长度 (*arg).i = parse_direction(arg_value);
size_t len = 0; break;
for (int i = 0; i < param_index; i++) { case PARSE_CIRCLE_DIR:
len += strlen(non_empty_params[i]); (*arg).i = parse_circle_direction(arg_value);
} break;
len += (param_index - 1) + 1; // 逗号数 + null终止符 case PARSE_MOUSE_ACTION:
(*arg).ui = parse_mouse_action(arg_value);
char *temp = malloc(len); break;
if (temp) { case PARSE_TAG_INT2:
char *cursor = temp; (*arg).ui = 1 << (atoi(arg_value) - 1);
for (int i = 0; i < param_index; i++) { (*arg).i = atoi(arg_value2);
if (i > 0) { break;
*cursor++ = ','; case PARSE_TAG_STR2:
(*arg).ui = 1 << (atoi(arg_value) - 1);
(*arg).v = strdup(arg_value2);
break;
case PARSE_DIR_OR_STR:
(*arg).i = parse_direction(arg_value);
if ((*arg).i == UNDIR) {
(*arg).v = strdup(arg_value);
} }
size_t param_len = strlen(non_empty_params[i]); break;
memcpy(cursor, non_empty_params[i], param_len); case PARSE_DIR_OR_STR_INT2:
cursor += param_len; (*arg).i = parse_direction(arg_value);
(*arg).i2 = atoi(arg_value2);
if ((*arg).i == UNDIR) {
(*arg).v = strdup(arg_value);
}
break;
case PARSE_STR_TAG2:
(*arg).v = strdup(arg_value);
(*arg).ui = 1 << (atoi(arg_value2) - 1);
break;
case PARSE_OPTION: {
(*arg).v = strdup(arg_value);
const char *non_empty_params[4] = {NULL};
int param_index = 0;
if (arg_value2 && arg_value2[0] != '\0')
non_empty_params[param_index++] = arg_value2;
if (arg_value3 && arg_value3[0] != '\0')
non_empty_params[param_index++] = arg_value3;
if (arg_value4 && arg_value4[0] != '\0')
non_empty_params[param_index++] = arg_value4;
if (arg_value5 && arg_value5[0] != '\0')
non_empty_params[param_index++] = arg_value5;
if (param_index == 0) {
(*arg).v2 = strdup("");
} else {
size_t len = 0;
for (int j = 0; j < param_index; j++) {
len += strlen(non_empty_params[j]);
}
len += (param_index - 1) + 1;
char *temp = malloc(len);
if (temp) {
char *cursor = temp;
for (int j = 0; j < param_index; j++) {
if (j > 0) {
*cursor++ = ',';
}
size_t param_len = strlen(non_empty_params[j]);
memcpy(cursor, non_empty_params[j], param_len);
cursor += param_len;
}
*cursor = '\0';
(*arg).v2 = temp;
}
}
break;
} }
*cursor = '\0'; case PARSE_NUMTYPE_NUMTYPE:
(*arg).v2 = temp; (*arg).ui = parse_num_type(arg_value);
(*arg).ui2 = parse_num_type(arg_value2);
(*arg).i = (*arg).ui == NUM_TYPE_DEFAULT ? atoi(arg_value)
: atoi(arg_value + 1);
(*arg).i2 = (*arg).ui2 == NUM_TYPE_DEFAULT ? atoi(arg_value2)
: atoi(arg_value2 + 1);
break;
case PARSE_STR_STR2_STR3:
(*arg).v = strdup(arg_value);
(*arg).v2 = strdup(arg_value2);
(*arg).v3 = strdup(arg_value3);
break;
} }
return func;
} }
} else if (strcmp(func_name, "setkeymode") == 0) {
func = setkeymode;
(*arg).v = strdup(arg_value);
} else if (strcmp(func_name, "switch_keyboard_layout") == 0) {
func = switch_keyboard_layout;
} else if (strcmp(func_name, "setlayout") == 0) {
func = setlayout;
(*arg).v = strdup(arg_value);
} else if (strcmp(func_name, "switch_layout") == 0) {
func = switch_layout;
} else if (strcmp(func_name, "togglefloating") == 0) {
func = togglefloating;
} else if (strcmp(func_name, "togglefullscreen") == 0) {
func = togglefullscreen;
} else if (strcmp(func_name, "togglefakefullscreen") == 0) {
func = togglefakefullscreen;
} else if (strcmp(func_name, "toggleoverlay") == 0) {
func = toggleoverlay;
} else if (strcmp(func_name, "minimized") == 0) {
func = minimized;
} else if (strcmp(func_name, "restore_minimized") == 0) {
func = restore_minimized;
} else if (strcmp(func_name, "toggle_scratchpad") == 0) {
func = toggle_scratchpad;
} else if (strcmp(func_name, "toggle_render_border") == 0) {
func = toggle_render_border;
} else if (strcmp(func_name, "focusmon") == 0) {
func = focusmon;
(*arg).i = parse_direction(arg_value);
if ((*arg).i == UNDIR) {
(*arg).v = strdup(arg_value);
}
} else if (strcmp(func_name, "tagmon") == 0) {
func = tagmon;
(*arg).i = parse_direction(arg_value);
(*arg).i2 = atoi(arg_value2);
if ((*arg).i == UNDIR) {
(*arg).v = strdup(arg_value);
};
} else if (strcmp(func_name, "incgaps") == 0) {
func = incgaps;
(*arg).i = atoi(arg_value);
} else if (strcmp(func_name, "togglegaps") == 0) {
func = togglegaps;
} else if (strcmp(func_name, "chvt") == 0) {
func = chvt;
(*arg).ui = atoi(arg_value);
} else if (strcmp(func_name, "spawn") == 0) {
func = spawn;
(*arg).v = strdup(arg_value);
} else if (strcmp(func_name, "spawn_shell") == 0) {
func = spawn_shell;
(*arg).v = strdup(arg_value);
} else if (strcmp(func_name, "spawn_on_empty") == 0) {
func = spawn_on_empty;
(*arg).v = strdup(arg_value); // 注意:之后需要释放这个内存
(*arg).ui = 1 << (atoi(arg_value2) - 1);
} else if (strcmp(func_name, "quit") == 0) {
func = quit;
} else if (strcmp(func_name, "create_virtual_output") == 0) {
func = create_virtual_output;
} else if (strcmp(func_name, "destroy_all_virtual_output") == 0) {
func = destroy_all_virtual_output;
} else if (strcmp(func_name, "moveresize") == 0) {
func = moveresize;
(*arg).ui = parse_mouse_action(arg_value);
} else if (strcmp(func_name, "togglemaximizescreen") == 0) {
func = togglemaximizescreen;
} else if (strcmp(func_name, "viewtoleft_have_client") == 0) {
func = viewtoleft_have_client;
(*arg).i = atoi(arg_value);
} else if (strcmp(func_name, "viewtoright_have_client") == 0) {
func = viewtoright_have_client;
(*arg).i = atoi(arg_value);
} else if (strcmp(func_name, "reload_config") == 0) {
func = reload_config;
} else if (strcmp(func_name, "tag") == 0) {
func = tag;
(*arg).ui = 1 << (atoi(arg_value) - 1);
(*arg).i = atoi(arg_value2);
} else if (strcmp(func_name, "view") == 0) {
func = bind_to_view;
(*arg).ui = 1 << (atoi(arg_value) - 1);
(*arg).i = atoi(arg_value2);
} else if (strcmp(func_name, "viewcrossmon") == 0) {
func = viewcrossmon;
(*arg).ui = 1 << (atoi(arg_value) - 1);
(*arg).v = strdup(arg_value2);
} else if (strcmp(func_name, "tagcrossmon") == 0) {
func = tagcrossmon;
(*arg).ui = 1 << (atoi(arg_value) - 1);
(*arg).v = strdup(arg_value2);
} else if (strcmp(func_name, "toggletag") == 0) {
func = toggletag;
(*arg).ui = 1 << (atoi(arg_value) - 1);
} else if (strcmp(func_name, "toggleview") == 0) {
func = toggleview;
(*arg).ui = 1 << (atoi(arg_value) - 1);
} else if (strcmp(func_name, "comboview") == 0) {
func = comboview;
(*arg).ui = 1 << (atoi(arg_value) - 1);
} else if (strcmp(func_name, "smartmovewin") == 0) {
func = smartmovewin;
(*arg).i = parse_direction(arg_value);
} else if (strcmp(func_name, "smartresizewin") == 0) {
func = smartresizewin;
(*arg).i = parse_direction(arg_value);
} else if (strcmp(func_name, "resizewin") == 0) {
func = resizewin;
(*arg).ui = parse_num_type(arg_value);
(*arg).ui2 = parse_num_type(arg_value2);
(*arg).i = (*arg).ui == NUM_TYPE_DEFAULT ? atoi(arg_value)
: atoi(arg_value + 1);
(*arg).i2 = (*arg).ui2 == NUM_TYPE_DEFAULT ? atoi(arg_value2)
: atoi(arg_value2 + 1);
} else if (strcmp(func_name, "movewin") == 0) {
func = movewin;
(*arg).ui = parse_num_type(arg_value);
(*arg).ui2 = parse_num_type(arg_value2);
(*arg).i = (*arg).ui == NUM_TYPE_DEFAULT ? atoi(arg_value)
: atoi(arg_value + 1);
(*arg).i2 = (*arg).ui2 == NUM_TYPE_DEFAULT ? atoi(arg_value2)
: atoi(arg_value2 + 1);
} else if (strcmp(func_name, "toggle_named_scratchpad") == 0) {
func = toggle_named_scratchpad;
(*arg).v = strdup(arg_value);
(*arg).v2 = strdup(arg_value2);
(*arg).v3 = strdup(arg_value3);
} else if (strcmp(func_name, "disable_monitor") == 0) {
func = disable_monitor;
(*arg).v = strdup(arg_value);
} else if (strcmp(func_name, "enable_monitor") == 0) {
func = enable_monitor;
(*arg).v = strdup(arg_value);
} else if (strcmp(func_name, "toggle_monitor") == 0) {
func = toggle_monitor;
(*arg).v = strdup(arg_value);
} else {
return NULL;
} }
return func;
return NULL;
} }
void set_env() { void set_env() {

View file

@ -1,71 +1,5 @@
int minimized(const Arg *arg); #define REGISTER_FUNC(name, parser) int name(const Arg *arg);
int restore_minimized(const Arg *arg); #define REGISTER_FUNC_ALIAS(alias, name, parser) int name(const Arg *arg);
int toggle_scratchpad(const Arg *arg); #include "function_registry.def"
int focusdir(const Arg *arg); #undef REGISTER_FUNC
int toggleoverview(const Arg *arg); #undef REGISTER_FUNC_ALIAS
int set_proportion(const Arg *arg);
int switch_proportion_preset(const Arg *arg);
int zoom(const Arg *arg);
int tagsilent(const Arg *arg);
int tagtoleft(const Arg *arg);
int tagtoright(const Arg *arg);
int tagcrossmon(const Arg *arg);
int viewtoleft(const Arg *arg);
int viewtoright(const Arg *arg);
int viewtoleft_have_client(const Arg *arg);
int viewtoright_have_client(const Arg *arg);
int viewcrossmon(const Arg *arg);
int togglefloating(const Arg *arg);
int togglefullscreen(const Arg *arg);
int togglemaximizescreen(const Arg *arg);
int togglegaps(const Arg *arg);
int tagmon(const Arg *arg);
int spawn(const Arg *arg);
int spawn_shell(const Arg *arg);
int spawn_on_empty(const Arg *arg);
int setkeymode(const Arg *arg);
int switch_keyboard_layout(const Arg *arg);
int setlayout(const Arg *arg);
int switch_layout(const Arg *arg);
int setmfact(const Arg *arg);
int quit(const Arg *arg);
int moveresize(const Arg *arg);
int exchange_client(const Arg *arg);
int exchange_stack_client(const Arg *arg);
int killclient(const Arg *arg);
int toggleglobal(const Arg *arg);
int incnmaster(const Arg *arg);
int focusmon(const Arg *arg);
int focusstack(const Arg *arg);
int chvt(const Arg *arg);
int reload_config(const Arg *arg);
int smartmovewin(const Arg *arg);
int smartresizewin(const Arg *arg);
int centerwin(const Arg *arg);
int bind_to_view(const Arg *arg);
int toggletag(const Arg *arg);
int toggleview(const Arg *arg);
int tag(const Arg *arg);
int comboview(const Arg *arg);
int incgaps(const Arg *arg);
int incigaps(const Arg *arg);
int incihgaps(const Arg *arg);
int incivgaps(const Arg *arg);
int incogaps(const Arg *arg);
int incohgaps(const Arg *arg);
int incovgaps(const Arg *arg);
int defaultgaps(const Arg *arg);
int togglefakefullscreen(const Arg *arg);
int toggleoverlay(const Arg *arg);
int movewin(const Arg *arg);
int resizewin(const Arg *arg);
int toggle_named_scratchpad(const Arg *arg);
int toggle_render_border(const Arg *arg);
int create_virtual_output(const Arg *arg);
int destroy_all_virtual_output(const Arg *arg);
int focuslast(const Arg *arg);
int toggle_trackpad_enable(const Arg *arg);
int setoption(const Arg *arg);
int disable_monitor(const Arg *arg);
int enable_monitor(const Arg *arg);
int toggle_monitor(const Arg *arg);

View file

@ -0,0 +1,71 @@
REGISTER_FUNC(focusstack, PARSE_CIRCLE_DIR)
REGISTER_FUNC(focusdir, PARSE_DIR)
REGISTER_FUNC(incnmaster, PARSE_INT)
REGISTER_FUNC(setmfact, PARSE_FLOAT)
REGISTER_FUNC(zoom, PARSE_NONE)
REGISTER_FUNC(exchange_client, PARSE_DIR)
REGISTER_FUNC(exchange_stack_client, PARSE_CIRCLE_DIR)
REGISTER_FUNC(toggleglobal, PARSE_NONE)
REGISTER_FUNC(toggleoverview, PARSE_INT)
REGISTER_FUNC(set_proportion, PARSE_FLOAT)
REGISTER_FUNC(switch_proportion_preset, PARSE_NONE)
REGISTER_FUNC(viewtoleft, PARSE_INT)
REGISTER_FUNC(viewtoright, PARSE_INT)
REGISTER_FUNC(tagsilent, PARSE_TAG)
REGISTER_FUNC(tagtoleft, PARSE_INT)
REGISTER_FUNC(tagtoright, PARSE_INT)
REGISTER_FUNC(killclient, PARSE_NONE)
REGISTER_FUNC(centerwin, PARSE_NONE)
REGISTER_FUNC(focuslast, PARSE_NONE)
REGISTER_FUNC(toggle_trackpad_enable, PARSE_NONE)
REGISTER_FUNC(setoption, PARSE_OPTION)
REGISTER_FUNC(setkeymode, PARSE_STR)
REGISTER_FUNC(switch_keyboard_layout, PARSE_NONE)
REGISTER_FUNC(setlayout, PARSE_STR)
REGISTER_FUNC(switch_layout, PARSE_NONE)
REGISTER_FUNC(togglefloating, PARSE_NONE)
REGISTER_FUNC(togglefullscreen, PARSE_NONE)
REGISTER_FUNC(togglefakefullscreen, PARSE_NONE)
REGISTER_FUNC(toggleoverlay, PARSE_NONE)
REGISTER_FUNC(minimized, PARSE_NONE)
REGISTER_FUNC(restore_minimized, PARSE_NONE)
REGISTER_FUNC(toggle_scratchpad, PARSE_NONE)
REGISTER_FUNC(toggle_render_border, PARSE_NONE)
REGISTER_FUNC(focusmon, PARSE_DIR_OR_STR)
REGISTER_FUNC(tagmon, PARSE_DIR_OR_STR_INT2)
REGISTER_FUNC(incgaps, PARSE_INT)
REGISTER_FUNC(togglegaps, PARSE_NONE)
REGISTER_FUNC(chvt, PARSE_UINT)
REGISTER_FUNC(spawn, PARSE_STR)
REGISTER_FUNC(spawn_shell, PARSE_STR)
REGISTER_FUNC(spawn_on_empty, PARSE_STR_TAG2)
REGISTER_FUNC(quit, PARSE_NONE)
REGISTER_FUNC(create_virtual_output, PARSE_NONE)
REGISTER_FUNC(destroy_all_virtual_output, PARSE_NONE)
REGISTER_FUNC(moveresize, PARSE_MOUSE_ACTION)
REGISTER_FUNC(togglemaximizescreen, PARSE_NONE)
REGISTER_FUNC(viewtoleft_have_client, PARSE_INT)
REGISTER_FUNC(viewtoright_have_client, PARSE_INT)
REGISTER_FUNC(reload_config, PARSE_NONE)
REGISTER_FUNC(tag, PARSE_TAG_INT2)
REGISTER_FUNC_ALIAS(view, bind_to_view, PARSE_TAG_INT2)
REGISTER_FUNC(viewcrossmon, PARSE_TAG_STR2)
REGISTER_FUNC(tagcrossmon, PARSE_TAG_STR2)
REGISTER_FUNC(toggletag, PARSE_TAG)
REGISTER_FUNC(toggleview, PARSE_TAG)
REGISTER_FUNC(comboview, PARSE_TAG)
REGISTER_FUNC(smartmovewin, PARSE_DIR)
REGISTER_FUNC(smartresizewin, PARSE_DIR)
REGISTER_FUNC(resizewin, PARSE_NUMTYPE_NUMTYPE)
REGISTER_FUNC(movewin, PARSE_NUMTYPE_NUMTYPE)
REGISTER_FUNC(toggle_named_scratchpad, PARSE_STR_STR2_STR3)
REGISTER_FUNC(disable_monitor, PARSE_STR)
REGISTER_FUNC(enable_monitor, PARSE_STR)
REGISTER_FUNC(toggle_monitor, PARSE_STR)
REGISTER_FUNC(incigaps, PARSE_NONE)
REGISTER_FUNC(incihgaps, PARSE_NONE)
REGISTER_FUNC(incivgaps, PARSE_NONE)
REGISTER_FUNC(incogaps, PARSE_NONE)
REGISTER_FUNC(incohgaps, PARSE_NONE)
REGISTER_FUNC(incovgaps, PARSE_NONE)
REGISTER_FUNC(defaultgaps, PARSE_NONE)