diff --git a/include/action.h b/include/action.h index 4a387e1b..76c6fc98 100644 --- a/include/action.h +++ b/include/action.h @@ -20,6 +20,8 @@ struct action { struct action *action_create(const char *action_name); +bool action_is_valid(struct action *action); + void action_arg_add_str(struct action *action, const char *key, const char *value); void action_arg_from_xml_node(struct action *action, char *nodename, char *content); diff --git a/src/action.c b/src/action.c index e973f70a..ad5a657b 100644 --- a/src/action.c +++ b/src/action.c @@ -249,6 +249,20 @@ action_str_from_arg(struct action_arg *arg) return ((struct action_arg_str *)arg)->value; } +static bool +arg_value_exists(struct action *action, const char *key) +{ + assert(action); + assert(key); + struct action_arg *arg; + wl_list_for_each(arg, &action->args, link) { + if (!strcasecmp(key, arg->key)) { + return true; + } + } + return false; +} + static const char * get_arg_value_str(struct action *action, const char *key, const char *default_value) { @@ -347,6 +361,46 @@ actions_contain_toggle_keybinds(struct wl_list *action_list) return false; } +/* Checks for *required* arguments */ +bool +action_is_valid(struct action *action) +{ + const char *arg_name = NULL; + switch (action->type) { + case ACTION_TYPE_EXECUTE: + arg_name = "command"; + break; + case ACTION_TYPE_MOVE_TO_EDGE: + case ACTION_TYPE_SNAP_TO_EDGE: + arg_name = "direction"; + break; + case ACTION_TYPE_SHOW_MENU: + arg_name = "menu"; + break; + case ACTION_TYPE_GO_TO_DESKTOP: + case ACTION_TYPE_SEND_TO_DESKTOP: + arg_name = "to"; + break; + case ACTION_TYPE_SNAP_TO_REGION: + arg_name = "region"; + break; + case ACTION_TYPE_FOCUS_OUTPUT: + arg_name = "output"; + break; + default: + /* No arguments required */ + return true; + } + + if (arg_value_exists(action, arg_name)) { + return true; + } + + wlr_log(WLR_ERROR, "Missing required argument for %s: %s", + action_names[action->type], arg_name); + return false; +} + void action_list_free(struct wl_list *action_list) { struct action_arg *arg, *arg_tmp;