key-bindings


XMonad: Is there a way to bind a simultaneously triggered keychord?


Is there a way to make simultaneous key presses into a keybinding, e.g. for the keys w, e, f, when pressed within 0.05 seconds of each other, to trigger a command?
To be more specific:
If w, e, f are pressed within 0.05 seconds of each other, then upon the pressing of the last one, XMonad should trigger said command. XMonad should also have intercepted the three keys so that they are not superfluously sent to the focused window.
Otherwise (if at least one of them are not pressed within the 0.05 second time period) XMonad should send the keys to the focused window as usual.
My goal in this is to use w, e, f to "Escape" into a vim-like "Normal Mode", a XMonad.Actions.Submap (submap).
Update with a failed method, in case anyone can see a way to fix it:
I attempted to implement this using submaps, so that, for example, if you pressed w you would end up in chord_mode_w, if you pressed e from there you would end up in chord_mode_we, and if you pressed f from there you would finally end up in normal_mode, for instance. The implementation was very messy: I included, in my main keybindings, something like:
("w", spawn "xdotool key <chord_mode_w_keybinding> ; sleep 0.05 ; xdotool key <abort_keybinding>")
(chord_mode_w_keybinding, chord_mode_w)
for detecting w (the rest would be similar), along with (incomplete) submaps such as:
chord_mode_w = submap . mkKeymap c $
[
("e", chord_mode_we )
, ("f", chord_mode_wf )
, (abort_keybinding, pasteString "w")
-- in order for the submap to not eat all other letters,
-- would need to include all mappings like:
, ("a", pasteString "wa")
, ("b", pasteString "wb")
...
]
chord_mode_we = submap . mkKeymap c $
[
("f", normal_mode )
, (abort_keybinding, pasteString "we")
-- in order for the submap to not eat all other letters,
-- would need to include all mappings like:
, ("a", pasteString "wea")
, ("b", pasteString "web")
...
]
chord_mode_wf = submap . mkKeymap c $
[
("e", normal_mode )
, (abort_keybinding, pasteString "wf")
-- in order for the submap to not eat all other letters,
-- would need to include all mappings like:
, ("a", pasteString "wfa")
, ("b", pasteString "wfb")
...
]
A complete implementation would evidently have been very messy, but in theory should have sent me to normal_mode if I pressed "wef" within 0.05 seconds of each other, aborting and typing out the characters otherwise. There were two problems, however:
pasteString (as well as the other paste functions in XMonad.Util.Paste) is too slow for normal typing
I would end up in normal_mode only a small fraction of the time even if I set the abort delay much higher. Not sure of the reason behind this.
(The reason I used pasteString when aborting instead of spawning another xdotool was that output of xdotool would re-trigger one of the chord_mode_w_keybinding, chord_mode_e_keybinding, chord_mode_f_keybinding, back in the main keybindings, sending me back to the chord modes indefinitely.)
http://xmonad.org/xmonad-docs/xmonad-contrib/XMonad-Actions-Submap.html
Submap really does do almost what you want (it gets you most of the way there) ... and I will suggest that you may want to change what you are trying to do, ever so slightly, and then Submaps handle it perfectly.
You can configure Submap to capture a w key event, and start waiting for an e which then waits for an f. I even tried this out, and confirmed that it works:
, ((0, xK_w), submap . M.fromList $
[ ((0, xK_e), submap . M.fromList $
[ ((0, xK_f), spawn "notify-send \"wef combo detected!\"" ) ])
])
However, the above is almost certainly not something you'd actually want to do... since it is now impossible to send a w keypress to a window (I had to disable that config before typing this answer, which required sending several w keypress events to the active window)
The behavior I saw just now when playing with this is: if I press w, xmonad traps that event (does not send it to the active window) and is now in a state where it is waiting for either e or something else ... if I press something else, xmonad is no longer in that state, but it does not "replay" those trapped events. So if I press w and then some other key which isn't e, the result is only that xmonad is back out of the state listening for keys in the submap. It does not ever allow a w through to the active window... which I found inconvenient.
Your options as I see it are:
1) settle for the initial keybinding having a modifier, so your multi-key command would be Mod4-w e f
2) find a way to hack the delay logic you described into the action in the submap
I started using a config like this, where I nest conceptually similar actions that are infrequently needed under a tree of nested submaps, analogous to what I pasted above. The root of that tree, however, always has a modifier, so it doesn't steal keypresses which I want to forward to the active window. I use Mod3-semicolon as the root of that tree, and then there are many unmodified keypresses which are just letters (they are mnemonics for the actions).
To me, this seems like a better solution, rather than waiting for a few hundred milliseconds, and then forwarding the events unless they matched. I feel like I would find that annoying, since it would delay any w keypress event...
YMMV, hope it helps someone

Related Links

Is there a move cursor to nearest '=' code navigation in IntelliJ?
Disabling Mousewheel Bind
Fish shell ESC/META keybinding with iterm2 on os x yosemite
XMonad: Is there a way to bind a simultaneously triggered keychord?
Simple key binding issue
unable to get C-PGUP or C-PGDOWN key codes in tmux
How do I override a default keybinding in LightTable?
Is it possible to change key bindings in Sublime Text dynamically from a plugin?
Ace Editor - Change CTRL+H keybinding
KeyBindings in Java stop working after component is remade
Tmux Scroll Up/Down Page using Ctrl-b and Ctrl-f
How to create key binding to set XML syntax?
How to bypass a bindkey directive in GNU screen?
XMonad keybindings doesn't work
Get file path + file name in a keybindings file in Sublime Text 2
GNU screen custom key bindings format

Categories

HOME
logging
autohotkey
primefaces
qemu
jenkins-pipeline
openacc
cxf
formatting
boxplot
arguments
ubuntu-14.04
checkpoint
flowtype
zabbix
browserstack
angularjs-ng-repeat
google-my-business-api
theory
activejdbc
point-of-sale
adroitlogic
captcha
fastreport
sha1
nsoperation
audio-streaming
gpo
hl7-fhir
pushbullet
inline-assembly
sqldependency
custom-fields
azure-table-storage
pypy
delphi-2010
intermec
blockly
ragel
flex3
gstreamer-1.0
extern
word-wrap
mockserver
aura-framework
mtm
text-formatting
evaluation
spring-cloud-bus
lucee
monaca
activesupport
chain
spring-social-twitter
ownership
optional-parameters
scikit-image
universe
mate-desktop
tinybox2
chomsky-normal-form
calc
dcast
ooad
methodology
github-for-mac
gitk
sparkcore
system.diagnostics
veeam
accpac
service-broker
dojox.grid
powershell-v1.0
windows-search
parallel-port
pidgin
nodeunit
mobile-robots
ironworker
pyxplot
wpd
pudb
nx
database-restore
nsregularexpression
correctness
netzke
nsscrollview
pdf-reader
nserror
parsec
motorola-droid
vectorwise
auto-compile
linq-to-mysql
large-data-volumes
tracd

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App