Merge allow_markup and plain_text into markup

Merge the allow_markup and plain_text settings into a single setting.

These 2 settings had a similar function, allow_markup controlled whether
markup was parsed or stripped and plain_text whether the notification
was escaped and displayed as is.

To cover all the possible combinations of the settings mentioned above
`markup` can take the following values:

full:  The equivalent of allow_markup yes, plain_text no.
       Passes the text straight to pango with minimal parsing. All valid
       pango tags will be parsed.

strip: The equivalent of allow_markup no, plain_text no.
       Strips the markup using string_strip_delimited. The parsing is
       simplistic and if there are any unescaped '<' and/or '>'
       characters it might get tripped and strip out actual text.

       According to the GNOME notification specification, if a server
       doesn't support markup(and we don't advertise that we do if it is
       turned off) it should be stripped clientside, so this setting
       should rarely be used. It is mainly left in for compatibility
       with broken clients that don't follow the specification.

no:   The equivalent of allow_markup [yes/no](any value), plain_text
      yes.
      Makes the notification content be rendered as plain text
      regardless if it contains markup. Any Markup will be shown as
      regular text.

Markup inside 'format' will still be parsed regardless of what markup is
set to.

Closes #279
This commit is contained in:
Nikos Tsipinakis 2017-02-04 16:36:43 +02:00
parent 4aa4e93123
commit 4e1b97f3cc
10 changed files with 89 additions and 61 deletions

View File

