feat: Spaces are allowed before and after the fields in config

This commit is contained in:
DreamMaoMao 2025-05-12 08:14:04 +08:00
parent 0a79024da8
commit bc4f598259

View file

@ -212,6 +212,54 @@ typedef struct {
typedef void (*FuncType)(const Arg *);
Config config;
// Helper function to trim whitespace from start and end of a string
void trim_whitespace(char *str) {
if (str == NULL || *str == '\0') return;
// Trim leading space
char *start = str;
while (isspace((unsigned char)*start)) {
start++;
}
// Trim trailing space
char *end = str + strlen(str) - 1;
while (end > start && isspace((unsigned char)*end)) {
end--;
}
// Null-terminate the trimmed string
*(end + 1) = '\0';
// Move the trimmed part to the beginning if needed
if (start != str) {
memmove(str, start, end - start + 2); // +2 to include null terminator
}
}
int parse_double_array(const char *input, double *output, int max_count) {
char *dup = strdup(input); // 复制一份用于修改
char *token;
int count = 0;
token = strtok(dup, ",");
while (token != NULL && count < max_count) {
trim_whitespace(token); // 对每一个分割后的 token 去除前后空格
char *endptr;
double val = strtod(token, &endptr);
if (endptr == token || *endptr != '\0') {
fprintf(stderr, "Error: Invalid number in array: %s\n", token);
free(dup);
return -1; // 解析失败
}
output[count++] = val;
token = strtok(NULL, ",");
}
free(dup);
return count;
}
// 清理字符串中的不可见字符(包括 \r, \n, 空格等)
char *sanitize_string(char *str) {
// 去除首部不可见字符
@ -611,6 +659,10 @@ void parse_config_line(Config *config, const char *line) {
return;
}
// Then trim each part separately
trim_whitespace(key);
trim_whitespace(value);
if (strcmp(key, "animations") == 0) {
config->animations = atoi(value);
} else if (strcmp(key, "animation_type_open") == 0) {
@ -638,34 +690,24 @@ void parse_config_line(Config *config, const char *line) {
} else if (strcmp(key, "animation_duration_close") == 0) {
config->animation_duration_close = atoi(value);
} else if (strcmp(key, "animation_curve_move") == 0) {
if (sscanf(value, "%lf,%lf,%lf,%lf", &config->animation_curve_move[0],
&config->animation_curve_move[1],
&config->animation_curve_move[2],
&config->animation_curve_move[3]) != 4) {
fprintf(stderr, "Error: Invalid animation_curve_move format: %s\n",
value);
int num = parse_double_array(value, config->animation_curve_move, 4);
if (num != 4) {
fprintf(stderr, "Error: Failed to parse animation_curve_move: %s\n", value);
}
} else if (strcmp(key, "animation_curve_open") == 0) {
if (sscanf(value, "%lf,%lf,%lf,%lf", &config->animation_curve_open[0],
&config->animation_curve_open[1],
&config->animation_curve_open[2],
&config->animation_curve_open[3]) != 4) {
fprintf(stderr, "Error: Invalid animation_curve_open format: %s\n",
value);
int num = parse_double_array(value, config->animation_curve_open, 4);
if (num != 4) {
fprintf(stderr, "Error: Failed to parse animation_curve_open: %s\n", value);
}
} else if (strcmp(key, "animation_curve_tag") == 0) {
if (sscanf(value, "%lf,%lf,%lf,%lf", &config->animation_curve_tag[0],
&config->animation_curve_tag[1], &config->animation_curve_tag[2],
&config->animation_curve_tag[3]) != 4) {
fprintf(stderr, "Error: Invalid animation_curve_tag format: %s\n", value);
int num = parse_double_array(value, config->animation_curve_tag, 4);
if (num != 4) {
fprintf(stderr, "Error: Failed to parse animation_curve_tag: %s\n", value);
}
} else if (strcmp(key, "animation_curve_close") == 0) {
if (sscanf(value, "%lf,%lf,%lf,%lf", &config->animation_curve_close[0],
&config->animation_curve_close[1],
&config->animation_curve_close[2],
&config->animation_curve_close[3]) != 4) {
fprintf(stderr, "Error: Invalid animation_curve_close format: %s\n",
value);
int num = parse_double_array(value, config->animation_curve_close, 4);
if (num != 4) {
fprintf(stderr, "Error: Failed to parse animation_curve_close: %s\n", value);
}
} else if (strcmp(key, "scroller_structs") == 0) {
config->scroller_structs = atoi(value);
@ -925,6 +967,9 @@ void parse_config_line(Config *config, const char *line) {
config->autostart[1], config->autostart[2]) != 3) {
fprintf(stderr, "Error: Invalid autostart format: %s\n", value);
}
trim_whitespace(config->autostart[0]);
trim_whitespace(config->autostart[1]);
trim_whitespace(config->autostart[2]);
} else if (strcmp(key, "tags") == 0) {
config->tag_rules =
realloc(config->tag_rules,
@ -949,6 +994,9 @@ void parse_config_line(Config *config, const char *line) {
char *key = token;
char *val = colon + 1;
trim_whitespace(key);
trim_whitespace(val);
if (strcmp(key, "id") == 0) {
rule->id = atoi(val);
} else if (strcmp(key, "layout_name") == 0) {
@ -1002,6 +1050,9 @@ void parse_config_line(Config *config, const char *line) {
char *key = token;
char *val = colon + 1;
trim_whitespace(key);
trim_whitespace(val);
if (strcmp(key, "isfloating") == 0) {
rule->isfloating = atoi(val);
} else if (strcmp(key, "title") == 0) {
@ -1043,6 +1094,8 @@ void parse_config_line(Config *config, const char *line) {
} else if (strcmp(key, "globalkeybinding") == 0) {
char mod_str[256], keysym_str[256];
sscanf(val, "%[^-]-%[a-zA-Z]", mod_str, keysym_str);
trim_whitespace(mod_str);
trim_whitespace(keysym_str);
rule->globalkeybinding.mod = parse_mod(mod_str);
rule->globalkeybinding.keysym = parse_keysym(keysym_str);
}
@ -1051,26 +1104,47 @@ void parse_config_line(Config *config, const char *line) {
}
config->window_rules_count++;
} else if (strcmp(key, "monitorrule") == 0) {
config->monitor_rules =
config->monitor_rules =
realloc(config->monitor_rules,
(config->monitor_rules_count + 1) * sizeof(ConfigMonitorRule));
if (!config->monitor_rules) {
if (!config->monitor_rules) {
fprintf(stderr, "Error: Failed to allocate memory for monitor rules\n");
return;
}
}
ConfigMonitorRule *rule =
&config->monitor_rules[config->monitor_rules_count];
memset(rule, 0, sizeof(ConfigMonitorRule));
ConfigMonitorRule *rule = &config->monitor_rules[config->monitor_rules_count];
memset(rule, 0, sizeof(ConfigMonitorRule));
char layout[256], name[256];
int parsed = sscanf(value, "%255[^,],%f,%d,%255[^,],%d,%f,%d,%d", name,
&rule->mfact, &rule->nmaster, layout, &rule->rr,
&rule->scale, &rule->x, &rule->y);
// 临时存储每个字段的原始字符串
char raw_name[256], raw_layout[256];
char raw_mfact[256], raw_nmaster[256], raw_rr[256];
char raw_scale[256], raw_x[256], raw_y[256];
if (parsed == 8) {
rule->name = strdup(name);
rule->layout = strdup(layout);
// 先读取所有字段为字符串
int parsed = sscanf(value, "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255s",
raw_name, raw_mfact, raw_nmaster, raw_layout,
raw_rr, raw_scale, raw_x, raw_y);
if (parsed == 8) {
// 修剪每个字段的空格
trim_whitespace(raw_name);
trim_whitespace(raw_mfact);
trim_whitespace(raw_nmaster);
trim_whitespace(raw_layout);
trim_whitespace(raw_rr);
trim_whitespace(raw_scale);
trim_whitespace(raw_x);
trim_whitespace(raw_y);
// 转换修剪后的字符串为特定类型
rule->name = strdup(raw_name);
rule->layout = strdup(raw_layout);
rule->mfact = atof(raw_mfact);
rule->nmaster = atoi(raw_nmaster);
rule->rr = atoi(raw_rr);
rule->scale = atof(raw_scale);
rule->x = atoi(raw_x);
rule->y = atoi(raw_y);
if (!rule->name || !rule->layout) {
if (rule->name)
@ -1092,6 +1166,8 @@ void parse_config_line(Config *config, const char *line) {
fprintf(stderr, "Error: Invalid bind format: %s\n", value);
return;
}
trim_whitespace(env_type);
trim_whitespace(env_value);
setenv(env_type, env_value, 1);
} else if (strncmp(key, "exec", 9) == 0) {
@ -1150,6 +1226,13 @@ void parse_config_line(Config *config, const char *line) {
fprintf(stderr, "Error: Invalid bind format: %s\n", value);
return;
}
trim_whitespace(mod_str);
trim_whitespace(keysym_str);
trim_whitespace(func_name);
trim_whitespace(arg_value);
trim_whitespace(arg_value2);
trim_whitespace(arg_value3);
trim_whitespace(arg_value4);
binding->mod = parse_mod(mod_str);
binding->keysym = parse_keysym(keysym_str);
@ -1193,6 +1276,13 @@ void parse_config_line(Config *config, const char *line) {
fprintf(stderr, "Error: Invalid mousebind format: %s\n", value);
return;
}
trim_whitespace(mod_str);
trim_whitespace(button_str);
trim_whitespace(func_name);
trim_whitespace(arg_value);
trim_whitespace(arg_value2);
trim_whitespace(arg_value3);
trim_whitespace(arg_value4);
binding->mod = parse_mod(mod_str);
binding->button = parse_button(button_str);
@ -1235,6 +1325,14 @@ void parse_config_line(Config *config, const char *line) {
return;
}
trim_whitespace(mod_str);
trim_whitespace(dir_str);
trim_whitespace(func_name);
trim_whitespace(arg_value);
trim_whitespace(arg_value2);
trim_whitespace(arg_value3);
trim_whitespace(arg_value4);
binding->mod = parse_mod(mod_str);
binding->dir = parse_direction(dir_str);
binding->arg.v = NULL;
@ -1280,6 +1378,15 @@ void parse_config_line(Config *config, const char *line) {
return;
}
trim_whitespace(mod_str);
trim_whitespace(motion_str);
trim_whitespace(fingers_count_str);
trim_whitespace(func_name);
trim_whitespace(arg_value);
trim_whitespace(arg_value2);
trim_whitespace(arg_value3);
trim_whitespace(arg_value4);
binding->mod = parse_mod(mod_str);
binding->motion = parse_direction(motion_str);
binding->fingers_count = atoi(fingers_count_str);