From d6e7710a7ebd0be1f2dba677394f5b30b3e52a4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 11 Jul 2023 10:26:28 +0200 Subject: [PATCH] particle: on-click: tilde expansion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We now do tilde expansion of the *first* argument in on-click handlers. That is: ~/bin/foobar.sh ~/arg1 is expanded to $HOME/bin/foobar.sh ~/arg1 (meaning, the handler will most likely *not* do what you’d expect) Related to #307 --- CHANGELOG.md | 2 ++ config-verify.c | 44 ++++++++++++++++++++++++++++++-------- config.c | 37 +++++++++++++++++++++++++++----- doc/yambar-particles.5.scd | 9 ++++---- particle.c | 4 ++-- particle.h | 2 +- 6 files changed, 77 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30c9d47..8ff897d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,10 +19,12 @@ * i3/sway: extend option `sort`; use `native` to sort numbered workspaces only. * modules/dwl: handle the appid status ([#284][284]) * battery: also show estimation for time to full ([#303][303]). +* on-click: tilde expansion ([#307][307]) [246]: https://codeberg.org/dnkl/yambar/issues/246 [256]: https://codeberg.org/dnkl/yambar/pulls/256 [284]: https://codeberg.org/dnkl/yambar/pulls/284 +[307]: https://codeberg.org/dnkl/yambar/issues/307 ### Changed diff --git a/config-verify.c b/config-verify.c index a099ef7..9b4fad7 100644 --- a/config-verify.c +++ b/config-verify.c @@ -174,22 +174,47 @@ conf_verify_dict(keychain_t *chain, const struct yml_node *node, return true; } +static bool +verify_on_click_path(keychain_t *chain, const struct yml_node *node) +{ + if (!conf_verify_string(chain, node)) + return false; + +#if 1 + /* We allow non-absolute paths in on-click handlers */ + return true; +#else + const char *path = yml_value_as_string(node); + + const bool is_absolute = path[0] == '/'; + const bool is_tilde = path[0] == '~' && path[1] == '/'; + + if (!is_absolute && !is_tilde) { + LOG_ERR("%s: path must be either absolute, or begin with '~/", + conf_err_prefix(chain, node)); + return false; + } + + return true; +#endif +} + bool conf_verify_on_click(keychain_t *chain, const struct yml_node *node) { /* on-click: */ const char *s = yml_value_as_string(node); if (s != NULL) - return true; + return verify_on_click_path(chain, node); static const struct attr_info info[] = { - {"left", false, &conf_verify_string}, - {"middle", false, &conf_verify_string}, - {"right", false, &conf_verify_string}, - {"wheel-up", false, &conf_verify_string}, - {"wheel-down", false, &conf_verify_string}, - {"previous", false, &conf_verify_string}, - {"next", false, &conf_verify_string}, + {"left", false, &verify_on_click_path}, + {"middle", false, &verify_on_click_path}, + {"right", false, &verify_on_click_path}, + {"wheel-up", false, &verify_on_click_path}, + {"wheel-down", false, &verify_on_click_path}, + {"previous", false, &verify_on_click_path}, + {"next", false, &verify_on_click_path}, {NULL, false, NULL}, }; @@ -306,7 +331,8 @@ conf_verify_particle_dictionary(keychain_t *chain, const struct yml_node *node) const char *particle_name = yml_value_as_string(particle); if (particle_name == NULL) { - LOG_ERR("%s: particle name must be a string", conf_err_prefix(chain, particle)); + LOG_ERR("%s: particle name must be a string", + conf_err_prefix(chain, particle)); return false; } diff --git a/config.c b/config.c index 3d32678..debf837 100644 --- a/config.c +++ b/config.c @@ -211,20 +211,47 @@ conf_to_particle(const struct yml_node *node, struct conf_inherit inherited) int right = margin != NULL ? yml_value_as_int(margin) : right_margin != NULL ? yml_value_as_int(right_margin) : 0; - const char *on_click_templates[MOUSE_BTN_COUNT] = {NULL}; + char *on_click_templates[MOUSE_BTN_COUNT] = {NULL}; if (on_click != NULL) { - const char *legacy = yml_value_as_string(on_click); + const char *yml_legacy = yml_value_as_string(on_click); + + if (yml_legacy != NULL) { + char *legacy = NULL; + + if (yml_legacy[0] == '~' && yml_legacy[1] == '/') { + const char *home_dir = getenv("HOME"); + + if (home_dir != NULL) + asprintf(&legacy, "%s/%s", home_dir, yml_legacy + 2); + + if (legacy == NULL) + legacy = strdup(yml_legacy); + } else + legacy = strdup(yml_legacy); - if (legacy != NULL) on_click_templates[MOUSE_BTN_LEFT] = legacy; + } - if (yml_is_dict(on_click)) { + else if (yml_is_dict(on_click)) { for (struct yml_dict_iter it = yml_dict_iter(on_click); it.key != NULL; yml_dict_next(&it)) { const char *key = yml_value_as_string(it.key); - const char *template = yml_value_as_string(it.value); + const char *yml_template = yml_value_as_string(it.value); + + char *template = NULL; + + if (yml_template[0] == '~' && yml_template[1] == '/') { + const char *home_dir = getenv("HOME"); + + if (home_dir != NULL) + asprintf(&template, "%s/%s", home_dir, yml_template + 2); + + if (template == NULL) + template = strdup(yml_template); + } else + template = strdup(yml_template); if (strcmp(key, "left") == 0) on_click_templates[MOUSE_BTN_LEFT] = template; diff --git a/doc/yambar-particles.5.scd b/doc/yambar-particles.5.scd index adf4485..5dc858b 100644 --- a/doc/yambar-particles.5.scd +++ b/doc/yambar-particles.5.scd @@ -44,10 +44,11 @@ following attributes are supported by all particles: | on-click : associative array/string : no -: When set to a string, executes the string as a command when the particle - is left-clicked. Tags can be used. Note that the string is *not* - executed in a shell. The same applies to all attributes associated with - it, below. +: When set to a string, executes the string as a command when the + particle is left-clicked. Tags can be used. Note that the string is + *not* executed in a shell. Environment variables are not expanded. + *~/* is expanded, but only in the first argument. The same applies + to all attributes associated with it, below. | on-click.left : string : no diff --git a/particle.c b/particle.c index fe1d138..2035d9a 100644 --- a/particle.c +++ b/particle.c @@ -30,7 +30,7 @@ particle_default_destroy(struct particle *particle) struct particle * particle_common_new(int left_margin, int right_margin, - const char **on_click_templates, + char **on_click_templates, struct fcft_font *font, enum font_shaping font_shaping, pixman_color_t foreground, struct deco *deco) { @@ -46,7 +46,7 @@ particle_common_new(int left_margin, int right_margin, for (size_t i = 0; i < MOUSE_BTN_COUNT; i++) { if (on_click_templates[i] != NULL) { p->have_on_click_template = true; - p->on_click_templates[i] = strdup(on_click_templates[i]); + p->on_click_templates[i] = on_click_templates[i]; } } } diff --git a/particle.h b/particle.h index c92c5fc..a2b55a8 100644 --- a/particle.h +++ b/particle.h @@ -64,7 +64,7 @@ struct exposable { }; struct particle *particle_common_new( - int left_margin, int right_margin, const char *on_click_templates[], + int left_margin, int right_margin, char *on_click_templates[], struct fcft_font *font, enum font_shaping font_shaping, pixman_color_t foreground, struct deco *deco);