diff --git a/contrib/dunstctl.fishcomp b/contrib/dunstctl.fishcomp index 7b59c9ba6..006e8b96d 100644 --- a/contrib/dunstctl.fishcomp +++ b/contrib/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 diff --git a/dunstctl b/dunstctl index 90afb5856..a42a7197c 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 [--json] Displays configured rules (in JSON) + rules [--json] Displays configured rules (optionally + in JSON) debug Print debugging information help Show this help EOH @@ -127,7 +128,7 @@ case "${1:-}" in "rules") case "${2:-}" in "") - method_call "${DBUS_IFAC_DUNST}.RuleList" + method_call "${DBUS_IFAC_DUNST}.RuleListHumanReadable" | sed '1s/^[[:space:]]\+//' ;; --json) busctl --user --json=pretty --no-pager call "${DBUS_NAME}" "${DBUS_PATH}" "${DBUS_IFAC_DUNST}" RuleList 2>/dev/null \ diff --git a/src/dbus.c b/src/dbus.c index 4d3c0d509..50d56866a 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -97,6 +97,9 @@ static const char *introspection_xml = " " " " " " + " " + " " + " " " " " " @@ -190,6 +193,7 @@ DBUS_METHOD(dunst_NotificationRemoveFromHistory); DBUS_METHOD(dunst_NotificationShow); DBUS_METHOD(dunst_RuleEnable); DBUS_METHOD(dunst_RuleList); +DBUS_METHOD(dunst_RuleListHumanReadable); DBUS_METHOD(dunst_Ping); static struct dbus_method methods_dunst[] = { {"ContextMenuCall", dbus_cb_dunst_ContextMenuCall}, @@ -204,6 +208,7 @@ static struct dbus_method methods_dunst[] = { {"Ping", dbus_cb_dunst_Ping}, {"RuleEnable", dbus_cb_dunst_RuleEnable}, {"RuleList", dbus_cb_dunst_RuleList}, + {"RuleListHumanReadable", dbus_cb_dunst_RuleListHumanReadable}, }; void dbus_cb_dunst_methods(GDBusConnection *connection, @@ -481,6 +486,67 @@ static void dbus_cb_dunst_RuleList(GDBusConnection *connection, g_dbus_connection_flush(connection, NULL, NULL, NULL); } +static void add_rule_entry_string(GStrvBuilder *builder, const char *name, const char *value) { + if (value) + g_strv_builder_add(builder, g_strdup_printf(" %s = %s", name, value)); +} + +static void dbus_cb_dunst_RuleListHumanReadable(GDBusConnection *connection, + const gchar *sender, + GVariant *parameters, + GDBusMethodInvocation *invocation) +{ + LOG_D("CMD: Listing all configured rules in human readable format"); + + GStrvBuilder *builder = g_strv_builder_new(); + + for (GSList *iter = rules; iter; iter = iter->next) { + struct rule *r = iter->data; + + if (is_special_section(r->name)) { + continue; + } + + g_strv_builder_add(builder, g_strdup_printf("[%s]", r->name)); + + // filters - order according to rule_matches_notification + if (r->enabled) + g_strv_builder_add(builder, g_strdup_printf(" enabled = %s", r->enabled ? "yes" : "no")); + // undocumented filter? + if (r->match_dbus_timeout >= 0) + g_strv_builder_add(builder, g_strdup_printf(" match_dbus_timeout = %ld", r->match_dbus_timeout)); + if (r->msg_urgency != URG_NONE) { + const char *msg_urgency; + switch (r->msg_urgency) { + case URG_LOW: + msg_urgency = "low"; + case URG_NORM: + msg_urgency = "normal"; + case URG_CRIT: + msg_urgency = "critical"; + } + g_strv_builder_add(builder, g_strdup_printf(" msg_urgency = %s", msg_urgency)); + } + if (r->match_transient >= 0) + g_strv_builder_add(builder, g_strdup_printf(" match_transient = %s", r->match_transient ? "yes" : "no")); + add_rule_entry_string(builder, "appname", r->appname); + add_rule_entry_string(builder, "desktop_entry", r->desktop_entry); + add_rule_entry_string(builder, "summary", r->summary); + add_rule_entry_string(builder, "body", r->body); + add_rule_entry_string(builder, "category", r->category); + add_rule_entry_string(builder, "stack_tag", r->stack_tag); + + // add an empty line after each rule to make it easier to read + g_strv_builder_add(builder, ""); + } + + gchar **answer = g_strv_builder_end(builder); + + g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", g_strjoinv("\n", answer))); + g_dbus_connection_flush(connection, NULL, NULL, NULL); + g_strfreev(answer); +} + static void dbus_cb_dunst_RuleEnable(GDBusConnection *connection, const gchar *sender, GVariant *parameters,