10

In Vim you can press . to repeat the latest change, including inserting text.

While in Emacs C-x z only repeats the last command. I am aware that macros can be used here, but more than often I realize that I need to re-insert the same text too late. When I need to re-insert it only one more time, defining a macro then is pointless.

Q: Is there a way to repeat the insertion of text inside of Emacs?

  • 1
    What is the "text" you want to repeat? Technically speaking, the last insertion is just the last character, which is probably not what you're after. So, how would you define a "text insertion" for your purpose? Clarifying it may also help you in finding ways to achieve it. – T. Verron Dec 2 '14 at 22:01
  • Hmm good question - how to define that last continuous buffer modification. Perhaps a buffer modification between two point moves which are not a result of a buffer modification (C-f, search, etc.)? If that makes any sense... – ooi Dec 2 '14 at 22:37
  • Clarify what you want with a recipe. There are many kinds of "insertion" (ways to insert text). Are you inserting interactively? If so, how? – Drew Dec 2 '14 at 22:59
  • Interactively. But ideally it wouldn't matter how or what. It's as if I forgot to start defining a macro. In which case the problem is when is that. Maybe some hook could be used. – ooi Dec 2 '14 at 23:35
  • 2
    How do you define 'last insert' in Emacs? Since there is no edit/command mode switch like in vi, how far in the history should we go? I usually just select "the last insert" (C-space, move the cursor, M-w to copy) and then C-y to paste as many time as needed. – Alain Dec 3 '14 at 0:00
7

dot-mode is a "minor mode to repeat typing or commands," and may do what you need. It basically just repeats the last insertions/deletions that you do. It is pretty similar to . in Vi(m).

  • 2
    What does it do? – Malabarba Dec 3 '14 at 0:00
  • 1
    Welcome to Emacs.SE. Right now, you're answer is closer to a comment than an answer. Could you please edit it to explain what dot-mode does and how it provides the functionality that OP is trying to get? – Dan Dec 3 '14 at 0:48
7

It's as if I forgot to start defining a macro

You could use kmacro-edit-lossage (C-x C-k l) for that: it allows you to view your 300 last keystrokes (including simple insertions), and edit them as a macro.

For simple usage, you would just locate the beginning of the insertion you want to repeat, delete all text from "Macro:" to that point, and press C-c C-c. Now you have a macro you can use to perform the same actions, as if you didn't forget to record it in the first place.

Sadly, this fails if the last 300 keystrokes include mouse clicks.

Edit: The following code changes it so that only the keys after the last mouse event are kept.

(defadvice recent-keys (after tv/recent-keys-no-mouse first ())
  "Return only the keys since the last mouse event"
  (let* ((vec ad-return-value)
         (lst (append vec nil))
         (nmax (length vec))
         (i (- nmax 1)))
    (while
        (and
         (>= i 0)
         (not
          (let ((mod (event-modifiers (elt vec i))))
            (or (memq 'click mod)
                (memq 'double mod)
                (memq 'triple mod)
                (memq 'drag mod)
                (memq 'down mod)))))
      (setq i (- i 1)))
    (setq ad-return-value (vconcat (nthcdr (+ i 1) lst) nil))))

(defun tv/kmacro-edit-lossage-no-mouse ()
  "Same as `kmacro-edit-lossage', but fallback if the keys contain mouse events.

Source: http://emacs.stackexchange.com/a/4071/184"
  (interactive)
  (ad-activate-regexp "tv/recent-keys-no-mouse")
  (call-interactively #'kmacro-edit-lossage)
  (ad-deactivate-regexp "tv/recent-keys-no-mouse"))

;; If you want this function to replace the default one, uncomment this line:
; (global-set-key (kbd "C-x C-k l") 'tv/kmacro-edit-lossage-no-mouse)
  • I do often scroll using the mouse, it would be cool to see how to remove those from macro. – ooi Dec 3 '14 at 18:19
  • Wow, this command would be useful if it didn't completely fail if the last 300 included mouse clicks. Maybe just don't include the clicks and let the user know instead of just refusing to work. – nanny Dec 3 '14 at 19:54
  • @nanny I added some elisp to enable a (imo) better fallback than just failing with an error message: with this function, only the keys after the last mouse event will be kept. Dropping the mouse events completely should be possible too, but the result of the macro would be somewhat unpredictable. – T. Verron Dec 3 '14 at 20:41
  • @ooi No idea if you got automatically pinged by the previous comment, so here is your ping too. – T. Verron Dec 3 '14 at 20:42
  • Thanks, I was working on the same thing. I think it may be possible to filter the args of edmacro-fix-menu-commands. It takes an optional argument which can ignore the mouse events. But I don't know enough about the advice system to get it to work. – nanny Dec 3 '14 at 20:44
4

I think dabbrev-expand function could do the trick. Let's suppose you've already typed some words: emacs, emotion, emoji, ... The next time you'll type a word beginning by 'em', you can hit M-/ and emacs will propose you to insert one of the already inserted words begining by 'em'. Keep hitting M-/ and emacs will show you 'emoji', then 'emotion, then ...

You may also have a look to repeat-complex-command. The popular example being: you want to repeat the command query-replace in many different buffers always using the same arguments, replace “pitt” by “patt”.

You run it once, go to a different window, and type C-x ESC ESC to run it again.

And to finish, may I suggest repeat-insert? This el file will help you to do insertion, using some kind of logic. It is more like, "reapeat last insertion, but for each iteration, the arguments will change.

This example could be found in the el file:

;; You can also iterate over lists:
;;   My desk is cluttered
;;   My desk is a real mess
;;   My desk is very hard to see
;;   My desk is buried
;;
;; from m-x insert-patterned
;;    ";;   My desk is %s"
;;    (cluttered "a real mess" "very hard to see" buried)

I hope that will help.

  • 1
    Maybe you can expand a little... – T. Verron Dec 2 '14 at 22:05
  • @T.Verron Done :) – Nsukami _ Dec 3 '14 at 0:43
  • 1
    Repeat-complex-command is like repeat (which the OP mentions), not really useful for text insertions. Repeat-insert needs to be thought of before inserting the text, just like a macro. But dabbrev-expand is a nice idea! – T. Verron Dec 3 '14 at 7:02

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.