baskerville/sxhkd

Modal Keybind Support

leath-dub opened this issue · 8 comments

Just opening an issue about this as I think I might try implement this - would be interested if anyone had done this yet ?

When I mean modal key binds I am referring to a way for you to define specific states for key binds to work in. For example you may have a window move state that allows you to press h,j,k,l to move windows around, to get out of the state you could hit Esc (like vim) or maybe this could be bound also.

Update on this I have a POC it basically adds a new field to the hokey_t struct called modal_info_t, this just has info on whether you are setting a mode or conditionally running a command if the mode is set.

The syntax right now is as such. I did it like this as it feels right that the guard for whether it is run is just in front of the command that you want to run.

# Enable mode named "normal"
alt + i
    ^normal [can also run command here (not sure why you'd wan't but eyy)]

# Run the command only if in normal mode
alt + t
    ?normal xterm

Kind of a hack in the way this is implemented means you can reset to the "empty" mode -- just an empty string or first char as '\0' byte, like this:


# Reset mode
alt + r; m
    ^

Edit: Personally I think this simple state approach is all you need. Like already with this we can have

Escape; @Escape
    ^

to reset like in vim

and

alt + i
    ^change_window

to set the "change_window" mode

Should I make a pr ? or would it get rejected ?

I think you could use : for that.

# resize window
alt + m : {h,j,k,l} {_, shift+}
  i3-msg resize {shrink width, grow height, shrink height, grow width} {20, 10} px

# audio
super + o: {j, k}
  pactl set-sink-volume @DEFAULT_SINK@ {-1%, +1%}
super + o: m
  pactl set-sink-mute @DEFAULT_SINK@ toggle

What would be really cool is being able to remap your keys in a specific mode.

super + m: remap({h,j,k,l}, {Left, Down, Up, Right})

That way you can, sort of, re-invent vim-motions or your own motions that can be used in a browser's text area or a Github's comment input for that matter.

Just to be clear, this is doable by using something like xdotool, but there are two reasons why you wouldn't use it:

  1. It simply doesn't work well: I don't know what's happening but it takes too long for the xdotool to run, and some times it gets repeated more than intended.
  2. It'll be way easier and cleaner if it was a built-in feature.

I think you could use : for that.

# resize window
alt + m : {h,j,k,l} {_, shift+}
  i3-msg resize {shrink width, grow height, shrink height, grow width} {20, 10} px

# audio
super + o: {j, k}
  pactl set-sink-volume @DEFAULT_SINK@ {-1%, +1%}
super + o: m
  pactl set-sink-mute @DEFAULT_SINK@ toggle

What would be really cool is being able to remap your keys in a specific mode.

super + m: remap({h,j,k,l}, {Left, Down, Up, Right})

That way you can, sort of, re-invent vim-motions or your own motions that can be used in a browser's text area or a Github's comment input for that matter.

Just to be clear, this is doable by using something like xdotool, but there are two reasons why you wouldn't use it:

  1. It simply doesn't work well: I don't know what's happening but it takes too long for the xdotool to run, and some times it gets repeated more than intended.
  2. It'll be way easier and cleaner if it was a built-in feature.

So the ':' allows for different command depending on the lhs ?

I am going back to this today and I think I can get the modes working well by having a check before grabbing keys. This means there wont be conflicts (I assume thats what ':' is for ?)

The character : takes whatever keybinding that comes after it and make it, say, exclusive to the keybinding before it(:).

If you consider those as modes, then yes, I think this will solve your issue.

The character : takes whatever keybinding that comes after it and make it, say, exclusive to the keybinding before it(:).

If you consider those as modes, then yes, I think this will solve your issue.

Yeah I think this is pretty much what I needed. Thanks !

im gonna close this

for that usecase with remaps id probably look into using evdev, would be probably less overhead than using xserver