onilog

posts tagged "hlwm"

Emacs-like WM

9 February 2012 0:00 AM (emacs | hlwm | guile)

I've been trying to get a more emacs~/~stumpwm-y feel in my window manager since I discovered that I can use xbindkeys to create emacs-like keybindings.

Today I got a little closer to that. I had some bash scripts that helped my xbindkeys setup with things like switching tags and moving windows, since that involved gathering some information and piping it into dmenu.

I figured out how I should do that, though. So now I've changed my ~/.xbindkeys.scm to include some functions to do that for me. You could look at it here.

I was having some trouble with calling dmenu though. I started with trying to use open-pipe with OPEN_BOTH argument so I could first write to and afterwards read from it. I didn't get it to work, I think it's because I didn't send an EOF at the end of the input, but I haven't found out how to do that yet. I ended up building a string that looks like echo 'value1\nvalue2\nvalue3\n' | dmenu and using that with open-input-pipe and using read-line on it. This looks like:

(define list '("value1" "value2" "value3"))
(let* ((file (open-input-pipe
              (string-append "echo '" (string-join list "\n") "' | dmenu")))
       (tag (read-line file)))
  (close-port file))

(display tag)

That will give the result of the dmenu call, it can be seen in the choose-tag function.

Of course you shouldn't forget that tag can still be nil or something that isn't in the list, so I use the string? and member functions to check whether I got something at all and if it exists in list.

Next up will be seeing what I can do with the information at hand. First idea is to reorder the tags and such as they do in emacs. I can (easily) keep track of the last picked value and I could keep an eye on the current value. Another idea, not directly related to all this is run-or-raise functionality, if I keep track what is started/moved where I might be able to do that as well, although that is not emacs related.

A strange HLWM configuration

29 January 2012 0:00 AM (guile | hlwm | scheme)

Heh, I only realized later that I'd posted snippets from my strange herbstluftwm config without explaining it. So you get lispy commands instead of bashy ones.

First, I'll say something to those people who don't know herbstluftwm, or its configuration method.

herbstluftwm uses a special program to send commands to the window manager while it's running. And the only configuration you can do is actually calling that program multiple times during startup. This may sound limiting in the way that I'm saying it, but it really isn't.

herbstluftwm calls the ~~/.config/herbstluftwm/autostart~ file. This file should contain some shell-executable code and should be executable by you. This means that it can be pretty much anything as long as it sends the right commands to the window manager.

By default a nice bash script is provided, as a starting point if you will. Now, as I'm almost certainly crazy (even just for trying this), I have replaced that original bash script with a guile script. Guile is the official GNU Extension Language and is an implementation of scheme, which is a lisp dialect. Since using emacs I have come to find lisp very interesting, and I've heard good things about guile, so I've always wanted to work with it more. Since I'm not really writing much at the moment, I'm looking for other ways to use it, like this one.

It wasn't all that hard, guile has some very nice and easy process management functions, and all I needed to do, really, was call the herbstclient program over and over again. So I wrote a function for that:

(define (hc command)
  "Calls the herbstclient program to execute a command"
  (system (string-append "herbstclient " command)))

This basically just calls the herbstclient program and appends the string command to it.

Then, there are some functions to help with setting up all the settings:

(define (keybind modkey key command)
  "Binds a keyboard key to a command, also prints it for testing
purposes"
  (display (string-append "keybind " modkey "-" key " " command "\n"))
  (hc (string-append "keybind " modkey "-" key " " command)))

(define (mousebind modkey button command)
  "Binds a mouse button to a command"
  (hc (string-append "mousebind " modkey "-" button " " command)))

(define (add-tag name)
  "Create a new tag"
  (hc (string-append "add " name)))

(define (set variable value)
  "Set the value of a variable"
  (hc (string-append "set " variable " " value)))

(define (unrule)
  "Clear all rules from memory"
  (hc "unrule -F"))

(define (rule spec)
  "Add a new rule"
  (hc (string-append "rule " spec)))

(define modkey "Mod4")

(define (create-tag name)
  (add-tag name)
  (keybind modkey name (string-append "use " name))
  (keybind modkey
           (string-append "Shift-" name)
           (string-append "move "  name)))

(define (dmenu-command fn nb nf)
  (string-append "dmenu_run -fn '" fn "' -nb '" nb "' -nf '" nf "'"))

(define (set-layout layout)
  (display (string-append "set_layout " layout "\n"))
  (hc (string-append "set_layout " layout)))

I've given them some docstrings, they should be fairly self explanatory that way. For the ones that don't have a docstring: create-tag creates a new tag (desktop) to be used, dmenu-command as a function I use to more easily change the values dmenu uses, set-layout sets a certain layout to be used and prints this for testing purposes.

This makes it easy to do many things, although having to do everything with strings is probably not very efficiƫnt. I'm still looking into creating a guile extension for herbstluftwm, but I have very little experience with IPCs, guile and X programming, so I'm not going very fast with that.

I hope that explains the lispy config snippets in my last post.