46

I was reading this article on how to create vi macros: vi sequence macro and I saw one useful macro to create a sequence in the buffer.

1.
2.
...
100.

In vi, the trick is that one can hit ctrl-a over a number and it will add one to it, so this made the macro easy. I want to be able to do the same thing in emacs.

11 Answers11

71

If you are using Emacs 23 (and maybe 22?), use kmacro-insert-counter which is bound to C-x C-k TAB by default. So for your example, you'd do:

C-x ( C-x C-k TAB . RET C-x )

So start macro, insert counter followed by '.', newline, end macro. Then C-x e e e e e e e etc. Or M-1 0 0 C-x e to get 100 of them.

EDIT:

Forgot to mention you can set the counter to an initial value also. For example to start at 1 instead of 0 do M-1 C-x C-k C-c.

And if you don't want the counter to increment at a particular point, prefix it with C-u. Of course the keystrokes are getting a bit ridiculous at this point, so I usually bind a key to insert-but-don't-increment.

viam0Zah
  • 25,949
  • 8
  • 77
  • 100
scottfrazer
  • 17,079
  • 4
  • 51
  • 49
  • 1
    Still relevant: `kmacro-set-counter C-x C-k C-c` `kmacro-add-counter C-x C-k C-a` `kmacro-insert-counter C-x C-k TAB` So the idea is, set the counter. Then define the macro and within the macro insert-and-increment the counter. Then repeatedly run the macro. This may have been obvious to other readers but I didn't initially get it. – Cheeso Jan 18 '17 at 21:49
  • Forgot that you can just hit `e` to repeat the macro after the initial `C-x e`. – young_souvlaki Sep 08 '20 at 23:56
62

Those who feel there are too many tricks to memorize might find acquiring some elisp more profitable:

M-: (dotimes (i 20) (insert (format "%2d.\n" (1+ i))))
huaiyuan
  • 26,129
  • 5
  • 57
  • 63
18

Emacs 23 supports elisp snippets in the replacement text of replace-regexp.

