2

I was using this to implement line duplication in emacs and decided to bind it to C-c d and it works without problems

What would be cooler though is if I can use C-c d do duplicate a line and then be able to make further duplications of this line by simply typing d. If I want 4 duplications, then the call would be C-c d, d, d, d.

What's the best way to achieve this? I assumed it would be activating a minor mode with C-c d that, when it starts, duplicates a line and then has the duplicate-line function bound to "d" in it's keymap.

The problem with this is that you have to disable the minor mode when a key is pressed that is not in it's keymap. Can this be done?

Or am I approaching this problem completely wrong?

1
  • Wow, two great answers from zck and glucas! I'm going with the one from zck though because it keeps me from having to add another dependency to my emacs config. That having been said though, I think hydra looks really cool and I could see it becoming a standard package in my config anyway.
    – flooose
    Commented Mar 12, 2017 at 11:45

2 Answers 2

1

You can use set-transient-map. First, make a sparse keymap with the binding you want for repetition:

(setq duplicate-line-keymap
      (let ((map (make-sparse-keymap)))
        (define-key map (kbd "d") #'my-duplicate-line)
        map))

Then, you can make your function, and at the end, call set-transient-map, and give it the keymap:

(defun my-duplicate-line ()
  (interactive)
  (duplicate-line)
  (set-transient-map duplicate-line-keymap))

Now, when you call #'my-duplicate-line, if you press "d" again, it'll repeat the call to #'my-duplicate-line, but if you press anything else, it'll do that behavior instead. You can put a message in the minibuffer to indicate what's going on:

(defun my-duplicate-line ()
  (interactive)
  (duplicate-line)
  (message "press d to duplicate again!")
  (set-transient-map duplicate-line-keymap))
4

This is exactly the use case for the hydra package, which you can install via package-install from melpa.

For example:

(defhydra hydra-duplicate-line ()
  "duplicate line"
  ("d" duplicate-line nil))

(global-set-key (kbd "C-c d") 'hydra-duplicate-line/duplicate-line)

This will bind C-c d to a command that will duplicate the current line and leave in a "temporary mode" where pressing d will duplicate the line again, and any other key will exit the hydra and do its usual function.

Hydra can do lots more, but this is a good place to start!

1
  • 1
    Note that hydra is creating transient maps using the mechanism described in @zck's answer. If this is a one-off scenario then you may not want to install a whole new package. That said, hydra makes it very convenient to create some quite sophisticated "temporary modes".
    – glucas
    Commented Mar 11, 2017 at 2:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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