diff --git a/README.md b/README.md index a92ecf7..63fe026 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on t ### Changelog: -2019-10-10 - Added mdpcontrol and scratchpad patches +2019-10-10 - Added mdpcontrol, scratchpad and spawn_cwd cpatches 2019-10-08 - Added columns layout and fakefullscreen patch @@ -214,6 +214,9 @@ Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on t - [sortscreens](https://www.mail-archive.com/hackers@suckless.org/msg09400.html) - this patch aims to address some inconsistencies when it comes to focusmon, tagmon and similar functionality by explicitly sorting screens left to right (or top to bottom in a vertical layout) + - [spawn_cwd](https://dwm.suckless.org/patches/spawn_cwd/) + - spawns programs from currently focused client's working directory + - [statusallmons](https://dwm.suckless.org/patches/statuspadding/) - this patch draws and updates the statusbar on all monitors diff --git a/dwm.c b/dwm.c index 5cf3675..1b9bbf5 100644 --- a/dwm.c +++ b/dwm.c @@ -45,6 +45,13 @@ #include "drw.h" #include "util.h" +#if SPAWNCMD_PATCH +#include +#include +#include +#define SPAWN_CWD_DELIM " []{}()<>\"':" +#endif // SPAWNCMD_PATCH + /* macros */ #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) @@ -2815,6 +2822,40 @@ spawn(const Arg *arg) if (fork() == 0) { if (dpy) close(ConnectionNumber(dpy)); + #if SPAWNCMD_PATCH + if (selmon->sel) { + const char* const home = getenv("HOME"); + assert(home && strchr(home, '/')); + const size_t homelen = strlen(home); + char *cwd, *pathbuf = NULL; + struct stat statbuf; + + cwd = strtok(selmon->sel->name, SPAWN_CWD_DELIM); + /* NOTE: strtok() alters selmon->sel->name in-place, + * but that does not matter because we are going to + * exec() below anyway; nothing else will use it */ + while (cwd) { + if (*cwd == '~') { /* replace ~ with $HOME */ + if (!(pathbuf = malloc(homelen + strlen(cwd)))) /* ~ counts for NULL term */ + die("fatal: could not malloc() %u bytes\n", homelen + strlen(cwd)); + strcpy(strcpy(pathbuf, home) + homelen, cwd + 1); + cwd = pathbuf; + } + + if (strchr(cwd, '/') && !stat(cwd, &statbuf)) { + if (!S_ISDIR(statbuf.st_mode)) + cwd = dirname(cwd); + + if (!chdir(cwd)) + break; + } + + cwd = strtok(NULL, SPAWN_CWD_DELIM); + } + + free(pathbuf); + } + #endif // SPAWNCMD_PATCH setsid(); execvp(((char **)arg->v)[0], (char **)arg->v); fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]); diff --git a/patches.h b/patches.h index 52ac273..a87e293 100644 --- a/patches.h +++ b/patches.h @@ -334,6 +334,11 @@ */ #define SORTSCREENS_PATCH 0 +/* Spawns programs from currently focused client's working directory. + * https://dwm.suckless.org/patches/spawn_cwd/ + */ +#define SPAWNCMD_PATCH 0 + /* This patch draws and updates the statusbar on all monitors. * https://dwm.suckless.org/patches/statusallmons/ */