6

I currently have this in my init file (key-chord-define-global "xf" 'find-file). Actually, xf and fx will trigger the find-file function. In fact, whatever the keychord I defined, it works whatever the order in which keys are pressed. So, just want to know if this is a normal behaviour, and if there is there a way to avoid fx to be considered as a keychord.

  • 2
    Key-chord bindings should be thought of as "two keys pressed at the same time", so order doesn't matter by design. – glucas Mar 8 '15 at 0:57
  • @glucas Thanks, I understand, having the possibility to set key-chord-two-keys-delay is not really suggesting an idea of "pressed at same time", then, made me think the order could matter. – Nsukami _ Mar 8 '15 at 12:13
  • Agreed. The delay is intended as a margin of error , I think. But with a slightly longer delay you could imagine having different bindings for different orders. I'm not aware of any way to configure that. – glucas Mar 8 '15 at 12:30
  • 1
    If you'd like to bind only a specific sequence, you should check out github.com/abo-abo/hydra. That package can be used to create 'temporary modes'. You could potentially bind x to start a hydra that binds f to your desired action and times out after a moment. Hydras can be configued so that keys not specifically bound keep their default behavior and exit the hydra -- there are a number of posts on oremacs.com that explain this better. :-) – glucas Mar 8 '15 at 15:58
8

If you look at the source for key-chord.el, when you add a binding for xf it is explicitly creating two bindings, one for xf and one for fx.

Just because this is the standard doesn't mean you have to adhere to it. You can modify the code that does this to only do one binding.

You'll just need to take a line out of key-chord-define.

Here is the function, and the line to remove:

(defun key-chord-define (keymap keys command)
  (if (/= 2 (length keys))
      (error "Key-chord keys must have two elements"))
  (let ((key1 (logand 255 (aref keys 0)))
        (key2 (logand 255 (aref keys 1))))
    (if (eq key1 key2)
        (define-key keymap (vector 'key-chord key1 key2) command)
      (define-key keymap (vector 'key-chord key1 key2) command)
      ;; just remove this line:
      (define-key keymap (vector 'key-chord key2 key1) command))))
  • 1
    thanks a lot for the advice, let's not adhere to the standard. – Nsukami _ Mar 9 '15 at 21:50
7

As mentioned in the comments, you may be able to achieve what you want using a different package like hydra. Here is an example that binds find-file to the key sequence x f with no modifiers.

(require 'hydra)

(defun x-hydra-pre ()
  (insert "x")
  (hydra-timeout 0.5))

(defhydra x-hydra (:body-pre x-hydra-pre
                   :color blue
                   :hint nil)
  ("f" (progn (zap-to-char -1 ?x) (ido-find-file))))

(global-set-key "x" #'x-hydra/body)

With this configuration, the key sequence xf (with no modifiers) will call ido-find-file. Typing an x followed by anything else will behave normally, and if you really need to type "xf" you can hit x and wait half a second for the hydra to time out before hitting the f.

So what's happening here:

  • x is globally bound to enable a hydra, which sets up a temporary key map.
  • The hydra has a :body-pre hook which runs when the hydra body is invoked. In this case it inserts an "x" and starts a timeout timer.
  • The hydra's temporary key map binds f to delete the "x" that was just inserted and instead find a file.
  • Any other key will exit the hydra and perform its normal action so you can just keep typing.
  • When the 0.5 second timer elapses, the hydra exits so its temporary key bindings go away.

(Note that at the time I tested this I had an error with hydra timeout support, but there is a fix available.)

  • 1
    This doesn't do the timeout thing though which makes it feel pretty awkward for normal typing, the other problem is that it gets weird once you do more than one such combination. – wasamasa Mar 8 '15 at 18:46
  • Agreed, just offering an alternative. With this approach you could make x a prefix for all sorts of commands and still type an x when necessary using xx. See also github.com/abo-abo/hydra/issues/34 re: timeout support. – glucas Mar 8 '15 at 18:48
  • 2
    Perhaps a better key to abuse this way is q, since it must almost always be followed by a u (in English). So make q start a hydra where u inserts qu; then make whatever other bindings you need. :) – glucas Mar 8 '15 at 18:50
  • @glucas given that timeouts are now supported (yay!), could you extend the answer to include them? – PythonNut Mar 9 '15 at 1:13
  • @PythonNut I'd like to, but I'm having some issues with hydra's timeout support. I just submitted a pull request for one problem, but it seems like there is something else that isn't behaving as I'd expect... – glucas Mar 9 '15 at 1:15
5

To get help with a function in emacs, type C-h f <function name>. In your case, e.g. key-chord-mode. This doesn't give you much info regarding your specific question, but the help buffer will contain a link to the file where the function is defined, in this case key-chord.el. In this file there is documentation in the comments at the beginning of the file, containing:

;; ########   Terminology   ########################################
;;
;; In this package, a "key chord" is two keys pressed simultaneously,
;; or a single key quickly pressed twice.
;;

And further down:

;; ########   Tips   ########################################
;;
...
;; Grep your own texts to verify that a combination is unusual.
;; And don't forget to check both permutations: "fg" and "gf".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.