From 5b209f35330e744b43d17e651f2da98c6d3a5c62 Mon Sep 17 00:00:00 2001 From: Bjoern Hiller Date: Thu, 12 Oct 2023 17:50:11 +0200 Subject: [PATCH 1/7] Add new Dbus method RuleList The intention is to have a way to get all configured rules. --- src/dbus.c | 147 ++++++++++++++++++++++++++++++++++++++++++++ src/settings_data.h | 1 + test/dbus.c | 74 +++++++++++++++++++++- 3 files changed, 219 insertions(+), 3 deletions(-) diff --git a/src/dbus.c b/src/dbus.c index 95d339984..e989d5caa 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -6,12 +6,14 @@ #include #include +#include "draw.h" #include "dunst.h" #include "log.h" #include "menu.h" #include "notification.h" #include "queues.h" #include "settings.h" +#include "settings_data.h" #include "utils.h" #include "rules.h" #include "option_parser.h" @@ -95,6 +97,9 @@ static const char *introspection_xml = " " " " " " + " " + " " + " " " " " " @@ -187,6 +192,7 @@ DBUS_METHOD(dunst_NotificationPopHistory); DBUS_METHOD(dunst_NotificationRemoveFromHistory); DBUS_METHOD(dunst_NotificationShow); DBUS_METHOD(dunst_RuleEnable); +DBUS_METHOD(dunst_RuleList); DBUS_METHOD(dunst_Ping); static struct dbus_method methods_dunst[] = { {"ContextMenuCall", dbus_cb_dunst_ContextMenuCall}, @@ -200,6 +206,7 @@ static struct dbus_method methods_dunst[] = { {"NotificationShow", dbus_cb_dunst_NotificationShow}, {"Ping", dbus_cb_dunst_Ping}, {"RuleEnable", dbus_cb_dunst_RuleEnable}, + {"RuleList", dbus_cb_dunst_RuleList}, }; void dbus_cb_dunst_methods(GDBusConnection *connection, @@ -411,6 +418,146 @@ static void dbus_cb_dunst_NotificationRemoveFromHistory(GDBusConnection *connect g_dbus_connection_flush(connection, NULL, NULL, NULL); } +static const char *enum_to_string(const struct string_to_enum_def values[], int enum_value) +{ + for (size_t i = 0; values[i].string != NULL; i++) { + if (values[i].enum_value == enum_value) { + return values[i].string; + } + } + return NULL; +} + +static void color_entry(const struct color c, GVariantDict *dict, const char *field_name) { + char buf[10]; + if (color_to_string(c, buf)) { + g_variant_dict_insert(dict, field_name, "s", buf); + } +} + +static void dbus_cb_dunst_RuleList(GDBusConnection *connection, + const gchar *sender, + GVariant *parameters, + GDBusMethodInvocation *invocation) +{ + LOG_D("CMD: Listing all configured rules"); + + GVariantBuilder builder; + g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); + + for (GSList *iter = rules; iter; iter = iter->next) { + struct rule *r = iter->data; + + if (is_special_section(r->name)) { + continue; + } + + GVariantDict dict; + g_variant_dict_init(&dict, NULL); + g_variant_dict_insert(&dict, "name", "s", r->name); + + // filters - order according to rule_matches_notification + g_variant_dict_insert(&dict, "enabled", "b", r->enabled); + // undocumented filter? + if (r->match_dbus_timeout > -1) + g_variant_dict_insert(&dict, "match_dbus_timeout", "i", r->match_dbus_timeout); + if (r->msg_urgency != URG_NONE) + g_variant_dict_insert(&dict, + "msg_urgency", + "s", + enum_to_string(urgency_enum_data, r->msg_urgency)); + if (r->match_transient > -1) + g_variant_dict_insert(&dict, "match_transient", "b", r->match_transient); + if (r->appname) + g_variant_dict_insert(&dict, "appname", "s", r->appname); + if (r->desktop_entry) + g_variant_dict_insert(&dict, "desktop_entry", "s", r->desktop_entry); + if (r->summary) + g_variant_dict_insert(&dict, "summary", "s", r->summary); + if (r->body) + g_variant_dict_insert(&dict, "body", "s", r->body); + if (r->category) + g_variant_dict_insert(&dict, "category", "s", r->category); + if (r->stack_tag) + g_variant_dict_insert(&dict, "stack_tag", "s", r->stack_tag); + + // settings to apply - order according to rule_apply + if (r->timeout != -1) + g_variant_dict_insert(&dict, "timeout", "x", r->timeout); + if (r->override_dbus_timeout != -1) + g_variant_dict_insert(&dict, "override_dbus_timeout", "x", r->override_dbus_timeout); + if (r->urgency != URG_NONE) + g_variant_dict_insert(&dict, "urgency", "s", enum_to_string(urgency_enum_data, r->urgency)); + if (r->fullscreen != FS_NULL) + g_variant_dict_insert(&dict, + "fullscreen", + "s", + enum_to_string(fullscreen_enum_data, r->fullscreen)); + if (r->history_ignore != -1) + g_variant_dict_insert(&dict, "history_ignore", "b", r->history_ignore); + if (r->set_transient != -1) + g_variant_dict_insert(&dict, "set_transient", "b", r->set_transient); + if (r->skip_display != -1) + g_variant_dict_insert(&dict, "skip_display", "b", r->skip_display); + if (r->word_wrap != -1) + g_variant_dict_insert(&dict, "word_wrap", "b", r->word_wrap); + if (r->ellipsize != -1) + g_variant_dict_insert(&dict, + "ellipsize", + "s", + enum_to_string(ellipsize_enum_data, r->ellipsize)); + if (r->alignment != -1) + g_variant_dict_insert(&dict, + "alignment", + "s", + enum_to_string(horizontal_alignment_enum_data, r->alignment)); + if (r->hide_text != -1) + g_variant_dict_insert(&dict, "hide_text", "b", r->hide_text); + if (r->progress_bar_alignment != -1) + g_variant_dict_insert(&dict, + "progress_bar_alignment", + "s", + enum_to_string(horizontal_alignment_enum_data, + r->progress_bar_alignment)); + if (r->min_icon_size != -1) + g_variant_dict_insert(&dict, "min_icon_size", "i", r->min_icon_size); + if (r->max_icon_size != -1) + g_variant_dict_insert(&dict, "max_icon_size", "i", r->max_icon_size); + if (r->action_name) + g_variant_dict_insert(&dict, "action_name", "s", r->action_name); + if (r->set_category) + g_variant_dict_insert(&dict, "set_category", "s", r->set_category); + if (r->markup != MARKUP_NULL) + g_variant_dict_insert(&dict, "markup", "s", enum_to_string(markup_mode_enum_data, r->markup)); + if (r->icon_position != -1) + g_variant_dict_insert(&dict, + "icon_position", + "s", + enum_to_string(icon_position_enum_data, r->icon_position)); + color_entry(r->fg, &dict, "fg"); + color_entry(r->bg, &dict, "bg"); + color_entry(r->highlight, &dict, "highlight"); + color_entry(r->fc, &dict, "fc"); + if (r->format) + g_variant_dict_insert(&dict, "format", "s", r->format); + if (r->default_icon) + g_variant_dict_insert(&dict, "default_icon", "s", r->default_icon); + if (r->new_icon) + g_variant_dict_insert(&dict, "new_icon", "s", r->new_icon); + if (r->script) + g_variant_dict_insert(&dict, "script", "s", r->script); + if (r->set_stack_tag) + g_variant_dict_insert(&dict, "set_stack_tag", "s", r->set_stack_tag); + if (r->override_pause_level != -1) + g_variant_dict_insert(&dict, "override_pause_level", "i", r->override_pause_level); + + g_variant_builder_add_value(&builder, g_variant_dict_end(&dict)); + } + + g_dbus_method_invocation_return_value(invocation, g_variant_new("(aa{sv})", &builder)); + g_dbus_connection_flush(connection, NULL, NULL, NULL); +} + static void dbus_cb_dunst_RuleEnable(GDBusConnection *connection, const gchar *sender, GVariant *parameters, diff --git a/src/settings_data.h b/src/settings_data.h index afb245b73..a2ccf1ac5 100644 --- a/src/settings_data.h +++ b/src/settings_data.h @@ -122,6 +122,7 @@ struct setting { * - Add the default rule value in `settings_data.h` (usually -1 or NULL) * - Set default value in notification.c (`notification_create`). This is where * the real default is set. + * - Add the rule to the output of `dbus_cb_dunst_RuleList` in `dbus.c`. * - Free the variable in `notification.c` if dynamically allocated. * - Free the variable in `rules.c` if dynamically allocated. * - Remove the setting from the global settings struct in `settings.h`. diff --git a/test/dbus.c b/test/dbus.c index 3798ea9b3..4e5a3acd8 100644 --- a/test/dbus.c +++ b/test/dbus.c @@ -609,6 +609,67 @@ TEST test_dbus_cb_dunst_RuleEnable(void) ASSERT(!rule->enabled); g_variant_unref(result); + rules = g_slist_remove(rules, rule); + g_free(rule->name); + g_free(rule); + + PASS(); +} + +TEST test_dbus_cb_dunst_RuleList(void) +{ + struct rule *rule = rule_new("testing RuleList"); + rule->appname = "dunstify"; + rule->urgency = URG_CRIT; + rule->fg = (struct color){.r = 0.1, .g = 0.1, .b = 0.1, .a = 1.0}; + + GVariant *result = dbus_invoke_ifac("RuleList", NULL, DUNST_IFAC); + ASSERT(result != NULL); + ASSERT_STR_EQ("(aa{sv})", g_variant_get_type_string(result)); + + GVariantIter tuple_iter; + g_variant_iter_init(&tuple_iter, result); + GVariant *array = g_variant_iter_next_value(&tuple_iter); + + GVariantIter array_iter; + g_variant_iter_init(&array_iter, array); + GVariant *dict = g_variant_iter_next_value(&array_iter); + + GVariantDict d; + g_variant_dict_init(&d, dict); + + char *str; + bool boolean; + + ASSERT(g_variant_dict_lookup(&d, "name", "s", &str)); + ASSERT_STR_EQ("testing RuleList", str); + g_free(str); + + ASSERT(g_variant_dict_lookup(&d, "enabled", "b", &boolean)); + ASSERT(boolean); + + ASSERT(g_variant_dict_lookup(&d, "appname", "s", &str)); + ASSERT_STR_EQ("dunstify", str); + g_free(str); + + ASSERT(g_variant_dict_lookup(&d, "urgency", "s", &str)); + ASSERT_STR_EQ("critical", str); + g_free(str); + + ASSERT(g_variant_dict_lookup(&d, "fg", "s", &str)); + ASSERT_STR_EQ("#191919ff", str); + g_free(str); + + ASSERT_FALSE(g_variant_dict_lookup(&d, "bg", "s", &str)); + + g_variant_dict_clear(&d); + g_variant_unref(dict); + g_variant_unref(array); + g_variant_unref(result); + rules = g_slist_remove(rules, rule); + g_free(rule->name); + g_free(rule); + PASS(); } @@ -1210,7 +1271,9 @@ TEST test_override_dbus_timeout(void) ASSERT_EQ_FMT(expected_timeout, n->timeout, "%" G_GINT64_FORMAT); dbus_notification_free(n_dbus); - rule->enabled = false; + rules = g_slist_remove(rules, rule); + g_free(rule->name); + g_free(rule); PASS(); } @@ -1239,7 +1302,9 @@ TEST test_match_dbus_timeout(void) ASSERT_EQ_FMT(expected_timeout, n->timeout, "%" G_GINT64_FORMAT); dbus_notification_free(n_dbus); - rule->enabled = false; + rules = g_slist_remove(rules, rule); + g_free(rule->name); + g_free(rule); PASS(); } @@ -1267,7 +1332,9 @@ TEST test_timeout(void) ASSERT_EQ_FMT(expected_timeout, n->timeout, "%" G_GINT64_FORMAT); dbus_notification_free(n_dbus); - rule->enabled = false; + rules = g_slist_remove(rules, rule); + g_free(rule->name); + g_free(rule); PASS(); } @@ -1309,6 +1376,7 @@ gpointer run_threaded_tests(gpointer data) RUN_TEST(test_timeout); RUN_TEST(test_dbus_cb_dunst_NotificationListHistory); RUN_TEST(test_dbus_cb_dunst_RuleEnable); + RUN_TEST(test_dbus_cb_dunst_RuleList); RUN_TEST(assert_methodlists_sorted); From 27f2aea53254575cbae390e236a51cbbbcc93862 Mon Sep 17 00:00:00 2001 From: Bjoern Hiller Date: Thu, 12 Oct 2023 17:51:02 +0200 Subject: [PATCH 2/7] Teach dunstctl how to get all defined rules --- dunstctl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dunstctl b/dunstctl index ce94815ab..7340839e8 100755 --- a/dunstctl +++ b/dunstctl @@ -34,6 +34,7 @@ show_help() { get-pause-level Get the current pause level set-pause-level level Set the pause level rule name enable|disable|toggle Enable or disable a rule by its name + rules Displays configured rules (in JSON) debug Print debugging information help Show this help EOH @@ -123,6 +124,10 @@ case "${1:-}" in property_set paused variant:boolean:"$2" fi ;; + "rules") + busctl --user --json=pretty --no-pager call org.freedesktop.Notifications /org/freedesktop/Notifications org.dunstproject.cmd0 RuleList 2>/dev/null \ + || die "Dunst is not running." + ;; "rule") [ "${2:-}" ] \ || die "No rule name parameter specified. Please give the rule name" From adca2c353aeee6d6c58dc2f0f2832aabd6caaf3a Mon Sep 17 00:00:00 2001 From: Bjoern Hiller Date: Thu, 12 Oct 2023 17:52:41 +0200 Subject: [PATCH 3/7] Generalize __fish_dunstctl_history to __fish_dunstctl_info This can be re-used to retrieve other pairs of information (e.g. history id message could be helpful as well). --- completions/dunstctl.fishcomp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/completions/dunstctl.fishcomp b/completions/dunstctl.fishcomp index 909f3ac7f..d8093a613 100644 --- a/completions/dunstctl.fishcomp +++ b/completions/dunstctl.fishcomp @@ -1,10 +1,10 @@ if command -q jq - function __fish_dunstctl_history - dunstctl history | jq -r '.data[][] | "\(.id.data)\t\(.appname.data)"' + function __fish_dunstctl_info + dunstctl $argv[1] | jq -r ".data[][] | \"\(.$argv[2].data)\t\(.$argv[3].data)\"" end else - function __fish_dunstctl_history - dunstctl history | awk '/"id" :/ {getline; getline; print $3}' + function __fish_dunstctl_info + dunstctl $argv[1] | awk -vpattern="\"$argv[2]\" :" '$0 ~ pattern {getline; getline; gsub("\"", "", $3); print $3}' end end @@ -27,7 +27,7 @@ complete -c dunstctl -f -n __fish_use_subcommand -a help -d 'Show this help' # command specific arguments complete -c dunstctl -x -n '__fish_seen_subcommand_from action close close-all context history history-clear is-paused debug help' complete -c dunstctl -x -n '__fish_seen_subcommand_from count' -a 'displayed history waiting' -complete -c dunstctl -x -n '__fish_seen_subcommand_from history-pop history-rm' -a '(__fish_dunstctl_history)' +complete -c dunstctl -x -n '__fish_seen_subcommand_from history-pop history-rm' -a '(__fish_dunstctl_info history id appname)' complete -c dunstctl -x -n '__fish_seen_subcommand_from set-paused' -a 'true false toggle' # TODO: add completion for rule when there is a proper way to get configured rules From 677cac589392ebbbe2397d07e4dbdba126bdf0ae Mon Sep 17 00:00:00 2001 From: Bjoern Hiller Date: Thu, 12 Oct 2023 17:53:44 +0200 Subject: [PATCH 4/7] Add new rules and implement proper rule completion in fish --- completions/dunstctl.fishcomp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/completions/dunstctl.fishcomp b/completions/dunstctl.fishcomp index d8093a613..3eb47c0a0 100644 --- a/completions/dunstctl.fishcomp +++ b/completions/dunstctl.fishcomp @@ -8,6 +8,16 @@ else end end +function __fish_dunstctl_rule_complete + set -l parts (string split ' ' $argv[1]) + if test (count $parts[-1]) -eq 0 || test $parts[-2] = rule + __fish_dunstctl_info rules name enabled + return + end + # TODO? enable disable might not make sense when the rule is already in the correct state + echo -e 'enable\ndisable\ntoggle' +end + # commands complete -c dunstctl -f -n __fish_use_subcommand -a action -d 'Perform the default action, or open the context menu of the notification at the given position' complete -c dunstctl -f -n __fish_use_subcommand -a close -d 'Close the last notification' @@ -20,6 +30,7 @@ complete -c dunstctl -f -n __fish_use_subcommand -a history-pop -d 'Pop the late complete -c dunstctl -f -n __fish_use_subcommand -a history-rm -d 'Remove the notification from history with given ID' complete -c dunstctl -f -n __fish_use_subcommand -a is-paused -d 'Check if dunst is running or paused' complete -c dunstctl -f -n __fish_use_subcommand -a set-paused -d 'Set the pause status' +complete -c dunstctl -f -n __fish_use_subcommand -a rules -d 'Displays configured rules (in JSON)' complete -c dunstctl -f -n __fish_use_subcommand -a rule -d 'Enable or disable a rule by its name' complete -c dunstctl -f -n __fish_use_subcommand -a debug -d 'Print debugging information' complete -c dunstctl -f -n __fish_use_subcommand -a help -d 'Show this help' @@ -29,7 +40,6 @@ complete -c dunstctl -x -n '__fish_seen_subcommand_from action close close-all c complete -c dunstctl -x -n '__fish_seen_subcommand_from count' -a 'displayed history waiting' complete -c dunstctl -x -n '__fish_seen_subcommand_from history-pop history-rm' -a '(__fish_dunstctl_info history id appname)' complete -c dunstctl -x -n '__fish_seen_subcommand_from set-paused' -a 'true false toggle' - -# TODO: add completion for rule when there is a proper way to get configured rules +complete -c dunstctl -x -n '__fish_seen_subcommand_from rule' -a '(__fish_dunstctl_rule_complete (commandline -c))' # ex: filetype=fish From 78e4289b23af74ab9ab3fe717d60cee0584b21a9 Mon Sep 17 00:00:00 2001 From: Bjoern Hiller Date: Fri, 10 Nov 2023 16:10:32 +0100 Subject: [PATCH 5/7] Implement human-readable variant of RuleList The old JSON formatted variant is now reachable with the `--json` flag. --- completions/dunstctl.fishcomp | 9 +++++---- dunstctl | 22 +++++++++++++++++++--- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/completions/dunstctl.fishcomp b/completions/dunstctl.fishcomp index 3eb47c0a0..a64f02f05 100644 --- a/completions/dunstctl.fishcomp +++ b/completions/dunstctl.fishcomp @@ -1,17 +1,17 @@ if command -q jq function __fish_dunstctl_info - dunstctl $argv[1] | jq -r ".data[][] | \"\(.$argv[2].data)\t\(.$argv[3].data)\"" + dunstctl (string split ' ' $argv[1]) | jq -r ".data[][] | \"\(.$argv[2].data)\t\(.$argv[3].data)\"" end else function __fish_dunstctl_info - dunstctl $argv[1] | awk -vpattern="\"$argv[2]\" :" '$0 ~ pattern {getline; getline; gsub("\"", "", $3); print $3}' + dunstctl (string split ' ' $argv[1]) | awk -vpattern="\"$argv[2]\" :" '$0 ~ pattern {getline; getline; gsub("\"", "", $3); print $3}' end end function __fish_dunstctl_rule_complete set -l parts (string split ' ' $argv[1]) if test (count $parts[-1]) -eq 0 || test $parts[-2] = rule - __fish_dunstctl_info rules name enabled + __fish_dunstctl_info 'rules --json' name enabled return end # TODO? enable disable might not make sense when the rule is already in the correct state @@ -30,7 +30,7 @@ complete -c dunstctl -f -n __fish_use_subcommand -a history-pop -d 'Pop the late complete -c dunstctl -f -n __fish_use_subcommand -a history-rm -d 'Remove the notification from history with given ID' complete -c dunstctl -f -n __fish_use_subcommand -a is-paused -d 'Check if dunst is running or paused' complete -c dunstctl -f -n __fish_use_subcommand -a set-paused -d 'Set the pause status' -complete -c dunstctl -f -n __fish_use_subcommand -a rules -d 'Displays configured rules (in JSON)' +complete -c dunstctl -f -n __fish_use_subcommand -a rules -d 'Displays configured rules (optionally in JSON)' complete -c dunstctl -f -n __fish_use_subcommand -a rule -d 'Enable or disable a rule by its name' complete -c dunstctl -f -n __fish_use_subcommand -a debug -d 'Print debugging information' complete -c dunstctl -f -n __fish_use_subcommand -a help -d 'Show this help' @@ -41,5 +41,6 @@ complete -c dunstctl -x -n '__fish_seen_subcommand_from count' -a 'displayed his complete -c dunstctl -x -n '__fish_seen_subcommand_from history-pop history-rm' -a '(__fish_dunstctl_info history id appname)' complete -c dunstctl -x -n '__fish_seen_subcommand_from set-paused' -a 'true false toggle' complete -c dunstctl -x -n '__fish_seen_subcommand_from rule' -a '(__fish_dunstctl_rule_complete (commandline -c))' +complete -c dunstctl -x -n '__fish_seen_subcommand_from rules' -a --json # ex: filetype=fish diff --git a/dunstctl b/dunstctl index 7340839e8..97f2dc733 100755 --- a/dunstctl +++ b/dunstctl @@ -34,7 +34,8 @@ show_help() { get-pause-level Get the current pause level set-pause-level level Set the pause level rule name enable|disable|toggle Enable or disable a rule by its name - rules Displays configured rules (in JSON) + rules [--json] Displays configured rules (optionally + in JSON) debug Print debugging information help Show this help EOH @@ -125,8 +126,23 @@ case "${1:-}" in fi ;; "rules") - busctl --user --json=pretty --no-pager call org.freedesktop.Notifications /org/freedesktop/Notifications org.dunstproject.cmd0 RuleList 2>/dev/null \ - || die "Dunst is not running." + case "${2:-}" in + "" | --json) + busctl --user --json=pretty --no-pager call "${DBUS_NAME}" "${DBUS_PATH}" "${DBUS_IFAC_DUNST}" RuleList \ + | { + if [ "${2:-}" = '--json' ] + then + cat + else + jq --raw-output '.data[][] | ["[\(.name.data)]"], [to_entries[] | select(.key != "name") | " \(.key) = \(.value.data)"] | join("\n")' + fi + } \ + || die "Dunst is not running." + ;; + *) + die "Unknown format \"${2}\". Please use either \"--json\" or no option at all." + ;; + esac ;; "rule") [ "${2:-}" ] \ From b852511a62eb2f6178163abebc7c2dd4b3bd28a7 Mon Sep 17 00:00:00 2001 From: Bjoern Hiller Date: Fri, 19 Apr 2024 16:06:27 +0200 Subject: [PATCH 6/7] Document new rules subcommand in man page of dunstctl --- docs/dunstctl.pod | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/dunstctl.pod b/docs/dunstctl.pod index 7ceaa31ab..626972674 100644 --- a/docs/dunstctl.pod +++ b/docs/dunstctl.pod @@ -85,6 +85,10 @@ display specific notifications while paused. Enables, disables or toggles the rule identified by its name. This can be used to temporarily activate or deactivate specific rules. +=item B [--json] + +Exports all currently configured rules (optionally JSON formatted). + =item B Tries to contact dunst and checks for common faults between dunstctl and dunst. From 30b83c430f46ebbdb4bea9dc32267aee5e2a5c8a Mon Sep 17 00:00:00 2001 From: Bjoern Hiller Date: Fri, 19 Apr 2024 16:40:48 +0200 Subject: [PATCH 7/7] Update completions to use new method --- README.md | 1 + completions/_dunstctl.zshcomp | 5 ++--- completions/dunstctl.bashcomp | 9 +++++---- completions/dunstctl.fishcomp | 10 ++-------- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 2946f1d94..445659e71 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,7 @@ distro's repositories, don't worry, it's not hard to build it yourself. - wayland-client (can build without, see [make parameters](#make-parameters)) - wayland-protocols (optional, for recompiling protocols) - xdg-utils (optional, xdg-open is the default 'browser' for opening URLs) +- jq (optional, for installed completions and tools in contrib) The names will be different depending on your [distribution](https://github.com/dunst-project/dunst/wiki/Dependencies). diff --git a/completions/_dunstctl.zshcomp b/completions/_dunstctl.zshcomp index 856fbe0a5..57a66604c 100644 --- a/completions/_dunstctl.zshcomp +++ b/completions/_dunstctl.zshcomp @@ -6,8 +6,6 @@ local curcontext="$curcontext" ret=1 local -a state line subs -local DUNSTRC="${XDG_CONFIG_HOME:-$HOME/.config}/dunst/dunstrc" - _arguments -C \ '1:cmd:->cmds' \ '2:opt:->opts' \ @@ -30,6 +28,7 @@ case $state in 'get-pause-level:Get current dunst's pause level' 'set-pause-level:Set current dunst's pause level' 'rule:Enable or disable a rule by its name' + 'rules:Displays configured rules' 'debug:Print debugging information' 'help:Show this help' ) @@ -63,7 +62,7 @@ case $state in rule) local -a rules; rules=( - `awk '/^\[.*\]/{ if ( match($0, /^\[global|urgency|experimental/) == 0 ) { print substr($0, 2, length($0)-2) } }' < "$DUNSTRC"` + `dunstctl rules --json | jq -r '.data[][].name.data'` ) _describe rules_opts rules && ret=0 ;; diff --git a/completions/dunstctl.bashcomp b/completions/dunstctl.bashcomp index a72c9c405..6a1e19309 100644 --- a/completions/dunstctl.bashcomp +++ b/completions/dunstctl.bashcomp @@ -1,9 +1,8 @@ _dunstctl() { local opts cur prev split=false - local DUNSTRC=${XDG_CONFIG_HOME:-$HOME/.config}/dunst/dunstrc _get_comp_words_by_ref cur prev COMPREPLY=() - opts='action close close-all context count debug help history history-clear history-pop history-rm is-paused rule set-paused' + opts='action close close-all context count debug help history history-clear history-pop history-rm is-paused rule rules set-paused' case "$prev" in count) COMPREPLY=('displayed' 'history' 'waiting') @@ -15,8 +14,10 @@ _dunstctl() { awk '/"data" :/{print $3}' | sort -u) ) return ;; rule) - COMPREPLY=( $(awk \ - '/^\[.*\]/{ if ( match($0, /^\[global|experimental/) == 0 ) print substr($0, 2, length($0)-2) }' "$DUNSTRC" ) ) + COMPREPLY=( $( compgen -W "$(dunstctl rules --json | jq -r '.data[][].name.data')" -- $cur ) ) + return ;; + rules) + COMPREPLY=( $( compgen -W "--json" ) ) return ;; esac diff --git a/completions/dunstctl.fishcomp b/completions/dunstctl.fishcomp index a64f02f05..6d4a99b22 100644 --- a/completions/dunstctl.fishcomp +++ b/completions/dunstctl.fishcomp @@ -1,11 +1,5 @@ -if command -q jq - function __fish_dunstctl_info - dunstctl (string split ' ' $argv[1]) | jq -r ".data[][] | \"\(.$argv[2].data)\t\(.$argv[3].data)\"" - end -else - function __fish_dunstctl_info - dunstctl (string split ' ' $argv[1]) | awk -vpattern="\"$argv[2]\" :" '$0 ~ pattern {getline; getline; gsub("\"", "", $3); print $3}' - end +function __fish_dunstctl_info + dunstctl (string split ' ' $argv[1]) | jq -r ".data[][] | \"\(.$argv[2].data)\t\(.$argv[3].data)\"" end function __fish_dunstctl_rule_complete