diff --git a/docs/dunst.5.pod b/docs/dunst.5.pod index 04f32f51b..b616bc2d5 100644 --- a/docs/dunst.5.pod +++ b/docs/dunst.5.pod @@ -364,6 +364,14 @@ For a complete markup reference, see =item B<%I> iconname (without its path) +=item B<%D> duplicate notification count + +=item B<%A> custom action indicator + +=item B<%C> action count + +=item B<%U> custom URL indicator + =item B<%p> progress value ([ 0%] to [100%]) =item B<%n> progress value without any extra characters @@ -404,10 +412,24 @@ it, summary, body, icon and urgency are all identical. Hide the count of stacked duplicate notifications. -=item B (values: [true/false], default: true) +=item B DEPRECATED (values: [true/false], default: true) Show an indicator if a notification contains actions and/or open-able URLs. See -ACTIONS below for further details. +ACTIONS below for further details. This setting is deprecated, please use +action_indicator and url_indicator instead. + +=item B (values: [true/false], default: true) + +Includes the number of actions available in the default action indicator. +If %C is used in the format string, it will be shown regardless of this setting. + +=item B (default: "A") + +Indicator used in the format string replacing %A when the notification has actions. + +=item B (default: "U") + +Indicator used in the format string replacing %U when the notification has URLs. =item B (default: "/usr/share/icons/gnome/16x16/status/:/usr/share/icons/gnome/16x16/devices/") diff --git a/dunstrc b/dunstrc index b92482b77..9aa171ee4 100644 --- a/dunstrc +++ b/dunstrc @@ -159,6 +159,10 @@ # %b body # %i iconname (including its path) # %I iconname (without its path) + # %D Duplicate notification count + # %A Action indicator + # %C Action count + # %U URL indicator # %p progress value if set ([ 0%] to [100%]) or nothing # %n progress value if set without any extra characters # %% Literal % @@ -191,9 +195,16 @@ # Hide the count of stacked notifications with the same content hide_duplicate_count = false - # Display indicators for URLs (U) and actions (A). + # (DEPRECATED) Display default indicators for URLs (U) and actions (A) show_indicators = yes + # Prefix default action indicator with action count (for custom indicators use %C) + show_action_count = yes + + # Custom indicators + action_indicator = "A" + url_indicator = "U" + ### Icons ### # Recursive icon lookup. You can set a single theme, instead of having to diff --git a/src/notification.c b/src/notification.c index d23ab7da8..1152d83b1 100644 --- a/src/notification.c +++ b/src/notification.c @@ -589,6 +589,38 @@ static void notification_format_message(struct notification *n) n->progress != -1 ? pg : "", MARKUP_NO); break; + case 'D': + char *dup_count = g_strdup_printf("(%d)", n->dup_count); + notification_replace_single_field( + &n->msg, + &substr, + n->dup_count > 0 ? dup_count : "", + MARKUP_NO); + g_free(dup_count); + break; + case 'A': + notification_replace_single_field( + &n->msg, + &substr, + g_hash_table_size(n->actions) ? settings.action_indicator : "", + MARKUP_NO); + break; + case 'C': + char *action_count = g_strdup_printf("%d", g_hash_table_size(n->actions)); + notification_replace_single_field( + &n->msg, + &substr, + action_count, + MARKUP_NO); + g_free(action_count); + break; + case 'U': + notification_replace_single_field( + &n->msg, + &substr, + n->urls ? settings.url_indicator : "", + MARKUP_NO); + break; case '%': notification_replace_single_field( &n->msg, @@ -651,21 +683,41 @@ void notification_update_text_to_render(struct notification *n) char *buf = NULL; + char *prev_indicators = NULL; + char *indicators = NULL; + char *msg = g_strchomp(n->msg); - /* print dup_count and msg */ - if ((n->dup_count > 0 && !settings.hide_duplicate_count) - && (g_hash_table_size(n->actions) || n->urls) && settings.show_indicators) { - buf = g_strdup_printf("(%d%s%s) %s", - n->dup_count, - g_hash_table_size(n->actions) ? "A" : "", - n->urls ? "U" : "", msg); - } else if ((g_hash_table_size(n->actions) || n->urls) && settings.show_indicators) { - buf = g_strdup_printf("(%s%s) %s", - g_hash_table_size(n->actions) ? "A" : "", - n->urls ? "U" : "", msg); - } else if (n->dup_count > 0 && !settings.hide_duplicate_count) { - buf = g_strdup_printf("(%d) %s", n->dup_count, msg); + if (n->dup_count > 0 && !settings.hide_duplicate_count) { + indicators = g_strdup_printf("%d ", n->dup_count); + } + + if (settings.show_indicators) { + if(g_hash_table_size(n->actions)) { + prev_indicators = indicators; + char *action_count = g_strdup_printf("%d", g_hash_table_size(n->actions)); + + indicators = g_strdup_printf("%s%s%s", + prev_indicators ? prev_indicators : "", + settings.show_action_count ? action_count : "", + settings.action_indicator + ); + + g_free(prev_indicators); + g_free(action_count); + } + if(n->urls) { + prev_indicators = indicators; + + indicators = g_strdup_printf("%s%s", prev_indicators ? prev_indicators : "", settings.url_indicator); + + g_free(prev_indicators); + } + } + + if (indicators) { + buf = g_strdup_printf("(%s) %s", indicators, msg); + g_free(indicators); } else { buf = g_strdup(msg); } @@ -705,7 +757,7 @@ void notification_update_text_to_render(struct notification *n) void notification_do_action(struct notification *n) { assert(n->default_action_name); - + if (g_hash_table_size(n->actions)) { if (g_hash_table_contains(n->actions, n->default_action_name)) { signal_action_invoked(n, n->default_action_name); diff --git a/src/settings.h b/src/settings.h index 4496ca1d1..95522b362 100644 --- a/src/settings.h +++ b/src/settings.h @@ -109,6 +109,9 @@ struct settings { int sticky_history; int history_length; int show_indicators; + int show_action_count; + char *action_indicator; + char *url_indicator; int ignore_dbusclose; int ignore_newline; int line_height; diff --git a/src/settings_data.h b/src/settings_data.h index 5c68bb4ff..7162b8355 100644 --- a/src/settings_data.h +++ b/src/settings_data.h @@ -112,7 +112,7 @@ struct setting { /* * How to add/change a rule * ------------------------ - * + * * - Add variable to `struct rules` in `rules.h` (make sure to read the comment * at the top of the struct) * - Add variable to to `struct notification` in `notification.h` @@ -957,13 +957,43 @@ static const struct setting allowed_settings[] = { { .name = "show_indicators", .section = "global", - .description = "Show indicators for actions \"(A)\" and URLs \"(U)\"", + .description = "Show default indicators for actions \"(A)\" and URLs \"(U)\"", .type = TYPE_CUSTOM, .default_value = "true", .value = &settings.show_indicators, .parser = string_parse_enum, .parser_data = boolean_enum_data, }, + { + .name = "show_action_count", + .section = "global", + .description = "Show the number of actions available for a notification", + .type = TYPE_CUSTOM, + .default_value = "true", + .value = &settings.show_action_count, + .parser = string_parse_enum, + .parser_data = boolean_enum_data, + }, + { + .name = "action_indicator", + .section = "global", + .description = "String to show when there are actions", + .type = TYPE_STRING, + .default_value = "A", + .value = &settings.action_indicator, + .parser = NULL, + .parser_data = NULL, + }, + { + .name = "url_indicator", + .section = "global", + .description = "String to show when there are URLs", + .type = TYPE_STRING, + .default_value = "U", + .value = &settings.url_indicator, + .parser = NULL, + .parser_data = NULL, + }, { .name = "separator_height", .section = "global", diff --git a/test/notification.c b/test/notification.c index 9aa249617..5fc436e70 100644 --- a/test/notification.c +++ b/test/notification.c @@ -229,6 +229,50 @@ TEST test_notification_maxlength(void) PASS(); } +TEST test_notification_with_default_indicators(void) +{ + struct notification *n = notification_create(); + + char *dummy_action = g_strdup("dummy_action"); + + n->summary = "sum"; + n->body = "bod"; + n->urls = "https://example.com"; + g_hash_table_insert(n->actions, dummy_action, dummy_action); + + n->msg = "foo"; + + notification_update_text_to_render(n); + + ASSERT(STRN_EQ(n->text_to_render, "(1AU) foo", 9)); + + g_free(dummy_action); + notification_unref(n); + + PASS(); +} + + +TEST test_notification_with_custom_indicators(void) +{ + struct notification *n = notification_create(); + + char *dummy_action = g_strdup("dummy_action"); + + n->format = "%C %A %U"; + n->urls = "https://example.com"; + g_hash_table_insert(n->actions, dummy_action, dummy_action); + + notification_format_message(n); + + ASSERT(STRN_EQ(n->msg, "1 A U", 5)); + + g_free(dummy_action); + notification_unref(n); + + PASS(); +} + SUITE(suite_notification) { @@ -256,11 +300,15 @@ SUITE(suite_notification) "%b", "Look at my shiny ", "%I", "icoknpath.png", "%i", "/this/is/my/icoknpath.png", + "%D", "", + "%A", "", + "%C", "0", + "%U", "", "%p", "[ 95%]", "%n", "95", "%%", "%", "%", "%", - "%UNKNOWN", "%UNKNOWN", + "%unknown", "%unknown", NULL }; @@ -274,6 +322,8 @@ SUITE(suite_notification) g_clear_pointer(&a, notification_unref); RUN_TEST(test_notification_maxlength); + RUN_TEST(test_notification_with_default_indicators); + RUN_TEST(test_notification_with_custom_indicators); } /* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */