From 82aa682b4046f8ca6a581cd9cf502eddc6c9c760 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Mon, 24 May 2021 13:29:40 +0200 Subject: [PATCH] Adding emoji-highlight patch --- README.md | 5 +- config.def.h | 18 +++-- dmenu.c | 162 ++++++++++++++++++++++++++++++++++++++--- patch/fuzzyhighlight.c | 18 ++++- patch/highlight.c | 21 ++++-- patch/xresources.c | 75 ++++++++++++++++++- patches.def.h | 16 +++- 7 files changed, 287 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index fa707e1..56ce211 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ dmenu, how to install it and how it works. ### Changelog: -2021-05-23 - Adding support for `ctrl+v` to paste +2021-05-23 - Adding support for `ctrl+v` to paste and adding emoji-highlight patch 2021-05-17 - Added the restrict return, no sort, gridnav and plain-prompt (listfullwidth) patches @@ -81,6 +81,9 @@ dmenu, how to install it and how it works. with the current input as the last argument and update the option list according to the output of that command + - [emoji-highlight](https://tools.suckless.org/dmenu/patches/emoji-highlight/) + - this patch will allow for emojis on the left side with a colored background when selected + - [fuzzyhighlight](https://tools.suckless.org/dmenu/patches/fuzzyhighlight/) - intended to be combined with the fuzzymatch patch, this makes it so that fuzzy matches are highlighted diff --git a/config.def.h b/config.def.h index c070808..59c996f 100644 --- a/config.def.h +++ b/config.def.h @@ -57,12 +57,11 @@ static const unsigned int alphas[][3] = { }; #endif // ALPHA_PATCH -#if XRESOURCES_PATCH -static char *colors[][2] = -#else -static const char *colors[][2] = +static +#if !XRESOURCES_PATCH +const #endif // XRESOURCES_PATCH -{ +char *colors[][2] = { /* fg bg */ [SchemeNorm] = { "#bbbbbb", "#222222" }, [SchemeSel] = { "#eeeeee", "#005577" }, @@ -77,6 +76,14 @@ static const char *colors[][2] = #if HIGHPRIORITY_PATCH [SchemeHp] = { "#bbbbbb", "#333333" }, #endif // HIGHPRIORITY_PATCH + #if EMOJI_HIGHLIGHT_PATCH + [SchemeHover] = { "#ffffff", "#353D4B" }, + [SchemeGreen] = { "#ffffff", "#52E067" }, + [SchemeRed] = { "#ffffff", "#e05252" }, + [SchemeYellow] = { "#ffffff", "#e0c452" }, + [SchemeBlue] = { "#ffffff", "#5280e0" }, + [SchemePurple] = { "#ffffff", "#9952e0" }, + #endif // EMOJI_HIGHLIGHT_PATCH }; /* -l option; if nonzero, dmenu uses vertical list with given number of lines */ static unsigned int lines = 0; @@ -86,6 +93,7 @@ static unsigned int columns = 0; #endif // GRID_PATCH #if LINE_HEIGHT_PATCH static unsigned int lineheight = 0; /* -h option; minimum height of a menu line */ +static unsigned int min_lineheight = 8; #endif // LINE_HEIGHT_PATCH #if NAVHISTORY_PATCH static unsigned int maxhist = 15; diff --git a/dmenu.c b/dmenu.c index ed848e8..70d9491 100644 --- a/dmenu.c +++ b/dmenu.c @@ -69,6 +69,14 @@ enum { #if HIGHPRIORITY_PATCH SchemeHp, #endif // HIGHPRIORITY_PATCH + #if EMOJI_HIGHLIGHT_PATCH + SchemeHover, + SchemeGreen, + SchemeYellow, + SchemeBlue, + SchemePurple, + SchemeRed, + #endif // EMOJI_HIGHLIGHT_PATCH SchemeLast, }; /* color schemes */ @@ -142,6 +150,10 @@ static int use_text_input = 0; #if PRESELECT_PATCH static unsigned int preselected = 0; #endif // PRESELECT_PATCH +#if EMOJI_HIGHLIGHT_PATCH +static int commented = 0; +static int animated = 0; +#endif // EMOJI_HIGHLIGHT_PATCH static Atom clip, utf8; #if WMTYPE_PATCH @@ -279,6 +291,118 @@ static int drawitem(struct item *item, int x, int y, int w) { int r; + #if TSV_PATCH + char *text = item->stext; + #else + char *text = item->text; + #endif // TSV_PATCH + + #if EMOJI_HIGHLIGHT_PATCH + int iscomment = 0; + if (text[0] == '>') { + if (text[1] == '>') { + iscomment = 3; + switch (text[2]) { + case 'r': + drw_setscheme(drw, scheme[SchemeRed]); + break; + case 'g': + drw_setscheme(drw, scheme[SchemeGreen]); + break; + case 'y': + drw_setscheme(drw, scheme[SchemeYellow]); + break; + case 'b': + drw_setscheme(drw, scheme[SchemeBlue]); + break; + case 'p': + drw_setscheme(drw, scheme[SchemePurple]); + break; + #if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH + case 'h': + drw_setscheme(drw, scheme[SchemeNormHighlight]); + break; + #endif // HIGHLIGHT_PATCH | FUZZYHIGHLIGHT_PATCH + case 's': + drw_setscheme(drw, scheme[SchemeSel]); + break; + default: + iscomment = 1; + drw_setscheme(drw, scheme[SchemeNorm]); + break; + } + } else { + drw_setscheme(drw, scheme[SchemeNorm]); + iscomment = 1; + } + } else if (text[0] == ':') { + iscomment = 2; + if (item == sel) { + switch (text[1]) { + case 'r': + drw_setscheme(drw, scheme[SchemeRed]); + break; + case 'g': + drw_setscheme(drw, scheme[SchemeGreen]); + break; + case 'y': + drw_setscheme(drw, scheme[SchemeYellow]); + break; + case 'b': + drw_setscheme(drw, scheme[SchemeBlue]); + break; + case 'p': + drw_setscheme(drw, scheme[SchemePurple]); + break; + #if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH + case 'h': + drw_setscheme(drw, scheme[SchemeNormHighlight]); + break; + #endif // HIGHLIGHT_PATCH | FUZZYHIGHLIGHT_PATCH + case 's': + drw_setscheme(drw, scheme[SchemeSel]); + break; + default: + drw_setscheme(drw, scheme[SchemeSel]); + iscomment = 0; + break; + } + } else { + drw_setscheme(drw, scheme[SchemeNorm]); + } + } + #endif // EMOJI_HIGHLIGHT_PATCH + + #if EMOJI_HIGHLIGHT_PATCH + int temppadding = 0; + if (iscomment == 2) { + if (text[2] == ' ') { + temppadding = drw->fonts->h * 3; + animated = 1; + char dest[1000]; + strcpy(dest, text); + dest[6] = '\0'; + #if LINE_HEIGHT_PATCH + drw_text(drw, x, y, temppadding, MAX(lineheight, bh), temppadding / 2.6, dest + 3, 0); + #else + drw_text(drw, x, y, temppadding, bh, temppadding / 2.6, dest + 3, 0); + #endif // LINE_HEIGHT_PATCH + iscomment = 6; + drw_setscheme(drw, sel == item ? scheme[SchemeHover] : scheme[SchemeNorm]); + } + } + + char *output; + if (commented) { + static char onestr[2]; + onestr[0] = text[0]; + onestr[1] = '\0'; + output = onestr; + } else { + output = text; + } + #endif // EMOJI_HIGHLIGHT_PATCH + if (item == sel) drw_setscheme(drw, scheme[SchemeSel]); #if HIGHPRIORITY_PATCH @@ -298,23 +422,36 @@ drawitem(struct item *item, int x, int y, int w) else drw_setscheme(drw, scheme[SchemeNorm]); - r = drw_text(drw, x, y, w, bh, lrpad / 2 - #if TSV_PATCH - , item->stext + r = drw_text(drw + #if EMOJI_HIGHLIGHT_PATCH + , x + ((iscomment == 6) ? temppadding : 0) #else - , item->text - #endif // TSV_PATCH + , x + #endif // EMOJI_HIGHLIGHT_PATCH + , y + , w + , bh + #if EMOJI_HIGHLIGHT_PATCH + , commented ? (bh - drw_fontset_getwidth(drw, output)) / 2 : lrpad / 2 + #else + , lrpad / 2 + #endif // EMOJI_HIGHLIGHT_PATCH + #if EMOJI_HIGHLIGHT_PATCH + , output + iscomment + #else + , text + #endif // EMOJI_HIGHLIGHT_PATCH , 0 #if PANGO_PATCH , True #endif // PANGO_PATCH ); - #if PANGO_PATCH - #else - r = drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0); - #endif // PANGO_PATCH #if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH + #if EMOJI_HIGHLIGHT_PATCH + drawhighlights(item, output + iscomment, x + ((iscomment == 6) ? temppadding : 0), y, w); + #else drawhighlights(item, x, y, w); + #endif // EMOJI_HIGHLIGHT_PATCH #endif // HIGHLIGHT_PATCH | FUZZYHIGHLIGHT_PATCH return r; } @@ -1755,7 +1892,7 @@ main(int argc, char *argv[]) #if LINE_HEIGHT_PATCH else if(!strcmp(argv[i], "-h")) { /* minimum height of one menu line */ lineheight = atoi(argv[++i]); - lineheight = MAX(lineheight,8); /* reasonable default in case of value too small/negative */ + lineheight = MAX(lineheight, min_lineheight); /* reasonable default in case of value too small/negative */ } #endif // LINE_HEIGHT_PATCH else if (!strcmp(argv[i], "-nb")) /* normal background color */ @@ -1847,6 +1984,11 @@ main(int argc, char *argv[]) lrpad = drw->fonts->h; #endif // PANGO_PATCH + #if LINE_HEIGHT_PATCH + if (lineheight == -1) + lineheight = drw->fonts->h * 2.5; + #endif // LINE_HEIGHT_PATCH + #ifdef __OpenBSD__ if (pledge("stdio rpath", NULL) == -1) die("pledge"); diff --git a/patch/fuzzyhighlight.c b/patch/fuzzyhighlight.c index 5d32972..737b5d9 100644 --- a/patch/fuzzyhighlight.c +++ b/patch/fuzzyhighlight.c @@ -1,17 +1,29 @@ static void +#if EMOJI_HIGHLIGHT_PATCH +drawhighlights(struct item *item, char *output, int x, int y, int maxw) +#else drawhighlights(struct item *item, int x, int y, int maxw) +#endif // EMOJI_HIGHLIGHT_PATCH { int i, indent; char *highlight; char c; - if (!(strlen(item->text) && strlen(text))) + #if EMOJI_HIGHLIGHT_PATCH + char *itemtext = output; + #elif TSV_PATCH + char *itemtext = item->stext; + #else + char *itemtext = item->text; + #endif // TSV_PATCH + + if (!(strlen(itemtext) && strlen(text))) return; drw_setscheme(drw, scheme[item == sel ? SchemeSelHighlight : SchemeNormHighlight]); - for (i = 0, highlight = item->text; *highlight && text[i];) { + for (i = 0, highlight = itemtext; *highlight && text[i];) { #if FUZZYMATCH_PATCH if (!fstrncmp(&(*highlight), &text[i], 1)) #else @@ -21,7 +33,7 @@ drawhighlights(struct item *item, int x, int y, int maxw) /* get indentation */ c = *highlight; *highlight = '\0'; - indent = TEXTW(item->text); + indent = TEXTW(itemtext); *highlight = c; /* highlight character */ diff --git a/patch/highlight.c b/patch/highlight.c index ab5d7f2..57087a9 100644 --- a/patch/highlight.c +++ b/patch/highlight.c @@ -1,20 +1,31 @@ static void +#if EMOJI_HIGHLIGHT_PATCH +drawhighlights(struct item *item, char *output, int x, int y, int maxw) +#else drawhighlights(struct item *item, int x, int y, int maxw) +#endif // EMOJI_HIGHLIGHT_PATCH { char restorechar, tokens[sizeof text], *highlight, *token; int indentx, highlightlen; + #if EMOJI_HIGHLIGHT_PATCH + char *itemtext = output; + #elif TSV_PATCH + char *itemtext = item->stext; + #else + char *itemtext = item->text; + #endif // TSV_PATCH drw_setscheme(drw, scheme[item == sel ? SchemeSelHighlight : SchemeNormHighlight]); strcpy(tokens, text); for (token = strtok(tokens, " "); token; token = strtok(NULL, " ")) { - highlight = fstrstr(item->text, token); + highlight = fstrstr(itemtext, token); while (highlight) { // Move item str end, calc width for highlight indent, & restore - highlightlen = highlight - item->text; + highlightlen = highlight - itemtext; restorechar = *highlight; - item->text[highlightlen] = '\0'; - indentx = TEXTW(item->text); - item->text[highlightlen] = restorechar; + itemtext[highlightlen] = '\0'; + indentx = TEXTW(itemtext); + itemtext[highlightlen] = restorechar; // Move highlight str end, draw highlight, & restore restorechar = highlight[strlen(token)]; diff --git a/patch/xresources.c b/patch/xresources.c index d324863..ae5519f 100644 --- a/patch/xresources.c +++ b/patch/xresources.c @@ -45,7 +45,17 @@ readxresources(void) colors[SchemeOut][ColFg] = strdup(xval.addr); else colors[SchemeOut][ColFg] = strdup(colors[SchemeOut][ColFg]); - #if FUZZYHIGHLIGHT_PATCH + #if MORECOLOR_PATCH + if (XrmGetResource(xdb, "dmenu.midbackground", "*", &type, &xval)) + colors[SchemeMid][ColBg] = strdup(xval.addr); + else + colors[SchemeMid][ColBg] = strdup(colors[SchemeMid][ColBg]); + if (XrmGetResource(xdb, "dmenu.midforeground", "*", &type, &xval)) + colors[SchemeMid][ColFg] = strdup(xval.addr); + else + colors[SchemeMid][ColFg] = strdup(colors[SchemeMid][ColFg]); + #endif // MORECOLOR_PATCH + #if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH if (XrmGetResource(xdb, "dmenu.selhlbackground", "*", &type, &xval)) colors[SchemeSelHighlight][ColBg] = strdup(xval.addr); else @@ -62,8 +72,67 @@ readxresources(void) colors[SchemeNormHighlight][ColFg] = strdup(xval.addr); else colors[SchemeNormHighlight][ColFg] = strdup(colors[SchemeNormHighlight][ColFg]); - #endif // FUZZYHIGHLIGHT_PATCH - + #endif // HIGHLIGHT_PATCH | FUZZYHIGHLIGHT_PATCH + #if HIGHPRIORITY_PATCH + if (XrmGetResource(xdb, "dmenu.hpbackground", "*", &type, &xval)) + colors[SchemeHp][ColBg] = strdup(xval.addr); + else + colors[SchemeHp][ColBg] = strdup(colors[SchemeHp][ColBg]); + if (XrmGetResource(xdb, "dmenu.hpforeground", "*", &type, &xval)) + colors[SchemeHp][ColFg] = strdup(xval.addr); + else + colors[SchemeHp][ColFg] = strdup(colors[SchemeHp][ColFg]); + #endif // HIGHPRIORITY_PATCH + #if EMOJI_HIGHLIGHT_PATCH + if (XrmGetResource(xdb, "dmenu.hoverbackground", "*", &type, &xval)) + colors[SchemeHover][ColBg] = strdup(xval.addr); + else + colors[SchemeHover][ColBg] = strdup(colors[SchemeHover][ColBg]); + if (XrmGetResource(xdb, "dmenu.hoverforeground", "*", &type, &xval)) + colors[SchemeHover][ColFg] = strdup(xval.addr); + else + colors[SchemeHover][ColFg] = strdup(colors[SchemeHover][ColFg]); + if (XrmGetResource(xdb, "dmenu.greenbackground", "*", &type, &xval)) + colors[SchemeGreen][ColBg] = strdup(xval.addr); + else + colors[SchemeGreen][ColBg] = strdup(colors[SchemeGreen][ColBg]); + if (XrmGetResource(xdb, "dmenu.greenforeground", "*", &type, &xval)) + colors[SchemeGreen][ColFg] = strdup(xval.addr); + else + colors[SchemeGreen][ColFg] = strdup(colors[SchemeGreen][ColFg]); + if (XrmGetResource(xdb, "dmenu.yellowbackground", "*", &type, &xval)) + colors[SchemeYellow][ColBg] = strdup(xval.addr); + else + colors[SchemeYellow][ColBg] = strdup(colors[SchemeYellow][ColBg]); + if (XrmGetResource(xdb, "dmenu.yellowforeground", "*", &type, &xval)) + colors[SchemeYellow][ColFg] = strdup(xval.addr); + else + colors[SchemeYellow][ColFg] = strdup(colors[SchemeYellow][ColFg]); + if (XrmGetResource(xdb, "dmenu.bluebackground", "*", &type, &xval)) + colors[SchemeBlue][ColBg] = strdup(xval.addr); + else + colors[SchemeBlue][ColBg] = strdup(colors[SchemeBlue][ColBg]); + if (XrmGetResource(xdb, "dmenu.blueforeground", "*", &type, &xval)) + colors[SchemeBlue][ColFg] = strdup(xval.addr); + else + colors[SchemeBlue][ColFg] = strdup(colors[SchemeBlue][ColFg]); + if (XrmGetResource(xdb, "dmenu.purplebackground", "*", &type, &xval)) + colors[SchemePurple][ColBg] = strdup(xval.addr); + else + colors[SchemePurple][ColBg] = strdup(colors[SchemePurple][ColBg]); + if (XrmGetResource(xdb, "dmenu.purpleforeground", "*", &type, &xval)) + colors[SchemePurple][ColFg] = strdup(xval.addr); + else + colors[SchemePurple][ColFg] = strdup(colors[SchemePurple][ColFg]); + if (XrmGetResource(xdb, "dmenu.redbackground", "*", &type, &xval)) + colors[SchemeRed][ColBg] = strdup(xval.addr); + else + colors[SchemeRed][ColBg] = strdup(colors[SchemeRed][ColBg]); + if (XrmGetResource(xdb, "dmenu.redforeground", "*", &type, &xval)) + colors[SchemeRed][ColFg] = strdup(xval.addr); + else + colors[SchemeRed][ColFg] = strdup(colors[SchemeRed][ColFg]); + #endif // EMOJI_HIGHLIGHT_PATCH XrmDestroyDatabase(xdb); } } \ No newline at end of file diff --git a/patches.def.h b/patches.def.h index cc61afb..828b1a2 100644 --- a/patches.def.h +++ b/patches.def.h @@ -43,6 +43,15 @@ */ #define DYNAMIC_OPTIONS_PATCH 0 +/* This patch will allow for emojis on the left side with a colored background when selected. + * To test this try running: + * $ echo -e ":b here\n:p there\n:r and here" | ./dmenu -p "Search..." -W 400 -l 20 -i -h -1 + * NB: the original patch came embedded with the the xyw patch, the morecolors patch and the + * line height patch and as such is intended to be combined with these. + * https://tools.suckless.org/dmenu/patches/emoji-highlight/ + */ +#define EMOJI_HIGHLIGHT_PATCH 0 + /* This patch make it so that fuzzy matches gets highlighted and is therefore meant * to be used together with the fuzzymatch patch. * https://tools.suckless.org/dmenu/patches/fuzzyhighlight/ @@ -259,8 +268,10 @@ */ #define REJECTNOMATCH_PATCH 0 -/* This patch adds a '-r' option which disables Shift-Return and Ctrl-Return. +/* This patch adds a '-1' option which disables Shift-Return and Ctrl-Return. * This guarantees that dmenu will only output one item, and that item was read from stdin. + * The original patch used '-r'. This was changed to '-1' to avoid conflict with the incremental + * patch. * https://tools.suckless.org/dmenu/patches/restrict-return/ */ #define RESTRICT_RETURN_PATCH 0 @@ -304,6 +315,9 @@ * dmenu.foreground : normal foreground color * dmenu.selbackground : selected background color * dmenu.selforeground : selected foreground color + * + * See patch/xresources.c for more color settings. + * * https://tools.suckless.org/dmenu/patches/xresources/ */ #define XRESOURCES_PATCH 0