4 ms·
This is the entire source: #include <X11/Xlib.h> #include <stdlib.h> #define stk(s) XKeysymToKeycode(d, XStringToKeysym(s)) #define on(_, x
by 90s_dev 1y ago
This is the entire source:
#include <X11/Xlib.h>
#include <stdlib.h>
#define stk(s) XKeysymToKeycode(d, XStringToKeysym(s))
#define on(_, x) if (e.type == _) { x; }
#define map(k, x) if (e.xkey.keycode == stk(k)) { x; }
#define grab(...) const char *l[] = { __VA_ARGS__, 0 }; \
for (int i = 0; l[i]; i++) XGrabKey(d, stk(l[i]), Mod4Mask, r, 1, 1, 1);
int main() {
Display *d = XOpenDisplay(0); Window r = DefaultRootWindow(d); XEvent e;
XSelectInput(d, r, SubstructureRedirectMask);
grab("n", "q", "e");
while (!XNextEvent (d, &e)) {
on(ConfigureRequest, XMoveResizeWindow(d, e.xconfigure.window, 0, 0, e.xconfigure.width, e.xconfigure.height));
on(MapRequest, XMapWindow(d, e.xmaprequest.window);
XSetInputFocus(d, e.xmaprequest.window, 2, 0));
on(KeyPress, map("n", XCirculateSubwindowsUp(d, r); XSetInputFocus(d, e.xkey.window, 2, 0))
map("q", XKillClient(d, e.xkey.subwindow))
map("e", system("dmenu_run &")));
}
}
I have to say, I'm not usually a huge fan of C macros, but it works here so well, it feels so elegant and clean somehow.
- qsort 1y agoIs it really that much better than this: #include <X11/Xlib.h> #include <stdlib.h> int GetKeyCode(Display* d, char* s) { return XKeysymToKeycode(d, XStringToKeysym(s)); } int main() { Display* d = XOpenDisplay(0); Window r = DefaultRootWindow(d); XSelectInput(d, r, SubstructureRedirectMask); XGrabKey(d, GetKeyCode(d, "n"), Mod4Mask, r, 1, 1, 1); XGrabKey(d, GetKeyCode(d, "q"), Mod4Mask, r, 1, 1, 1); XGrabKey(d, GetKeyCode(d, "e"), Mod4Mask, r, 1, 1, 1); XEvent e; while (!XNextEvent(d, &e)) { switch (e.type) { case ConfigureRequest: XMoveResizeWindow(d, e.xconfigure.window, 0, 0, e.xconfigure.width, e.xconfigure.height); break; case MapRequest: XMapWindow(d, e.xmaprequest.window); break; case KeyPress: if (e.xkey.keycode == GetKeyCode(d, "n")) { XCirculateSubwindowsUp(d, r); XSetInputFocus(d, e.xkey.window, 2, 0); } if (e.xkey.keycode == GetKeyCode(d, "q")) XKillClient(d, e.xkey.subwindow); if (e.xkey.keycode == GetKeyCode(d, "e")) system("dmenu_run &"); } } }
- netrap 1y agoI think this is more readable than with macros, but it might be a preference.
- qsort 1y agoIt's also 50 bytes longer than the original. More LOC only because my Vim formats on save. Whenever somebody comes up with some big brain idea with macros, ORMs, DSLs, 180 IQ templates, language extensions that even Haskell nerds would say are too much, there's a good chance that the grugbrained version is just as readable, just as concise without going against the language. I'm this close to go completely nuts with this industry and commit to full butlerian jihad against anybody who goes higher in abstraction than ANSI C.
- deleted 1y ago[deleted]
- l-albertovich 1y agoJust for fun I reformatted it minimally in the conservative way I write code that is intended to be easy to read and understand to improve the odds of future contributors (or future me) introducing a bug in it due to misunderstanding it. It's painfully verbose but I think it's worth it considering that we're in 2025 and we're not limited to one character variable names. https://gist.github.com/leonardo-albertovich/984fff0825ff8feb6b390ac16847055f https://gist.github.com/leonardo-albertovich/984fff0825ff8fe...
- teo_zero 1y agoSorry but you didn't just reformatted it, you added new variables and return statements that were not in the original code (and even introduced bugs like row 41). As of short variable names, I'd argue that they are actually more readable than long ones when they're the iterator of a loop: while... XNextEvent(... &e) What else can "e" stand for in the body of this loop? Longer lifetimes and not-as-obvious scopes do deserve longer names. Finally, I strongly dislike this kind of reversed conditions: if (const == var) To paraphrase your own words, we're in 2025 and we should not be limited by our fear of forgetting one "=".
- illegalmemory 1y agoThis is slightly bigger version I wrote around 13 years ago. :) https://github.com/savitasinghvit/piwm/blob/master/piwm.c https://github.com/savitasinghvit/piwm/blob/master/piwm.c
- ajross 1y agoBeware! That's the DSL trap. It works here so well because it's limited to 20 lines and each macro does exactly what it needs to for the problem at hand. Take that DSL and use it over a year to write a bunch of code to do normal things as your app grows into its problem domain and spills over into a few more, and it melts. New developers will show up to onboard to your and be like "WTF is this 'on()' thing I'm looking at all over the place, and why isn't it used over here?!". Some enterprising developer will introduce "map2()" to indirect based on keysym and not keycode, etc... Domain Specific Languages are a mistake, almost every time they're used. And the only exceptions are the ones that grow into first class languages for well-defined problem areas (I'm thinking about things like VHDL or Mathematica here), and even there they tend not to be that much better than well-crafted domain-specific APIs in true programming languages (think numpy, pytorch, et. al.) DSLs: Just say no.
- 90s_dev 1y agoYeah exactly, this is why I stopped liking DSLs about 15 years ago, shortly after using Ruby extensively (probably not a coincidence) and converting to Clojure, where there was a large movement away from macros despite it being lisp. They're good in very isolated situations, and only when designed very carefully. This wm is quite possibly one of them; if you need more complexity than the macros here allow, and adding/changing macros only makes it worse, just use another wm.
- convolvatron 1y agothere really isn't a fundamental difference between DSLs and libraries for the points that you brought up. where it really starts to get sketchy is when you do really funny things with the base syntax (looking at you lisp and rust). if not well thought out they can be fragile, confusing, and a real burden for new contributors. I guess here's a question - do you consider regex libraries to be DSLs?
- silon42 1y agopersonally, I'd only consider a DSL to be good and useful if it can be implemented in different ways/languages, etc... It's not good if a DSL is language specific leaky abstraction. Regex is a good example of a DSL.
- klaussilveira 1y agoThat macro usage is sublime. Bravo!