diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2023-06-02 18:06:33 -0700 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2023-06-03 07:42:02 -0700 |
commit | 401cfce3ebb205e46b4582fc6be1a0d42e213d31 (patch) | |
tree | 7e1c42852e2ccd8fc95802476f6eb9f4f9d11545 | |
parent | 8dc099b955197c7100937d5fafc60c4b9681a5ab (diff) |
til_settings,setup: introduce til_setting_spec_t.override()
In situations where modules wish to alias setting values like
expanding "all" -> "mod0,mod1,mod2,mod3" they need a way to
intercept the value-acceptance @ desc-assignment time in the
front-end. This optional override() function does just that when
present in the spec.
The current setting's value is passed to the override, and
if what's returned differs from what was passed (by pointer
value), then the current value is freed and the override takes
its place. The override function is expected to _always_ return
non-NULL; either the value provided, or a newly allocated value
override. The override function must never free the supplied
value, that's the front-end's job in applying the override.
The override() must return NULL on errors, which are assumed to
be limited to ENOMEM failures.
-rw-r--r-- | src/setup.c | 16 | ||||
-rw-r--r-- | src/til.c | 17 | ||||
-rw-r--r-- | src/til_settings.c | 1 | ||||
-rw-r--r-- | src/til_settings.h | 1 |
4 files changed, 35 insertions, 0 deletions
diff --git a/src/setup.c b/src/setup.c index d3c3e6d..dfeb4df 100644 --- a/src/setup.c +++ b/src/setup.c @@ -30,6 +30,22 @@ int setup_interactively(til_settings_t *settings, int (*setup_func)(const til_se * validate its value against the description and assign the description if it passes. */ if (setting && !setting->desc) { + /* Apply override before, or after the spec_check()? unclear. + * TODO This probably also needs to move into a til_settings helper + */ + if (desc->spec.override) { + const char *o; + + o = desc->spec.override(setting->value); + if (!o) + return -ENOMEM; + + if (o != setting->value) { + free((void *)setting->value); + setting->value = o; + } + } + r = til_setting_spec_check(&desc->spec, setting->value); if (r < 0) { *res_failed_desc = desc; @@ -401,6 +401,23 @@ int til_module_setup_randomize(const til_module_t *module, unsigned seed, til_se assert(setting); + /* + * TODO This probably also needs to move into a til_settings helper, + * copy-n-pasta alert, taken from setup.c + */ + if (desc->spec.override) { + const char *o; + + o = desc->spec.override(setting->value); + if (!o) + return -ENOMEM; + + if (o != setting->value) { + free((void *)setting->value); + setting->value = o; + } + } + if (desc->spec.as_nested_settings && !setting->value_as_nested_settings) { char *label = NULL; diff --git a/src/til_settings.c b/src/til_settings.c index 08098d5..2811b72 100644 --- a/src/til_settings.c +++ b/src/til_settings.c @@ -407,6 +407,7 @@ int til_setting_desc_new(const til_settings_t *settings, const til_setting_spec_ } d->spec.random = spec->random; + d->spec.override = spec->override; d->spec.as_nested_settings = spec->as_nested_settings; d->spec.as_label = spec->as_label; diff --git a/src/til_settings.h b/src/til_settings.h index 858ff66..e0b1875 100644 --- a/src/til_settings.h +++ b/src/til_settings.h @@ -16,6 +16,7 @@ typedef struct til_setting_spec_t { const char **values; /* if a set of values is provided, listed here */ const char **annotations; /* if a set of values is provided, annotations for those values may be listed here */ char * (*random)(unsigned seed);/* if set, returns a valid random value for this setting */ + const char * (*override)(const char *value); /* if set, returns an override for value, or value if not overridden - so NULL returns indicate error (ENOMEM), assuming value is always non-NULL */ unsigned as_nested_settings:1; /* if set, this setting expects a settings string for its value and wants a til_setting_t.value_as_nested_settings instance created for it */ unsigned as_label:1; /* if set, this setting's value is to be used as a label component in path construction - only applies to the first setting entry in an instance (til_settings_t.entries[0]) */ } til_setting_spec_t; |