I frequently define keyboard macros that follow this pattern:

  • Copy a block of text
  • Navigate to a number that I want to increment in the copied block of text with isearch
  • Activate the mark and move the point to define a region encompassing the number
  • M-x replace-regexp
  • At the "Replace regexp" prompt, enter \([0-9]+\) to capture a group of one or more digits
  • At the "Replace regexp ([0-9]+) with:" prompt, enter \,(1+ \#1), where , indicates that an elisp form to substitute follows, 1+ is an increment function, and \#1 is the first captured match text, interpreted as a number.

After taking a minute to define the keyboard macro, this allows me to have almost the convenience of cutting and pasting to generate lots of blocks of almost-identical code, such as for case statements.

Note that this technique can be easily adapted to e.g. double numbers (\,(* 2 \#1)) or whatever. You can even use it to substitute the next element in an arbitrary sequence by using a combination of 'position and 'nth, but I won't go into that now :).

jlf
  • 3,461
  • 2
  • 18
  • 14
  • 1
    thanks for demonstrating how to use replace-regexp to substitute a counter for text – Noah Sussman Jun 18 '10 at 18:54
  • `\,(eval-expression)` is very neat in query replace regexps! I had to renumber a sequence of superscript numbers starting from 1. They were all in SMF `[sup]` tags, starting with 63. So I did this query replace regexp to start them from 1: `(default \[sup\][0-9]+\[\/sup\]`→ `[sup]\,(kmacro-insert-counter 1)[/sup]`. However, it replaced them with with something like [sup]New macro counter value: 1 (1)[/sup]00". How could I fix this (besides regexping that extra text out)? – Geremia Aug 26 '16 at 17:12
  • 1
    @Geremia: Here's what I had to do: `C`-`:` `(setq kmacro-counter 0)` and then: `\[sup\][0-9]+\[\/sup\]`→`[sup]\,(print (setq kmacro-counter (1+ kmacro-counter)))`. – Geremia Aug 26 '16 at 18:31
14

Since release 24.3 of Emacs (I believe actually since release 24.0), the keystroke sequence has been simplified:

<F3> <F3> . <ENTER> <F4>

Then repeating <F4> key will repeat the macro.

The trick is that, after having started a macro with <F3>, a second <F3> key press will insert the current value of the keyboard macro's counter into the buffer, and increments the counter by 1.

Other tricks:

  • <F3> C-u 2 <F3> . <ENTER> <F4> will increment with +2 (instead of +1)
  • C-u 100 <F3> <F3> . <ENTER> C-u 50 <F4> will start at 100 and finish at 149
  • C-x C-k C-f %03d <ENTER> <F3> <F3> . <ENTER> <F4> will pad with zero like "000"

Source: Keyboard Macro Counter section in Emacs manual.

thdox
  • 1,555
  • 2
  • 17
  • 18
  • 2
    To preset the counter, you just need a numeric prefix arg. e.g.: `C-u 100 . RET `. A prefix argument to `` says how many times to repeat the macro (inclusive of recording), so to count from 100 to 149 immediately you could finish that with `C-u 50 ` instead of just ``. – phils Aug 16 '14 at 23:54
  • Thanks phils. I improved my answer (and knowledge) with your comments. – thdox Aug 19 '14 at 20:29
  • 1
    `F3 F3 X F4` is a **huge** improvement over `C-x ( C-x C-k TAB X C-x )` in terms of ease of use for a throwaway-macro - and now I don't have to come here because I forgot the key acrobatics combo. I hope this answer will bubble up to the top, where it belongs. – Evgeniy Berezovsky Mar 25 '15 at 01:46
  • Hasn't this been in Emacs since at least Emacs 23? Because I distinctly remember this being a thing in Emacs 23. But I could be wrong. – Haakon Løtveit Mar 21 '16 at 22:51
8

Beside scottfrazer's answer, there is another way to create a sequence of numbers with CUA mode which may help you a lot when editing existing content. See Mark Mansour's screencast on Emacs Column Editing from position 2:30.

Community
  • 1
  • 1
viam0Zah
  • 25,949
  • 8
  • 77
  • 100
3

If you turn on the CUA minor mode (cua-mode), you can select a column of text and then fill it with a sequence of numbers using cua-sequence-rectangle (bound to M-n by default).

This is the same thing mentioned in the video Török Gábor linked to, but now it's written down here so you don't have to watch the whole video unless you want to. It is a good video.

Eric Anderson
  • 1,968
  • 2
  • 15
  • 19
  • 4
    It's also worth noting that these days you don't need `cua-mode`* to number a rectangle -- since 24.1 there's a regular rectangle operation `rectangle-number-lines` bound to `C-x r N`. (* or `cua-selection-mode`, which is definitely the preferable option for those who don't use `cua-mode` as standard.) – phils Jan 28 '14 at 20:04
  • 2
    I may as well link to [emacs string-insert-rectangle vector of numbers?](http://stackoverflow.com/a/9932745/324105) as well. – phils Jan 29 '14 at 03:19
1

Here is an extension that may help.

nedblorf
  • 5,135
  • 4
  • 27
  • 28
1

There's also:

C-u M-! jot -s '.C-q C-j' 10

It's not pure elisp, but has the same effect. You could write a named macro to run it for you.

Adobe
  • 12,967
  • 10
  • 85
  • 126
Kirk Strauser
  • 30,189
  • 5
  • 49
  • 65
  • 'jot' and 'seq' do the same thing for these purposes. If you're on Unix, you almost surely have at least one of them installed.q – Kirk Strauser Oct 04 '09 at 17:44
1

You can use shell-command-on-region otherwise :

C-u M-! seq 1 100|xargs -I{} echo {}"."
Adobe
  • 12,967
  • 10
  • 85
  • 126
antham
  • 408
  • 4
  • 15
0

Here's a simple defun for this:

(defun insert-range (START END &optional STEP FORMAT)
  "Inserts a range of integers from START to END with STEP (default to 1)
in a given format (default to \"\\n%d\")"
  (interactive
   (list (read-number "Start: " 1)
         (read-number "End: "  10)
         (read-number "Step: "  1)
         (read-string "Format (default to \"\\n%d\"): " nil nil "\n%d") ))
  (dotimes (i (1+ (/ (- END START) STEP)))
    (insert (format FORMAT (+ START (* i STEP))))
  )
)
Adobe
  • 12,967
  • 10
  • 85
  • 126
0

You can set up a sequence of counters starting from START and with step STEP using

C-x C-k C-c START RET F3 C-u STEP F3 F4,

where is anything else you want to include in your macro. This inserts the first counter, with value START. Afterwards, F4 will insert the next value in the sequence. If you skip the setting of START (i.e. if you do just F3 C-u STEP F3 F4) it'll start from 0. You can use C-x C-k C-f to specify the format of the counter.

You can also insert N elements of the sequence starting at START and with step STEP using huaiyuan's method: type M-: and enter

(dotimes (i N) (insert (format "%2d.\n" (+ START (* i STEP)))))
Arch Stanton
  • 382
  • 5
  • 14