Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Criteria #43

Merged
merged 37 commits into from
Jun 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
1fe0e3b
Add criteria
vilhalmer May 20, 2018
ab93887
First pass at criteria string parser
vilhalmer Jun 9, 2018
7182f0e
Add missing mako_style_spec.ignore_timeout
vilhalmer Jun 10, 2018
5a59247
create_criteria takes a config instead of state
vilhalmer Jun 10, 2018
2f8c982
apply_criteria_field consumes the token
vilhalmer Jun 10, 2018
723593d
criteria are stored in a list on mako_config
vilhalmer Jun 10, 2018
1df70a5
Split apply_style_option from apply_config_option
vilhalmer Jun 10, 2018
a3a93b4
Clean up criteria when destroying config
vilhalmer Jun 10, 2018
6834e42
Apply style from matched criteria to notifications
vilhalmer Jun 10, 2018
028c6f6
hidden_format -> hidden_style
vilhalmer Jun 10, 2018
585479a
Use notification's style in render
vilhalmer Jun 10, 2018
53e7bb1
Use global criteria when sending capabilities
vilhalmer Jun 10, 2018
abfa95c
Use global criteria to set surface size
vilhalmer Jun 10, 2018
5f2e541
Only try to look at the section if it exists
vilhalmer Jun 10, 2018
5a0fa33
Only try config options if it wasn't a valid style
vilhalmer Jun 10, 2018
5ea01cd
Actually init the default style
vilhalmer Jun 10, 2018
b04b73e
Apply the final criteria field after loop exits
vilhalmer Jun 10, 2018
97a7d71
Properly calculate inner margin again
vilhalmer Jun 10, 2018
e6e0765
Print error for invalid criteria
vilhalmer Jun 10, 2018
29fc3c6
Don't make a criteria for hidden
vilhalmer Jun 10, 2018
bbe53be
Fix reporting of criteria parsing success
vilhalmer Jun 10, 2018
22878fc
Finish up error message TODOs in criteria
vilhalmer Jun 10, 2018
db75066
hidden TODO is already done
vilhalmer Jun 10, 2018
f71b620
Saving this for a future PR
vilhalmer Jun 10, 2018
d676406
This happens automatically, though could be nicer
vilhalmer Jun 10, 2018
8a13aad
Missed converting padding
vilhalmer Jun 10, 2018
8486d19
Fix up hidden_style correctly
vilhalmer Jun 10, 2018
36ef70c
Plug a few leaks
vilhalmer Jun 10, 2018
6119476
Fix double-free in hidden_style when reloading
vilhalmer Jun 11, 2018
fa7f9f8
Don't try to parse empty criteria field
vilhalmer Jun 11, 2018
ae22b95
Squish up all those elses
vilhalmer Jun 12, 2018
0840c93
Combine unnecessary case
vilhalmer Jun 12, 2018
fa26e3b
token_location is a size_t
vilhalmer Jun 12, 2018
172cb7d
apply_each_criteria returns ssize_t
vilhalmer Jun 12, 2018
93264c8
Flip order of arguments to apply_style
vilhalmer Jun 12, 2018
9c7fe47
Update man page
vilhalmer Jun 12, 2018
9d89ba2
Add hidden back to man page
vilhalmer Jun 13, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
273 changes: 206 additions & 67 deletions config.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,17 @@
#include <unistd.h>

#include "config.h"
#include "criteria.h"

