Remix.run Logo
90s_dev 3 days 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 3 days ago | parent | next [-]

Is 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 &");
          }
      }
  }
l-albertovich 2 days ago | parent | next [-]

Just 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/984fff0825ff8fe...

teo_zero 2 days ago | parent [-]

Sorry 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 "=".
l-albertovich 2 days ago | parent [-]

Oh no, I accidentally duplicated a function call while quickly rewriting the code for fun, what a terrible sin! (as a side note, I didn't even compile the code but I after quick check I don't see any notes on the man page that suggest that the accidental spurious repeated call could cause a problem)

I understand that you might not like that style but I think you're comming a bit too strong on this, especially considering how carefully I worded my message in terms of not hurting any feeling and being clear about this being MY preference.

I guess I shouldn't probably even answer but it saddens me and makes me a bit angry to get a reminder of why I don't usually participate in social media.

teo_zero 2 days ago | parent [-]

It was not my intention to make you sad or angry. I assure you that I have nothing against who uses a different coding style than mine. But consider that, just like you, I too have the right to tell the world what my preference is. Should I have softened my post with more "IMHO", "I feel", "my taste"? Probably, and I apologize.

Please don't stop participating in social media just because a halfwit like me hasn't agree with you once!

l-albertovich 2 days ago | parent [-]

You know it's not about the disagreement, it's about that toxic need to be a smart-ass that's so prevalent in social media (including this platform).

I would've loved to engage in a conversation about coding styles such as MISRA, CERTs or even the small tweaks such as the one that offended you so deeply but you wasted the opportunity to engage in a constructive convesartion and instead chose to nitpick the "reformatting" thing (seriously, I just moved things around slightly, it's the same thing) or the nothing-burger "bug"...

I don't know, maybe I misinterpreted you and if that's the case then I apologize but when I saw that code and felt the urge to play/doodle I thought it could be a fun way to connect with someone over something silly and I just got disappointed.

netrap 3 days ago | parent | prev [-]

I think this is more readable than with macros, but it might be a preference.

qsort 3 days ago | parent | next [-]

It'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.

3 days ago | parent | prev [-]
[deleted]
ajross 3 days ago | parent | prev | next [-]

Beware! 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 3 days ago | parent | next [-]

Yeah 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 3 days ago | parent | prev [-]

there 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 2 days ago | parent | next [-]

personally, 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.

ajross 2 days ago | parent | prev [-]

Interestingly I'd say a regular expression is absolutely not a DSL. It's sort of the opposite. A DSL is a tightly crafted interface for the configuration needed to support solutions to one somewhat unique problem. And the "trap" above is that the fact that the problem area is narrow means that only experts will really understand the DSL.

A regex is a tool implementing a solution (albeit a tightly crafted one) to an extremely broad set of problem areas. I mean, sure, in some sense it's a "DSL for string matching", but that doesn't really capture the essence of the DSL trap mentioned above. I mean, almost everyone needs string matching. So there's no trap: basically everyone knows regex syntax, even if they like to complain about it.

illegalmemory 3 days ago | parent | prev | next [-]

This is slightly bigger version I wrote around 13 years ago. :)

https://github.com/savitasinghvit/piwm/blob/master/piwm.c

klaussilveira 3 days ago | parent | prev [-]

That macro usage is sublime. Bravo!