@ -1,8 +1,7 @@
/* see example dunstrc for additional explanations about these options */ /* see example dunstrc for additional explanations about these options */
char *font = "-*-terminus-medium-r-*-*-16-*-*-*-*-*-*-*"; char *font = "-*-terminus-medium-r-*-*-16-*-*-*-*-*-*-*";
bool allow_markup = false; char *markup = "no";
bool plain_text = true;
char *normbgcolor = "#1793D1"; char *normbgcolor = "#1793D1";
char *normfgcolor = "#DDDDDD"; char *normfgcolor = "#DDDDDD";
char *critbgcolor = "#ffaaaa"; char *critbgcolor = "#ffaaaa";
@ -94,11 +93,11 @@ keyboard_shortcut context_ks = {.str = "none",
rule_t default_rules[] = { rule_t default_rules[] = {
/* name can be any unique string. It is used to identify the rule in dunstrc to override it there */ /* name can be any unique string. It is used to identify the rule in dunstrc to override it there */
/* name, appname, summary, body, icon, category, msg_urgency, timeout, urgency, allow_markup, plain_text, new_icon, fg, bg, format, script */ /* name, appname, summary, body, icon, category, msg_urgency, timeout, urgency, markup, new_icon, fg, bg, format, script */
{ "empty", NULL, NULL, NULL, NULL, NULL, -1, -1, -1, -1, -1, NULL, NULL, NULL, NULL, NULL}, { "empty", NULL, NULL, NULL, NULL, NULL, -1, -1, -1, -1, NULL, NULL, NULL, NULL, NULL},
/* { "rule1", "notify-send", NULL, NULL, NULL, NULL, -1, -1, -1, -1, -1, NULL, NULL, NULL, "%s %b", NULL }, */ /* { "rule1", "notify-send", NULL, NULL, NULL, NULL, -1, -1, -1, -1, NULL, NULL, NULL, "%s %b", NULL }, */
/* { "rule2", "Pidgin", "*says*, NULL, NULL, NULL, -1, -1, CRITICAL, -1, -1, NULL, NULL, NULL, NULL, NULL }, */ /* { "rule2", "Pidgin", "*says*, NULL, NULL, NULL, -1, -1, CRITICAL, -1, NULL, NULL, NULL, NULL, NULL }, */
/* { "rule3", "Pidgin", "*signed on*", NULL, NULL, NULL, -1, -1, LOW, -1, -1, NULL, NULL, NULL, NULL, NULL }, */ /* { "rule3", "Pidgin", "*signed on*", NULL, NULL, NULL, -1, -1, LOW, -1, NULL, NULL, NULL, NULL, NULL }, */
/* { "rule4", "Pidgin", "*signed off*", NULL, NULL, NULL, -1, -1, LOW, -1, -1, NULL, NULL, NULL, NULL, NULL }, */ /* { "rule4", "Pidgin", "*signed off*", NULL, NULL, NULL, -1, -1, LOW, -1, NULL, NULL, NULL, NULL, NULL }, */
/* { "rule5", NULL, "*foobar*", NULL, NULL, NULL, -1, -1, -1, -1, -1, NULL, NULL, "#00FF00", NULL, NULL }, */ /* { "rule5", NULL, "*foobar*", NULL, NULL, NULL, -1, -1, -1, -1, NULL, NULL, "#00FF00", NULL, NULL }, */
}; };

35
dunstrc
View File

@ -1,20 +1,29 @@
[global] [global]
font = Monospace 8 font = Monospace 8
# Allow a small subset of html markup in notifications and formats: # Possible values are:
# <b>bold</b> # full: Allow a small subset of html markup in notifications:
# <i>italic</i> # <b>bold</b>
# <s>strikethrough</s> # <i>italic</i>
# <u>underline</u> # <s>strikethrough</s>
# <u>underline</u>
# #
# For a complete reference see # For a complete reference see
# <http://developer.gnome.org/pango/stable/PangoMarkupFormat.html>. # <http://developer.gnome.org/pango/stable/PangoMarkupFormat.html>.
# If markup is not allowed, those tags will be stripped out of the #
# message. # strip: This setting is provided for compatibility with some broken
allow_markup = yes # clients that send markup even though it's not enabled on the
# server. Dunst will try to strip the markup but the parsing is
# Treat incoming notifications as plain text # simplistic so using this option outside of matching rules for
plain_text = no # specific applications *IS GREATLY DISCOURAGED*.
#
# no: Disable markup parsing, incoming notifications will be treated as
# plain text. Dunst will not advertise that it has the body-markup
# capability if this is set as a global setting.
#
# It's important to note that markup inside the format option will be parsed
# regardless of what this is set to.
markup = full
# The format of the message. Possible variables are: # The format of the message. Possible variables are:
# %a appname # %a appname

View File

@ -110,7 +110,10 @@ static void on_get_capabilities(GDBusConnection * connection,
builder = g_variant_builder_new(G_VARIANT_TYPE("as")); builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
g_variant_builder_add(builder, "s", "actions"); g_variant_builder_add(builder, "s", "actions");
g_variant_builder_add(builder, "s", "body"); g_variant_builder_add(builder, "s", "body");
g_variant_builder_add(builder, "s", "body-markup");
if(settings.markup != MARKUP_NO)
g_variant_builder_add(builder, "s", "body-markup");
value = g_variant_new("(as)", builder); value = g_variant_new("(as)", builder);
g_variant_builder_unref(builder); g_variant_builder_unref(builder);
g_dbus_method_invocation_return_value(invocation, value); g_dbus_method_invocation_return_value(invocation, value);
@ -301,8 +304,7 @@ static void on_notify(GDBusConnection * connection,
n->icon = icon; n->icon = icon;
n->raw_icon = raw_icon; n->raw_icon = raw_icon;
n->timeout = timeout; n->timeout = timeout;
n->allow_markup = settings.allow_markup; n->markup = settings.markup;
n->plain_text = settings.plain_text;
n->progress = (progress < 0 || progress > 100) ? 0 : progress + 1; n->progress = (progress < 0 || progress > 100) ? 0 : progress + 1;
n->urgency = urgency; n->urgency = urgency;
n->category = category; n->category = category;

View File

@ -349,8 +349,7 @@ int dunst_main(int argc, char *argv[])
n->body = strdup("dunst is up and running"); n->body = strdup("dunst is up and running");
n->progress = 0; n->progress = 0;
n->timeout = 10; n->timeout = 10;
n->allow_markup = false; n->markup = MARKUP_NO;
n->plain_text = true;
n->urgency = LOW; n->urgency = LOW;
notification_init(n, 0); notification_init(n, 0);
} }

View File

@ -236,15 +236,14 @@ char *notification_quote_markup(char *str)
/* /*
* Replace all occurrences of "needle" with a quoted "replacement", * Replace all occurrences of "needle" with a quoted "replacement",
* according to the allow_markup/plain_text settings. * according to the markup settings.
*/ */
char *notification_replace_format(const char *needle, const char *replacement, char *notification_replace_format(const char *needle, const char *replacement,
char *haystack, bool allow_markup, char *haystack, enum markup_mode markup_mode) {
bool plain_text) {
char* tmp; char* tmp;
char* ret; char* ret;
if (plain_text) { if (markup_mode == MARKUP_NO) {
tmp = strdup(replacement); tmp = strdup(replacement);
tmp = string_replace_all("\\n", "\n", tmp); tmp = string_replace_all("\\n", "\n", tmp);
if (settings.ignore_newline) { if (settings.ignore_newline) {
@ -265,7 +264,7 @@ char *notification_replace_format(const char *needle, const char *replacement,
tmp = string_replace_all("<br />", "\n", tmp); tmp = string_replace_all("<br />", "\n", tmp);
} }
if (!allow_markup) { if (markup_mode != MARKUP_FULL ) {
tmp = notification_strip_markup(tmp); tmp = notification_strip_markup(tmp);
tmp = notification_quote_markup(tmp); tmp = notification_quote_markup(tmp);
} }
@ -373,17 +372,17 @@ int notification_init(notification * n, int id)
n->msg = string_replace_all("\\n", "\n", g_strdup(n->format)); n->msg = string_replace_all("\\n", "\n", g_strdup(n->format));
n->msg = notification_replace_format("%a", n->appname, n->msg, n->msg = notification_replace_format("%a", n->appname, n->msg,
false, true); MARKUP_NO);
n->msg = notification_replace_format("%s", n->summary, n->msg, n->msg = notification_replace_format("%s", n->summary, n->msg,
n->allow_markup, n->plain_text); n->markup);
n->msg = notification_replace_format("%b", n->body, n->msg, n->msg = notification_replace_format("%b", n->body, n->msg,
n->allow_markup, n->plain_text); n->markup);
if (n->icon) { if (n->icon) {
n->msg = notification_replace_format("%I", basename(n->icon), n->msg = notification_replace_format("%I", basename(n->icon),
n->msg, false, true); n->msg, MARKUP_NO);
n->msg = notification_replace_format("%i", n->icon, n->msg = notification_replace_format("%i", n->icon,
n->msg, false, true); n->msg, MARKUP_NO);
} }
if (n->progress) { if (n->progress) {

View File

@ -3,6 +3,7 @@
#define DUNST_NOTIFICATION_H #define DUNST_NOTIFICATION_H
#include "x.h" #include "x.h"
#include "settings.h"
#define LOW 0 #define LOW 0
#define NORM 1 #define NORM 1
@ -39,8 +40,7 @@ typedef struct _notification {
time_t timestamp; time_t timestamp;
int timeout; int timeout;
int urgency; int urgency;
bool allow_markup; enum markup_mode markup;
bool plain_text;
bool redisplayed; /* has been displayed before? */ bool redisplayed; /* has been displayed before? */
int id; int id;
int dup_count; int dup_count;

View File

@ -15,10 +15,8 @@ void rule_apply(rule_t * r, notification * n)
n->timeout = r->timeout; n->timeout = r->timeout;
if (r->urgency != -1) if (r->urgency != -1)
n->urgency = r->urgency; n->urgency = r->urgency;
if (r->allow_markup != -1) if (r->markup != -1)
n->allow_markup = r->allow_markup; n->markup = r->markup;
if (r->plain_text != -1)
n->plain_text = r->plain_text;
if (r->new_icon) { if (r->new_icon) {
if(n->icon) if(n->icon)
g_free(n->icon); g_free(n->icon);
@ -61,8 +59,7 @@ void rule_init(rule_t * r)
r->msg_urgency = -1; r->msg_urgency = -1;
r->timeout = -1; r->timeout = -1;
r->urgency = -1; r->urgency = -1;
r->allow_markup = -1; r->markup = -1;
r->plain_text = -1;
r->new_icon = NULL; r->new_icon = NULL;
r->fg = NULL; r->fg = NULL;
r->bg = NULL; r->bg = NULL;

View File

@ -6,6 +6,7 @@
#include "dunst.h" #include "dunst.h"
#include "notification.h" #include "notification.h"
#include "settings.h"
typedef struct _rule_t { typedef struct _rule_t {
char *name; char *name;
@ -20,8 +21,7 @@ typedef struct _rule_t {
/* actions */ /* actions */
int timeout; int timeout;
int urgency; int urgency;
int allow_markup; enum markup_mode markup;
int plain_text;
char *new_icon; char *new_icon;
char *fg; char *fg;
char *bg; char *bg;

View File

@ -30,7 +30,20 @@ static void parse_follow_mode(const char *mode)
fprintf(stderr, "Warning: unknown follow mode: \"%s\"\n", mode); fprintf(stderr, "Warning: unknown follow mode: \"%s\"\n", mode);
settings.f_mode = FOLLOW_NONE; settings.f_mode = FOLLOW_NONE;
} }
}
static enum markup_mode parse_markup_mode(const char *mode)
{
if (strcmp(mode, "strip") == 0) {
return MARKUP_STRIP;
} else if (strcmp(mode, "no") == 0) {
return MARKUP_NO;
} else if (strcmp(mode, "full") == 0) {
return MARKUP_FULL;
} else {
fprintf(stderr, "Warning: unknown markup mode: \"%s\"\n", mode);
return MARKUP_NO;
}
} }
static int ini_get_urgency(char *section, char *key, int def) static int ini_get_urgency(char *section, char *key, int def)
@ -89,17 +102,16 @@ void load_settings(char *cmdline_config_path)
"The font dunst should use." "The font dunst should use."
); );
settings.allow_markup = option_get_bool( {
"global", char *c = option_get_string(
"allow_markup", "-markup", allow_markup, "global",
"Allow markups in notifications/formats." "markup", "-markup", markup,
); "Specify how markup should be handled"
);
settings.plain_text = option_get_bool( settings.markup = parse_markup_mode(c);
"global", free(c);
"plain_text", "-plain", plain_text, }
"Treat incoming notifications as plain text."
);
settings.format = option_get_string( settings.format = option_get_string(
"global", "global",
@ -530,8 +542,19 @@ void load_settings(char *cmdline_config_path)
r->icon = ini_get_string(cur_section, "icon", r->icon); r->icon = ini_get_string(cur_section, "icon", r->icon);
r->category = ini_get_string(cur_section, "category", r->category); r->category = ini_get_string(cur_section, "category", r->category);
r->timeout = ini_get_int(cur_section, "timeout", r->timeout); r->timeout = ini_get_int(cur_section, "timeout", r->timeout);
r->allow_markup = ini_get_bool(cur_section, "allow_markup", r->allow_markup);
r->plain_text = ini_get_bool(cur_section, "plain_text", r->plain_text); {
char *c = ini_get_string(
cur_section,
"markup", ""
);
if (strlen(c) > 0) {
r->markup = parse_markup_mode(c);
free(c);
}
}
r->urgency = ini_get_urgency(cur_section, "urgency", r->urgency); r->urgency = ini_get_urgency(cur_section, "urgency", r->urgency);
r->msg_urgency = ini_get_urgency(cur_section, "msg_urgency", r->msg_urgency); r->msg_urgency = ini_get_urgency(cur_section, "msg_urgency", r->msg_urgency);
r->fg = ini_get_string(cur_section, "foreground", r->fg); r->fg = ini_get_string(cur_section, "foreground", r->fg);

View File

@ -6,11 +6,11 @@ enum alignment { left, center, right };
enum icon_position_t { icons_left, icons_right, icons_off }; enum icon_position_t { icons_left, icons_right, icons_off };
enum separator_color { FOREGROUND, AUTO, FRAME, CUSTOM }; enum separator_color { FOREGROUND, AUTO, FRAME, CUSTOM };
enum follow_mode { FOLLOW_NONE, FOLLOW_MOUSE, FOLLOW_KEYBOARD }; enum follow_mode { FOLLOW_NONE, FOLLOW_MOUSE, FOLLOW_KEYBOARD };
enum markup_mode { MARKUP_NO, MARKUP_STRIP, MARKUP_FULL };
typedef struct _settings { typedef struct _settings {
bool print_notifications; bool print_notifications;
bool allow_markup; enum markup_mode markup;
bool plain_text;
bool stack_duplicates; bool stack_duplicates;
bool hide_duplicates_count; bool hide_duplicates_count;
char *font; char *font;