summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/dmenu/dmenu.c76
-rw-r--r--core/dwm/config.def.h19
-rw-r--r--core/dwm/config.mk2
-rw-r--r--core/dwm/dwm.c111
4 files changed, 158 insertions, 50 deletions
diff --git a/core/dmenu/dmenu.c b/core/dmenu/dmenu.c
index 6ca6db6..5769e19 100644
--- a/core/dmenu/dmenu.c
+++ b/core/dmenu/dmenu.c
@@ -33,9 +33,10 @@
enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */
struct item {
- char *text;
- struct item *left, *right;
- int out;
+ char *text;
+ struct item *left, *right;
+ int out;
+ int distance;
};
static char text[BUFSIZ] = "";
@@ -85,17 +86,57 @@ fuzzy(const char *text, const char *pattern)
return 1;
}
+static int
+levenshtein(const char *s1, const char *s2)
+{
+ size_t len1 = strlen(s1), len2 = strlen(s2);
+ size_t i, j;
+ int *v0 = ecalloc(len2 + 1, sizeof *v0);
+ int *v1 = ecalloc(len2 + 1, sizeof *v1);
+
+ for (j = 0; j <= len2; j++)
+ v0[j] = j;
+ for (i = 0; i < len1; i++) {
+ v1[0] = i + 1;
+ for (j = 0; j < len2; j++) {
+ int cost = tolower((unsigned char)s1[i]) == tolower((unsigned char)s2[j]) ? 0 : 1;
+ v1[j + 1] = MIN(MIN(v1[j] + 1, v0[j + 1] + 1), v0[j] + cost);
+ }
+ memcpy(v0, v1, (len2 + 1) * sizeof *v0);
+ }
+ i = v0[len2];
+ free(v0);
+ free(v1);
+ return i;
+}
+
static void
appenditem(struct item *item, struct item **list, struct item **last)
{
- if (*last)
- (*last)->right = item;
- else
- *list = item;
+ struct item *i;
- item->left = *last;
- item->right = NULL;
- *last = item;
+ if (!*list) {
+ item->left = item->right = NULL;
+ *list = *last = item;
+ return;
+ }
+
+ for (i = *list; i && item->distance >= i->distance; i = i->right)
+ ;
+ if (!i) {
+ (*last)->right = item;
+ item->left = *last;
+ item->right = NULL;
+ *last = item;
+ } else {
+ item->right = i;
+ item->left = i->left;
+ if (i->left)
+ i->left->right = item;
+ else
+ *list = item;
+ i->left = item;
+ }
}
static void
@@ -261,11 +302,15 @@ match(void)
matches = matchend = NULL;
for (item = items; item && item->text; item++) {
- for (i = 0; i < tokc; i++)
+ int distance = 0;
+ for (i = 0; i < tokc; i++) {
if (!fuzzy(item->text, tokv[i]))
break;
+ distance += levenshtein(item->text, tokv[i]);
+ }
if (i != tokc)
continue;
+ item->distance = distance;
appenditem(item, &matches, &matchend);
}
curr = sel = matches;
@@ -553,11 +598,12 @@ readstdin(void)
}
if (line[len - 1] == '\n')
line[len - 1] = '\0';
- if (!(items[i].text = strdup(line)))
- die("strdup:");
+ if (!(items[i].text = strdup(line)))
+ die("strdup:");
- items[i].out = 0;
- }
+ items[i].out = 0;
+ items[i].distance = 0;
+ }
free(line);
if (items)
items[i].text = NULL;
diff --git a/core/dwm/config.def.h b/core/dwm/config.def.h
index 394937d..9707ffc 100644
--- a/core/dwm/config.def.h
+++ b/core/dwm/config.def.h
@@ -71,6 +71,8 @@ static const char *screenshotcmd[] = { "flameshot", "gui", NULL };
static const char *mediaplaypause[] = { "playerctl", "play-pause", NULL };
static const char *medianext[] = { "playerctl", "next", NULL };
static const char *mediaprev[] = { "playerctl", "previous", NULL };
+static const char *calendarcmd[] = { "/bin/sh", "-c", "st -e sh -c 'cal -3 | less'", NULL };
+static const char *dunstlogcmd[] = { "/bin/sh", "-c", "st -e sh -c 'less -+F \"$HOME/.cache/dunst/dunst.log\"'", NULL };
static const char *powermenucmd[] = { "/bin/sh", "-c", "power-menu.sh", NULL };
static const char *steamcmd[] = { "/bin/sh", "-c", "steam-dmenu.sh", NULL };
@@ -125,14 +127,15 @@ static const Key keys[] = {
/* button definitions */
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
static const Button buttons[] = {
- /* click event mask button function argument */
- { ClkLtSymbol, 0, Button1, setlayout, {0} },
- { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
- { ClkWinTitle, 0, Button2, zoom, {0} },
- { ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
- { ClkClientWin, MODKEY, Button1, movemouse, {0} },
- { ClkClientWin, MODKEY, Button2, togglefloating, {0} },
- { ClkClientWin, MODKEY, Button3, resizemouse, {0} },
+ /* click event mask button function argument */
+ { ClkLtSymbol, 0, Button1, setlayout, {0} },
+ { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
+ { ClkWinTitle, 0, Button2, zoom, {0} },
+ { ClkStatusText, 0, Button1, clickstatus, {0} },
+ { ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
+ { ClkClientWin, MODKEY, Button1, movemouse, {0} },
+ { ClkClientWin, MODKEY, Button2, togglefloating, {0} },
+ { ClkClientWin, MODKEY, Button3, resizemouse, {0} },
{ ClkTagBar, 0, Button1, view, {0} },
{ ClkTagBar, 0, Button3, toggleview, {0} },
{ ClkTagBar, MODKEY, Button1, tag, {0} },
diff --git a/core/dwm/config.mk b/core/dwm/config.mk
index b469a2b..6821465 100644
--- a/core/dwm/config.mk
+++ b/core/dwm/config.mk
@@ -23,7 +23,7 @@ FREETYPEINC = /usr/include/freetype2
# includes and libs
INCS = -I${X11INC} -I${FREETYPEINC}
-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
+LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lmpdclient
# flags
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
diff --git a/core/dwm/dwm.c b/core/dwm/dwm.c
index 4adbf21..fc150c0 100644
--- a/core/dwm/dwm.c
+++ b/core/dwm/dwm.c
@@ -47,6 +47,7 @@
#include <X11/extensions/Xinerama.h>
#endif /* XINERAMA */
#include <X11/Xft/Xft.h>
+#include <mpd/client.h>
#include "drw.h"
#include "util.h"
@@ -249,6 +250,7 @@ static void zoom(const Arg *arg);
static void clickstatus(const Arg *arg);
static void getcpu(char *buf, size_t len);
static void getram(char *buf, size_t len);
+static void getmusic(char *buf, size_t len);
static void gettime(char *buf, size_t len);
static void getdunst(char *buf, size_t len);
@@ -286,7 +288,7 @@ static Drw *drw;
static Monitor *mons, *selmon;
static Window root, wmcheckwin;
-enum { SNoti, SCPU, SRAM, STime, SPower, StatusLast };
+enum { SNoti, SCPU, SRAM, SMusic, STime, SPower, StatusLast };
typedef struct {
char text[64];
@@ -502,8 +504,10 @@ buttonpress(XEvent *e)
}
for (i = 0; i < LENGTH(buttons); i++)
if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button
- && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state))
- buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
+ && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state))
+ buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg :
+ click == ClkStatusText && buttons[i].arg.i == 0 ? &arg :
+ &buttons[i].arg);
}
void
@@ -765,13 +769,16 @@ void
drawbar(Monitor *m)
{
int x, w, tw = 0;
- int boxs = drw->fonts->h / 9;
- int boxw = drw->fonts->h / 6 + 2;
+ int boxs = drw->fonts->h / 9;
+ int boxw = drw->fonts->h / 4 + 3;
unsigned int i, occ = 0, urg = 0;
Client *c;
- if (!m->showbar)
- return;
+ if (!m->showbar)
+ return;
+
+ drw_setscheme(drw, scheme[SchemeNorm]);
+ drw_rect(drw, 0, 0, m->ww, bh - 3, 1, 1);
/* draw status first so it can be overdrawn by tags later */
if (m == selmon) { /* status is only drawn on selected monitor */
@@ -783,7 +790,7 @@ drawbar(Monitor *m)
continue;
w = TEXTW(statusitems[i].text);
statusitems[i].width = w;
- drw_text(drw, m->ww - tw - w, 0, w, bh, 0,
+ drw_text(drw, m->ww - tw - w, 0, w, bh - 3, 0,
statusitems[i].text, 0);
tw += w;
}
@@ -797,11 +804,9 @@ drawbar(Monitor *m)
}
x = 0;
for (i = 0; i < LENGTH(tags); i++) {
- if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i))
- continue;
w = TEXTW(tags[i]);
drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);
- drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i);
+ drw_text(drw, x, 0, w, bh - 3, lrpad / 2, tags[i], urg & 1 << i);
if (occ & 1 << i)
drw_rect(drw, x + boxs, boxs, boxw, boxw,
m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
@@ -810,20 +815,29 @@ drawbar(Monitor *m)
}
w = TEXTW(m->ltsymbol);
drw_setscheme(drw, scheme[SchemeNorm]);
- x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
-
- if ((w = m->ww - tw - x) > bh) {
- if (m->sel) {
- drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
- drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
- if (m->sel->isfloating)
- drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0);
- } else {
- drw_setscheme(drw, scheme[SchemeNorm]);
- drw_rect(drw, x, 0, w, bh, 1, 1);
- }
- }
- drw_map(drw, m->barwin, 0, 0, m->ww, bh);
+ x = drw_text(drw, x, 0, w, bh - 3, lrpad / 2, m->ltsymbol, 0);
+
+ if ((w = m->ww - tw - x) > bh) {
+ if (m->sel) {
+ int tx = x + (w - TEXTW(m->sel->name)) / 2;
+ int twid = TEXTW(m->sel->name);
+ drw_setscheme(drw, scheme[SchemeNorm]);
+ drw_text(drw, tx, 0, twid, bh - 3, lrpad / 2, m->sel->name, 0);
+ if (m == selmon) {
+ drw_setscheme(drw, scheme[SchemeSel]);
+ for (i = 0; i < 3; i++)
+ drw_rect(drw, tx - i, 0, twid + 2 * i, bh - 3, 0, 1);
+ }
+ if (m->sel->isfloating)
+ drw_rect(drw, tx + boxs, boxs, boxw, boxw, m->sel->isfixed, 0);
+ } else {
+ drw_setscheme(drw, scheme[SchemeNorm]);
+ drw_rect(drw, x, 0, w, bh - 3, 1, 1);
+ }
+ }
+ drw_setscheme(drw, scheme[SchemeSel]);
+ drw_rect(drw, 0, bh - 3, m->ww, 3, 1, 1);
+ drw_map(drw, m->barwin, 0, 0, m->ww, bh);
}
void
@@ -1681,7 +1695,7 @@ setup(void)
if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
die("no fonts could be loaded.");
lrpad = drw->fonts->h;
- bh = drw->fonts->h + 2;
+ bh = drw->fonts->h + 8;
updategeom();
/* init atoms */
utf8string = XInternAtom(dpy, "UTF8_STRING", False);
@@ -2201,6 +2215,47 @@ getram(char *buf, size_t len)
}
static void
+getmusic(char *buf, size_t len)
+{
+ struct mpd_connection *conn = mpd_connection_new(NULL, 0, 30000);
+ if (!conn || mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) {
+ if (conn)
+ mpd_connection_free(conn);
+ buf[0] = '\0';
+ return;
+ }
+ struct mpd_status *status = mpd_run_status(conn);
+ if (!status) {
+ mpd_connection_free(conn);
+ buf[0] = '\0';
+ return;
+ }
+ enum mpd_state state = mpd_status_get_state(status);
+ mpd_status_free(status);
+ if (state != MPD_STATE_PLAY) {
+ mpd_connection_free(conn);
+ buf[0] = '\0';
+ return;
+ }
+ struct mpd_song *song = mpd_run_current_song(conn);
+ if (!song) {
+ mpd_connection_free(conn);
+ buf[0] = '\0';
+ return;
+ }
+ const char *artist = mpd_song_get_tag(song, MPD_TAG_ARTIST, 0);
+ const char *title = mpd_song_get_tag(song, MPD_TAG_TITLE, 0);
+ if (title && artist)
+ snprintf(buf, len, "%s - %s", artist, title);
+ else if (title)
+ snprintf(buf, len, "%s", title);
+ else
+ buf[0] = '\0';
+ mpd_song_free(song);
+ mpd_connection_free(conn);
+}
+
+static void
gettime(char *buf, size_t len)
{
time_t now = time(NULL);
@@ -2254,6 +2309,7 @@ updatestatus(void)
getdunst(statusitems[SNoti].text, sizeof statusitems[SNoti].text);
getcpu(statusitems[SCPU].text, sizeof statusitems[SCPU].text);
getram(statusitems[SRAM].text, sizeof statusitems[SRAM].text);
+ getmusic(statusitems[SMusic].text, sizeof statusitems[SMusic].text);
gettime(statusitems[STime].text, sizeof statusitems[STime].text);
strncpy(statusitems[SPower].text, "⏻", sizeof statusitems[SPower].text);
@@ -2279,6 +2335,9 @@ clickstatus(const Arg *arg)
case STime:
spawn(&(Arg){ .v = calendarcmd });
break;
+ case SMusic:
+ spawn(&(Arg){ .v = mediaplaypause });
+ break;
case SPower:
spawn(&(Arg){ .v = powermenucmd });
break;