diff --git a/config.def.h b/config.def.h index 1edb647..ed3b175 100644 --- a/config.def.h +++ b/config.def.h @@ -4,18 +4,33 @@ static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ /* -fn option overrides fonts[0]; default X11 font or font set */ static const char *fonts[] = { - "monospace:size=10" + "monospace:size=10", + "FiraCode Nerd Font:size=12", }; + static const char *prompt = NULL; /* -p option; prompt to the left of input field */ -static const char *colors[SchemeLast][2] = { - /* fg bg */ - [SchemeNorm] = { "#bbbbbb", "#222222" }, - [SchemeSel] = { "#eeeeee", "#005577" }, - [SchemeOut] = { "#000000", "#00ffff" }, +static const char *colors[SchemeLast][10] = { + /* fg bg */ + [SchemeNorm] = { "#bbbbbb", "#222222", "#222222" }, + [SchemeSel] = { "#eeeeee", "#005577", "#005577" }, + [SchemeOut] = { "#000000", "#00ffff", "#00ffff" }, + [SchemeHighlight] = {"#f1fa8c", "#596377", "#3E485B"}, + [SchemeHover] = {"#ffffff", "#353D4B", "#3E485B"}, + [SchemeGreen] = {"#ffffff", "#52E067", "#41b252"}, + [SchemeRed] = {"#ffffff", "#e05252", "#c24343"}, + [SchemeYellow] = {"#ffffff", "#e0c452", "#bca33f"}, + [SchemeBlue] = {"#ffffff", "#5280e0", "#3a62b3"}, + [SchemePurple] = {"#ffffff", "#9952e0", "#7439b0"}, }; /* -l option; if nonzero, dmenu uses vertical list with given number of lines */ static unsigned int lines = 0; +static unsigned int lineheight = 0; /* -h option; minimum height of a menu line */ +static unsigned int min_lineheight = 8; +static int sely = 0; +static int commented = 0; +static int animated = 0; + /* * Characters not considered part of a word while deleting words * for example: " /?\"&[]" diff --git a/dmenu.c b/dmenu.c index 65f25ce..a558fcb 100644 --- a/dmenu.c +++ b/dmenu.c @@ -26,7 +26,20 @@ #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) /* enums */ -enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */ +enum { + SchemeNorm, + SchemeFade, + SchemeHighlight, + SchemeHover, + SchemeSel, + SchemeOut, + SchemeGreen, + SchemeYellow, + SchemeBlue, + SchemePurple, + SchemeRed, + SchemeLast +}; /* color schemes */ struct item { char *text; @@ -37,6 +50,9 @@ struct item { static char text[BUFSIZ] = ""; static char *embed; static int bh, mw, mh; +static int dmx = 0; /* put dmenu at this x offset */ +static int dmy = 0; /* put dmenu at this y offset (measured from the bottom if topbar is 0) */ +static unsigned int dmw = 0; /* make dmenu this wide */ static int inputw = 0, promptw; static int lrpad; /* sum of left and right padding */ static size_t cursor; @@ -114,16 +130,117 @@ cistrstr(const char *s, const char *sub) } static int -drawitem(struct item *item, int x, int y, int w) -{ - if (item == sel) - drw_setscheme(drw, scheme[SchemeSel]); - else if (item->out) - drw_setscheme(drw, scheme[SchemeOut]); - else - drw_setscheme(drw, scheme[SchemeNorm]); - - return drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0); +drawitem(struct item *item, int x, int y, int w) { + int iscomment = 0; + if (item->text[0] == '>') { + if (item->text[1] == '>') { + iscomment = 3; + switch (item->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; + case 'h': + drw_setscheme(drw, scheme[SchemeHighlight]); + break; + 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 (item->text[0] == ':') { + iscomment = 2; + if (item == sel) { + switch (item->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; + case 'h': + drw_setscheme(drw, scheme[SchemeHighlight]); + break; + case 's': + drw_setscheme(drw, scheme[SchemeSel]); + break; + default: + drw_setscheme(drw, scheme[SchemeSel]); + iscomment = 0; + break; + } + } else { + drw_setscheme(drw, scheme[SchemeNorm]); + } + } else { + if (item == sel) + drw_setscheme(drw, scheme[SchemeSel]); + else if (item->out) + drw_setscheme(drw, scheme[SchemeOut]); + else + drw_setscheme(drw, scheme[SchemeNorm]); + } + + int temppadding; + temppadding = 0; + if (iscomment == 2) { + if (item->text[2] == ' ') { + temppadding = drw->fonts->h * 3; + animated = 1; + char dest[1000]; + strcpy(dest, item->text); + dest[6] = '\0'; + drw_text(drw, x, y, temppadding, lineheight, temppadding / 2.6, dest + 3, 0); + iscomment = 6; + drw_setscheme(drw, sel == item ? scheme[SchemeHover] : scheme[SchemeNorm]); + } + } + + char *output; + if (commented) { + static char onestr[2]; + onestr[0] = item->text[0]; + onestr[1] = '\0'; + output = onestr; + } else { + output = item->text; + } + + if (item == sel) + sely = y; + return drw_text( + drw, x + ((iscomment == 6) ? temppadding : 0), y, + commented ? bh : (w - ((iscomment == 6) ? temppadding : 0)), bh, + commented ? (bh - drw_fontset_getwidth(drw, (output))) / 2 : lrpad / 2, + output + iscomment, 0); } static void @@ -131,7 +248,7 @@ drawmenu(void) { unsigned int curpos; struct item *item; - int x = 0, y = 0, w; + int x = 0, y = 0, fh = drw->fonts->h, w; drw_setscheme(drw, scheme[SchemeNorm]); drw_rect(drw, 0, 0, mw, mh, 1, 1); @@ -148,7 +265,7 @@ drawmenu(void) curpos = TEXTW(text) - TEXTW(&text[cursor]); if ((curpos += lrpad / 2 - 1) < w) { drw_setscheme(drw, scheme[SchemeNorm]); - drw_rect(drw, x + curpos, 2, 2, bh - 4, 1, 0); + drw_rect(drw, x + curpos, 2 + (bh - fh) / 2, 2, fh - 4, 1, 0); } if (lines > 0) { @@ -609,6 +726,7 @@ setup(void) /* calculate menu geometry */ bh = drw->fonts->h + 2; + bh = MAX(bh,lineheight); /* make a menu line AT LEAST 'lineheight' tall */ lines = MAX(lines, 0); mh = (lines + 1) * bh; #ifdef XINERAMA @@ -637,9 +755,9 @@ setup(void) if (INTERSECT(x, y, 1, 1, info[i])) break; - x = info[i].x_org; - y = info[i].y_org + (topbar ? 0 : info[i].height - mh); - mw = info[i].width; + x = info[i].x_org + dmx; + y = info[i].y_org + (topbar ? dmy : info[i].height - mh - dmy); + mw = (dmw>0 ? dmw : info[i].width); XFree(info); } else #endif @@ -647,9 +765,9 @@ setup(void) if (!XGetWindowAttributes(dpy, parentwin, &wa)) die("could not get embedding window attributes: 0x%lx", parentwin); - x = 0; - y = topbar ? 0 : wa.height - mh; - mw = wa.width; + x = dmx; + y = topbar ? dmy : wa.height - mh - dmy; + mw = (dmw>0 ? dmw : wa.width); } promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; inputw = MIN(inputw, mw/3); @@ -689,7 +807,8 @@ setup(void) static void usage(void) { - fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" + fputs("usage: dmenu [-bfiv] [-l lines] [-h height] [-p prompt] [-fn font] [-m monitor]\n" + " [-x xoffset] [-y yoffset] [-z width]\n" " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr); exit(1); } @@ -717,6 +836,16 @@ main(int argc, char *argv[]) /* these options take one argument */ else if (!strcmp(argv[i], "-l")) /* number of lines in vertical list */ lines = atoi(argv[++i]); + else if (!strcmp(argv[i], "-x")) /* window x offset */ + dmx = atoi(argv[++i]); + else if (!strcmp(argv[i], "-y")) /* window y offset (from bottom up if -b) */ + dmy = atoi(argv[++i]); + else if (!strcmp(argv[i], "-z")) /* make dmenu this wide */ + dmw = atoi(argv[++i]); + else if (!strcmp(argv[i], "-h")) { /* minimum height of one menu line */ + lineheight = atoi(argv[++i]); + lineheight = MAX(lineheight, min_lineheight); + } else if (!strcmp(argv[i], "-m")) mon = atoi(argv[++i]); else if (!strcmp(argv[i], "-p")) /* adds prompt to left of input field */ @@ -752,6 +881,9 @@ main(int argc, char *argv[]) die("no fonts could be loaded."); lrpad = drw->fonts->h; + if (lineheight == -1) + lineheight = drw->fonts->h * 2.5; + #ifdef __OpenBSD__ if (pledge("stdio rpath", NULL) == -1) die("pledge");