From 7ff8ef94c05ae6386463b63f3ba25add52340d8b Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Sat, 12 Mar 2022 17:29:26 -0800 Subject: til_settings: always describe relevant settings The existing iterative *_setup() interface only described settings not found, quietly accepting usable settings already present in the til_settings_t. This worked fine for the existing interactive text setup thing, but it's especially problematic for providing a GUI setup frontend. This commit makes it so the *_setup() methods always describe undescribed settings they recognize, leaving the setup frontend loop calling into the *_setup() methods to both apply the description validation if wanted and actually tie the description to respective setting returned by the _setup() methods as being related to the returned description. A new helper called til_settings_get_and_describe_value() has been introduced primarily for use of module setup methods to simplify this nonsense, replacing the til_settings_get_value() calls and surrounding logic, but retaining the til_setting_desc_t definitions largely verbatim. This also results in discarding of some ad-hoc til_setting_desc_check() calls, now that there's a centralized place where settings become "described" (setup_interactively in the case of rototiller). Now a GUI frontend (like glimmer) would just provide its own setup_interactively() equivalent for constructing its widgets for a given *_setup() method's chain of returned descs. Whereas in the past this wasn't really feasible unless there was never going to be pre-supplied settings. I suspect the til_setting_desc_check() integration into setup_interactively() needs more work, but I think this is good enough for now and I'm out of spare time for the moment. --- src/setup.c | 65 +++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 25 deletions(-) (limited to 'src/setup.c') diff --git a/src/setup.c b/src/setup.c index 9f67374..e027d1d 100644 --- a/src/setup.c +++ b/src/setup.c @@ -16,62 +16,78 @@ static int add_value(til_settings_t *settings, const char *key, const char *valu assert(key); - return til_settings_add_value(settings, key, value); + return til_settings_add_value(settings, key, value, NULL); } /* returns negative on error, otherwise number of additions made to settings */ -int setup_interactively(til_settings_t *settings, int (*setup_func)(til_settings_t *settings, til_setting_desc_t **next), int defaults) +int setup_interactively(til_settings_t *settings, int (*setup_func)(til_settings_t *settings, const til_setting_t **res_setting, const til_setting_desc_t **res_desc), int defaults) { - unsigned additions = 0; - char buf[256] = "\n"; - til_setting_desc_t *next; - int r; + unsigned additions = 0; + char buf[256] = "\n"; + const til_setting_t *setting; + const til_setting_desc_t *desc; + int r; assert(settings); assert(setup_func); /* TODO: regex and error handling */ - while ((r = setup_func(settings, &next)) > 0) { + while ((r = setup_func(settings, &setting, &desc)) > 0) { additions++; + /* if setup_func() has returned a description for an undescribed preexisting setting, + * validate its value against the description and assign the description if it passes. + */ + if (setting && !setting->desc) { + /* XXX FIXME: this key as value exception is janky, make a helper to access the value or stop doing that. */ + r = til_setting_desc_check(desc, setting->value ? : setting->key); + if (r < 0) + return r; + + /* XXX FIXME everything's constified necessitating this fuckery, revisit and cleanup later, prolly another til_settings helper */ + ((til_setting_t *)setting)->desc = desc; + + continue; + } + if (!defaults) puts(""); - if (next->values) { + if (desc->values) { unsigned i, preferred = 0; int width = 0; - for (i = 0; next->values[i]; i++) { + for (i = 0; desc->values[i]; i++) { int len; - len = strlen(next->values[i]); + len = strlen(desc->values[i]); if (len > width) width = len; } /* multiple choice */ if (!defaults) - printf("%s:\n", next->name); + printf("%s:\n", desc->name); - for (i = 0; next->values[i]; i++) { + for (i = 0; desc->values[i]; i++) { if (!defaults) - printf("%2u: %*s%s%s\n", i, width, next->values[i], - next->annotations ? ": " : "", - next->annotations ? next->annotations[i] : ""); + printf("%2u: %*s%s%s\n", i, width, desc->values[i], + desc->annotations ? ": " : "", + desc->annotations ? desc->annotations[i] : ""); - if (!strcmp(next->preferred, next->values[i])) + if (!strcmp(desc->preferred, desc->values[i])) preferred = i; } if (!defaults) printf("Enter a value 0-%u [%u (%s)]: ", - i - 1, preferred, next->preferred); + i - 1, preferred, desc->preferred); } else { /* arbitrarily typed input */ if (!defaults) - printf("%s [%s]: ", next->name, next->preferred); + printf("%s [%s]: ", desc->name, desc->preferred); } if (!defaults) { @@ -81,11 +97,11 @@ int setup_interactively(til_settings_t *settings, int (*setup_func)(til_settings if (*buf == '\n') { /* accept preferred */ - add_value(settings, next->key, next->preferred); + add_value(settings, desc->key, desc->preferred); } else { buf[strlen(buf) - 1] = '\0'; - if (next->values) { + if (desc->values) { unsigned i, j, found; /* multiple choice, map numeric input to values entry */ @@ -95,9 +111,9 @@ int setup_interactively(til_settings_t *settings, int (*setup_func)(til_settings goto _next; } - for (found = i = 0; next->values[i]; i++) { + for (found = i = 0; desc->values[i]; i++) { if (i == j) { - add_value(settings, next->key, next->values[i]); + add_value(settings, desc->key, desc->values[i]); found = 1; break; } @@ -112,12 +128,11 @@ int setup_interactively(til_settings_t *settings, int (*setup_func)(til_settings } else { /* use typed input as setting, TODO: apply regex */ - add_value(settings, next->key, buf); + add_value(settings, desc->key, buf); } } - _next: - til_setting_desc_free(next); + til_setting_desc_free(desc); } return r < 0 ? r : additions; -- cgit v1.2.1