void init_default_config(struct mako_config *config) {
init_default_style(&config->style);
wl_list_init(&config->criteria);
struct mako_criteria *global_criteria = create_criteria(config);
init_default_style(&global_criteria->style);

init_empty_style(&config->hidden_style);
config->hidden_style.format = strdup("(%h more)");
config->hidden_style.spec.format = true;

config->hidden_format = strdup("(%h more)");
config->output = strdup("");
config->max_visible = 5;

Expand All @@ -26,8 +32,12 @@ void init_default_config(struct mako_config *config) {
}

void finish_config(struct mako_config *config) {
finish_style(&config->style);
free(config->hidden_format);
struct mako_criteria *criteria, *tmp;
wl_list_for_each_safe(criteria, tmp, &config->criteria, link) {
destroy_criteria(criteria);
}

finish_style(&config->hidden_style);
free(config->output);
}

Expand Down Expand Up @@ -59,11 +69,116 @@ void init_default_style(struct mako_style *style) {
memset(&style->spec, true, sizeof(struct mako_style_spec));
}

void init_empty_style(struct mako_style *style) {
memset(style, 0, sizeof(struct mako_style));
}

void finish_style(struct mako_style *style) {
free(style->font);
free(style->format);
}

// Update `target` with the values specified in `style`. If a failure occurs,
// `target` will remain unchanged.
bool apply_style(struct mako_style *target, const struct mako_style *style) {
// Try to duplicate strings up front in case allocation fails and we have
// to bail without changing `target`.
char *new_font = NULL;
char *new_format = NULL;

if (style->spec.font) {
new_font = strdup(style->font);
if (new_font == NULL) {
fprintf(stderr, "allocation failed\n");
return false;
}
}

if (style->spec.format) {
new_format = strdup(style->format);
if (new_format == NULL) {
fprintf(stderr, "allocation failed\n");
return false;
}
}

// Now on to actually setting things!

if (style->spec.width) {
target->width = style->width;
target->spec.width = true;
}

if (style->spec.height) {
target->height = style->height;
target->spec.height = true;
}

if (style->spec.margin) {
target->margin = style->margin;
target->spec.margin = true;
}

if (style->spec.padding) {
target->padding = style->padding;
target->spec.padding = true;
}

if (style->spec.border_size) {
target->border_size = style->border_size;
target->spec.border_size = true;
}

if (style->spec.font) {
free(target->font);
target->font = new_font;
target->spec.font = true;
}

if (style->spec.markup) {
target->markup = style->markup;
target->spec.markup = true;
}

if (style->spec.format) {
free(target->format);
target->format = new_format;
target->spec.format = true;
}

if (style->spec.actions) {
target->actions = style->actions;
target->spec.actions = true;
}

if (style->spec.default_timeout) {
target->default_timeout = style->default_timeout;
target->spec.default_timeout = true;
}

if (style->spec.ignore_timeout) {
target->ignore_timeout = style->ignore_timeout;
target->spec.ignore_timeout = true;
}

if (style->spec.colors.background) {
target->colors.background = style->colors.background;
target->spec.colors.background = true;
}

if (style->spec.colors.text) {
target->colors.text = style->colors.text;
target->spec.colors.text = true;
}

if (style->spec.colors.border) {
target->colors.border = style->colors.border;
target->spec.colors.border = true;
}

return true;
}

static bool parse_int(const char *s, int *out) {
errno = 0;
char *end;
Expand Down Expand Up @@ -150,89 +265,74 @@ static bool parse_color(const char *color, uint32_t *out) {
return true;
}

static bool apply_config_option(struct mako_config *config, const char *section,
const char *name, const char *value) {
// First try to parse this as a global option.
if (section == NULL) {
if (strcmp(name, "max-visible") == 0) {
return parse_int(value, &config->max_visible);
} else if (strcmp(name, "output") == 0) {
free(config->output);
config->output = strdup(value);
return true;
} else if (strcmp(name, "sort") == 0) {
if (strcmp(value, "+priority") == 0) {
config->sort_criteria |= MAKO_SORT_CRITERIA_URGENCY;
config->sort_asc |= MAKO_SORT_CRITERIA_URGENCY;
} else if (strcmp(value, "-priority") == 0) {
config->sort_criteria |= MAKO_SORT_CRITERIA_URGENCY;
config->sort_asc &= ~MAKO_SORT_CRITERIA_URGENCY;
} else if (strcmp(value, "+time") == 0) {
config->sort_criteria |= MAKO_SORT_CRITERIA_TIME;
config->sort_asc |= MAKO_SORT_CRITERIA_TIME;
} else if (strcmp(value, "-time") == 0) {
config->sort_criteria |= MAKO_SORT_CRITERIA_TIME;
config->sort_asc &= ~MAKO_SORT_CRITERIA_TIME;
}
return true;
} else {
// We want to try the style options now, so keep going.
}
} else {
// TODO: criteria support
if (strcmp(section, "hidden") != 0) {
fprintf(stderr, "Only the 'hidden' section is currently supported\n");
return false;
}

if (strcmp(name, "format") == 0) {
free(config->hidden_format);
config->hidden_format = strdup(value);
return true;
} else {
fprintf(stderr, "Only 'format' is supported in the 'hidden' section\n");
return false;
static bool apply_config_option(struct mako_config *config, const char *name,
const char *value) {
if (strcmp(name, "max-visible") == 0) {
return parse_int(value, &config->max_visible);
} else if (strcmp(name, "output") == 0) {
free(config->output);
config->output = strdup(value);
return true;
} else if (strcmp(name, "sort") == 0) {
if (strcmp(value, "+priority") == 0) {
config->sort_criteria |= MAKO_SORT_CRITERIA_URGENCY;
config->sort_asc |= MAKO_SORT_CRITERIA_URGENCY;
} else if (strcmp(value, "-priority") == 0) {
config->sort_criteria |= MAKO_SORT_CRITERIA_URGENCY;
config->sort_asc &= ~MAKO_SORT_CRITERIA_URGENCY;
} else if (strcmp(value, "+time") == 0) {
config->sort_criteria |= MAKO_SORT_CRITERIA_TIME;
config->sort_asc |= MAKO_SORT_CRITERIA_TIME;
} else if (strcmp(value, "-time") == 0) {
config->sort_criteria |= MAKO_SORT_CRITERIA_TIME;
config->sort_asc &= ~MAKO_SORT_CRITERIA_TIME;
}
return true;
}

// Now try to match on style options.
struct mako_style *style = &config->style;
return false;
}

static bool apply_style_option(struct mako_style *style, const char *name,
const char *value) {
struct mako_style_spec *spec = &style->spec;

if (strcmp(name, "font") == 0) {
free(style->font);
style->font = strdup(value);
return true;
return spec->font = !!(style->font = strdup(value));
} else if (strcmp(name, "background-color") == 0) {
return parse_color(value, &style->colors.background);
return spec->colors.background =
parse_color(value, &style->colors.background);
} else if (strcmp(name, "text-color") == 0) {
return parse_color(value, &style->colors.text);
return spec->colors.text = parse_color(value, &style->colors.text);
} else if (strcmp(name, "width") == 0) {
return parse_int(value, &style->width);
return spec->width = parse_int(value, &style->width);
} else if (strcmp(name, "height") == 0) {
return parse_int(value, &style->height);
return spec->height = parse_int(value, &style->height);
} else if (strcmp(name, "margin") == 0) {
return parse_directional(value, &style->margin);
return spec->margin = parse_directional(value, &style->margin);
} else if (strcmp(name, "padding") == 0) {
return parse_int(value, &style->padding);
return spec->padding = parse_int(value, &style->padding);
} else if (strcmp(name, "border-size") == 0) {
return parse_int(value, &style->border_size);
return spec->border_size = parse_int(value, &style->border_size);
} else if (strcmp(name, "border-color") == 0) {
return parse_color(value, &style->colors.border);
return spec->colors.border = parse_color(value, &style->colors.border);
} else if (strcmp(name, "markup") == 0) {
style->markup = strcmp(value, "1") == 0;
return style->markup || strcmp(value, "0") == 0;
return spec->markup = style->markup || strcmp(value, "0") == 0;
} else if (strcmp(name, "format") == 0) {
free(style->format);
style->format = strdup(value);
return true;
return spec->format = !!(style->format = strdup(value));
} else if (strcmp(name, "default-timeout") == 0) {
return parse_int(value, &style->default_timeout);
return spec->default_timeout =
parse_int(value, &style->default_timeout);
} else if (strcmp(name, "ignore-timeout") == 0) {
style->ignore_timeout = strcmp(value, "1") == 0;
return style->ignore_timeout || strcmp(value, "0") == 0;
} else {
return false;
return spec->ignore_timeout = (
style->ignore_timeout || strcmp(value, "0") == 0);
}

return false;
}

static bool file_exists(const char *path) {
Expand Down Expand Up @@ -289,34 +389,72 @@ int load_config_file(struct mako_config *config) {
int lineno = 0;
char *line = NULL;
char *section = NULL;

struct mako_criteria *criteria = global_criteria(config);

size_t n = 0;
while (getline(&line, &n, f) > 0) {
++lineno;
if (line[0] == '\0' || line[0] == '\n' || line[0] == '#') {
continue;
}

if (line[strlen(line) - 1] == '\n') {
line[strlen(line) - 1] = '\0';
}

if (line[0] == '[' && line[strlen(line) - 1] == ']') {
free(section);
section = strndup(line + 1, strlen(line) - 2);
if (strcmp(section, "hidden") == 0) {
// Skip making a criteria for the hidden section.
criteria = NULL;
continue;
}
criteria = create_criteria(config);
if (!parse_criteria(section, criteria)) {
fprintf(stderr, "[%s:%d] Invalid criteria definition\n", base,
lineno);
ret = -1;
break;
}
continue;
}

char *eq = strchr(line, '=');
if (!eq) {
fprintf(stderr, "[%s:%d] Expected key=value\n", base, lineno);
ret = -1;
break;
}

bool valid_option = false;
eq[0] = '\0';
if (!apply_config_option(config, section, line, eq + 1)) {

struct mako_style *target_style;
if (section != NULL && strcmp(section, "hidden") == 0) {
// The hidden criteria is a lie, we store the associated style
// directly on the config because there's no "real" notification
// object to match against it later.
target_style = &config->hidden_style;
} else {
target_style = &criteria->style;
}

valid_option = apply_style_option(target_style, line, eq + 1);

if (!valid_option && section == NULL) {
valid_option = apply_config_option(config, line, eq + 1);
}

if (!valid_option) {
fprintf(stderr, "[%s:%d] Failed to parse option '%s'\n",
base, lineno, line);
ret = -1;
break;
}
}

free(section);
free(line);
fclose(f);
Expand Down Expand Up @@ -362,7 +500,8 @@ int parse_config_arguments(struct mako_config *config, int argc, char **argv) {
}

const char *name = long_options[option_index].name;
if (!apply_config_option(config, NULL, name, optarg)) {
if (!apply_style_option(&global_criteria(config)->style, name, optarg)
|| apply_config_option(config, name, optarg)) {
fprintf(stderr, "Failed to parse option '%s'\n", name);
return -1;
}
Expand Down
Loading