refactor(parse_config.h): replace the if else chain with a LUT loop approach

This commit is contained in:
ernestoCruz05 2026-04-11 09:42:12 +01:00
parent 7cfeeb3687
commit 417c052803

View file

@ -920,11 +920,108 @@ uint32_t parse_num_type(char *str) {
}
}
typedef enum {
ARG_NONE,
ARG_INT,
ARG_FLOAT,
ARG_UINT,
ARG_DIRECTION,
ARG_CIRCLE_DIR,
ARG_UINT_BIT,
ARG_STR_V,
ARG_MOUSE_ACTION,
ARG_INT_CLAMP,
ARG_SPECIAL_SETOPTION,
ARG_SPECIAL_VIEW,
ARG_SPECIAL_SPAWN,
ARG_SPECIAL_SPAWN_ON_EMPTY,
ARG_SPECIAL_TAG,
ARG_SPECIAL_FOCUSMON,
ARG_SPECIAL_TAGMON,
ARG_SPECIAL_CROSSMON,
ARG_SPECIAL_WINGEOM,
ARG_SPECIAL_TOGGLE_NAMED_SCRATCHPAD,
} ArgParseType;
typedef struct {
const char *name;
FuncType func;
ArgParseType arg_type;
} CmdEntry;
static const CmdEntry cmd_table[] = {
{ "focusstack", focusstack, ARG_CIRCLE_DIR },
{ "focusdir", focusdir, ARG_DIRECTION },
{ "incnmaster", incnmaster, ARG_INT },
{ "setmfact", setmfact, ARG_FLOAT },
{ "zoom", zoom, ARG_NONE },
{ "exchange_client", exchange_client, ARG_DIRECTION },
{ "exchange_stack_client", exchange_stack_client, ARG_CIRCLE_DIR },
{ "toggleglobal", toggleglobal, ARG_NONE },
{ "toggleoverview", toggleoverview, ARG_INT },
{ "set_proportion", set_proportion, ARG_FLOAT },
{ "switch_proportion_preset", switch_proportion_preset, ARG_CIRCLE_DIR },
{ "viewtoleft", viewtoleft, ARG_INT },
{ "viewtoright", viewtoright, ARG_INT },
{ "tagsilent", tagsilent, ARG_UINT_BIT },
{ "tagtoleft", tagtoleft, ARG_INT },
{ "tagtoright", tagtoright, ARG_INT },
{ "killclient", killclient, ARG_NONE },
{ "centerwin", centerwin, ARG_NONE },
{ "focuslast", focuslast, ARG_NONE },
{ "toggle_trackpad_enable", toggle_trackpad_enable, ARG_NONE },
{ "setoption", setoption, ARG_SPECIAL_SETOPTION },
{ "setkeymode", setkeymode, ARG_STR_V },
{ "switch_keyboard_layout", switch_keyboard_layout, ARG_INT_CLAMP },
{ "setlayout", setlayout, ARG_STR_V },
{ "switch_layout", switch_layout, ARG_NONE },
{ "togglefloating", togglefloating, ARG_NONE },
{ "togglefullscreen", togglefullscreen, ARG_NONE },
{ "togglefakefullscreen", togglefakefullscreen, ARG_NONE },
{ "toggleoverlay", toggleoverlay, ARG_NONE },
{ "minimized", minimized, ARG_NONE },
{ "restore_minimized", restore_minimized, ARG_NONE },
{ "toggle_scratchpad", toggle_scratchpad, ARG_NONE },
{ "toggle_render_border", toggle_render_border, ARG_NONE },
{ "focusmon", focusmon, ARG_SPECIAL_FOCUSMON },
{ "tagmon", tagmon, ARG_SPECIAL_TAGMON },
{ "incgaps", incgaps, ARG_INT },
{ "togglegaps", togglegaps, ARG_NONE },
{ "chvt", chvt, ARG_UINT },
{ "spawn", spawn, ARG_SPECIAL_SPAWN },
{ "spawn_shell", spawn_shell, ARG_SPECIAL_SPAWN },
{ "spawn_on_empty", spawn_on_empty, ARG_SPECIAL_SPAWN_ON_EMPTY },
{ "quit", quit, ARG_NONE },
{ "create_virtual_output", create_virtual_output, ARG_NONE },
{ "destroy_all_virtual_output", destroy_all_virtual_output, ARG_NONE },
{ "moveresize", moveresize, ARG_MOUSE_ACTION },
{ "togglemaximizescreen", togglemaximizescreen, ARG_NONE },
{ "viewtoleft_have_client", viewtoleft_have_client, ARG_INT },
{ "viewtoright_have_client", viewtoright_have_client, ARG_INT },
{ "reload_config", reload_config, ARG_NONE },
{ "tag", tag, ARG_SPECIAL_TAG },
{ "view", bind_to_view, ARG_SPECIAL_VIEW },
{ "viewcrossmon", viewcrossmon, ARG_SPECIAL_CROSSMON },
{ "tagcrossmon", tagcrossmon, ARG_SPECIAL_CROSSMON },
{ "toggletag", toggletag, ARG_UINT_BIT },
{ "toggleview", toggleview, ARG_UINT_BIT },
{ "comboview", comboview, ARG_UINT_BIT },
{ "smartmovewin", smartmovewin, ARG_DIRECTION },
{ "smartresizewin", smartresizewin, ARG_DIRECTION },
{ "resizewin", resizewin, ARG_SPECIAL_WINGEOM },
{ "movewin", movewin, ARG_SPECIAL_WINGEOM },
{ "toggle_named_scratchpad", toggle_named_scratchpad, ARG_SPECIAL_TOGGLE_NAMED_SCRATCHPAD },
{ "disable_monitor", disable_monitor, ARG_STR_V },
{ "enable_monitor", enable_monitor, ARG_STR_V },
{ "toggle_monitor", toggle_monitor, ARG_STR_V },
{ "scroller_stack", scroller_stack, ARG_DIRECTION },
{ "toggle_all_floating", toggle_all_floating, ARG_NONE },
};
FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value,
char *arg_value2, char *arg_value3, char *arg_value4,
char *arg_value5) {
FuncType func = NULL;
(*arg).i = 0;
(*arg).i2 = 0;
(*arg).f = 0.0f;
@ -935,279 +1032,147 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value,
(*arg).v2 = NULL;
(*arg).v3 = NULL;
if (strcmp(func_name, "focusstack") == 0) {
func = focusstack;
(*arg).i = parse_circle_direction(arg_value);
} else if (strcmp(func_name, "focusdir") == 0) {
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;
(*arg).i = parse_circle_direction(arg_value);
} 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;
const size_t table_len = sizeof(cmd_table) / sizeof(cmd_table[0]);
(*arg).v = strdup(arg_value);
for (size_t k = 0; k < table_len; k++) {
if (strcmp(func_name, cmd_table[k].name) != 0)
continue;
// 收集需要拼接的参数
const char *non_empty_params[4] = {NULL};
int32_t param_index = 0;
FuncType func = cmd_table[k].func;
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 (int32_t i = 0; i < param_index; i++) {
len += strlen(non_empty_params[i]);
}
len += (param_index - 1) + 1; // 逗号数 + null终止符
char *temp = malloc(len);
if (temp) {
char *cursor = temp;
for (int32_t i = 0; i < param_index; i++) {
if (i > 0) {
*cursor++ = ',';
switch (cmd_table[k].arg_type) {
case ARG_NONE:
break;
case ARG_INT:
(*arg).i = atoi(arg_value);
break;
case ARG_FLOAT:
(*arg).f = atof(arg_value);
break;
case ARG_UINT:
(*arg).ui = (uint32_t)atoi(arg_value);
break;
case ARG_DIRECTION:
(*arg).i = parse_direction(arg_value);
break;
case ARG_CIRCLE_DIR:
(*arg).i = parse_circle_direction(arg_value);
break;
case ARG_UINT_BIT:
(*arg).ui = 1 << (atoi(arg_value) - 1);
break;
case ARG_STR_V:
(*arg).v = strdup(arg_value);
break;
case ARG_MOUSE_ACTION:
(*arg).ui = parse_mouse_action(arg_value);
break;
case ARG_INT_CLAMP:
(*arg).i = CLAMP_INT(atoi(arg_value), 0, 100);
break;
case ARG_SPECIAL_SETOPTION: {
(*arg).v = strdup(arg_value);
const char *non_empty_params[4] = {NULL};
int32_t 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 (int32_t 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 (int32_t 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;
}
size_t param_len = strlen(non_empty_params[i]);
memcpy(cursor, non_empty_params[i], param_len);
cursor += param_len;
*cursor = '\0';
(*arg).v2 = temp;
}
*cursor = '\0';
(*arg).v2 = temp;
}
break;
}
} 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;
(*arg).i = CLAMP_INT(atoi(arg_value), 0, 100);
} 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;
char *values[] = {arg_value, arg_value2, arg_value3, arg_value4,
arg_value5};
(*arg).v = combine_args_until_empty(values, 5);
} else if (strcmp(func_name, "spawn_shell") == 0) {
func = spawn_shell;
char *values[] = {arg_value, arg_value2, arg_value3, arg_value4,
arg_value5};
(*arg).v = combine_args_until_empty(values, 5);
} 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;
uint32_t mask = 0;
char *token;
char *arg_copy = strdup(arg_value);
if (arg_copy != NULL) {
char *saveptr = NULL;
token = strtok_r(arg_copy, "|", &saveptr);
while (token != NULL) {
int32_t num = atoi(token);
if (num > 0 && num <= LENGTH(tags)) {
mask |= (1 << (num - 1));
case ARG_SPECIAL_VIEW: {
uint32_t mask = 0;
char *arg_copy = strdup(arg_value);
if (arg_copy != NULL) {
char *saveptr = NULL;
char *token = strtok_r(arg_copy, "|", &saveptr);
while (token != NULL) {
int32_t num = atoi(token);
if (num > 0 && num <= (int32_t)LENGTH(tags))
mask |= (1 << (num - 1));
token = strtok_r(NULL, "|", &saveptr);
}
token = strtok_r(NULL, "|", &saveptr);
free(arg_copy);
}
free(arg_copy);
(*arg).ui = mask ? mask : (uint32_t)atoi(arg_value);
(*arg).i = atoi(arg_value2);
break;
}
case ARG_SPECIAL_SPAWN: {
char *values[] = {arg_value, arg_value2, arg_value3, arg_value4,
arg_value5};
(*arg).v = combine_args_until_empty(values, 5);
break;
}
case ARG_SPECIAL_SPAWN_ON_EMPTY:
(*arg).v = strdup(arg_value);
(*arg).ui = 1 << (atoi(arg_value2) - 1);
break;
case ARG_SPECIAL_TAG:
(*arg).ui = 1 << (atoi(arg_value) - 1);
(*arg).i = atoi(arg_value2);
break;
case ARG_SPECIAL_FOCUSMON:
(*arg).i = parse_direction(arg_value);
if ((*arg).i == UNDIR)
(*arg).v = strdup(arg_value);
break;
case ARG_SPECIAL_TAGMON:
(*arg).i = parse_direction(arg_value);
(*arg).i2 = atoi(arg_value2);
if ((*arg).i == UNDIR)
(*arg).v = strdup(arg_value);
break;
case ARG_SPECIAL_CROSSMON:
(*arg).ui = 1 << (atoi(arg_value) - 1);
(*arg).v = strdup(arg_value2);
break;
case ARG_SPECIAL_WINGEOM:
(*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 ARG_SPECIAL_TOGGLE_NAMED_SCRATCHPAD:
(*arg).v = strdup(arg_value);
(*arg).v2 = strdup(arg_value2);
(*arg).v3 = strdup(arg_value3);
break;
default:
break;
}
if (mask) {
(*arg).ui = mask;
} else {
(*arg).ui = atoi(arg_value);
}
(*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 if (strcmp(func_name, "scroller_stack") == 0) {
func = scroller_stack;
(*arg).i = parse_direction(arg_value);
} else if (strcmp(func_name, "toggle_all_floating") == 0) {
func = toggle_all_floating;
} else {
return NULL;
return func;
}
return func;
return NULL;
}
void set_env() {