1

I sometimes need to insert auto_incremented, numbered columns on other people's machines so I'm looking for a good way to do so without relying on any custom plugins, macros, or scripts; standard Vim commands only.

Example going from :

line a
line b
line c
...
line x
line y
line z

becoming then :

line a
line b
line 3 c
...
line 24 x
line 25 y
line z

doing something like

:3,25 something

If older versions of vim or vi have different ways of doing it I'd appreciate hearing about those solutions, too .

2
  • I would make user of seq unix program and virtual block mode.
    – bkdm
    Feb 28, 2020 at 20:28
  • Why not ... I also know how to use it as qa ; Y then p + ctrl-A *number times ... but I am looking for more logical way
    – francois P
    Feb 28, 2020 at 20:45

3 Answers 3

3

I’d actually do this using either filbranden’s answer or possibly a macro recording, but as you specifically requested an ex command that takes a 3,25 range, how about using a substitute command that uses as its replacement an expression that calls the line() function:

:3,25s/line \zs/\=line('.') . ' '

Or alternatively, a normal command using the same function:

:3,25norm!ea ^R=line('.')^M

Note that in the above, ^R is a literal CTRL-R character, and ^M is a CTRL-M. To insert them into the command line you need to type Ctrl-VCtrl-R and Ctrl-VEnter, respectively.

As D. Ben Knoble points out in the comments, you can avoid one of these special characters by "putting" the contents of the expression register, instead of inserting it:

:3,25norm! e"=line('.')^Mpi 
                           ^ note the space at the end of the line

Further details

First command:

  • :help /\zs
  • :help sub-replace-expression
  • :help line()

Second command:

  • :help :normal
  • :help i_CTRL-R
  • :help quote_"
2
  • Slightly less special characters: :norm! "=line('.')^MP. I was annoyed that :%put =line('.') didn't work, since :put's range is used to determine the line to put on (i.e., it only works on one line at a time)
    – D. Ben Knoble
    Mar 1, 2020 at 18:20
  • @D.BenKnoble Nice spot!
    – Rich
    Mar 1, 2020 at 23:15
3

I'd solve this using blockwise Visual mode and the g, Ctrl+A Visual mode command, that increments each line in the selection by a successive number, effectively creating an incrementing sequence. (See :help v_g_CTRL-A.)

This is the way I'd do it (especially if I was playing Vimgolf):

  1. /c<CR> to put the cursor on the c character at the start of the block.
  2. <C-V> to begin blockwise Visual mode.
  3. /y<CR> to move to the y character that ends the selection.
  4. I2 <Esc> to insert a 2 and a space on that column. Note that in blockwise Visual mode, this will insert the contents on every line of the selection. We're using 2 here instead of 3 because then we can increment every line of the selection and we don't need to shrink it on the second step.
  5. gv to restore the selection once again. This will keep the column of 2s selected.
  6. g<C-A> to increment them all.

Ta-da!

If you had inserted 3 instead of 2, you can still use this method, by skipping the increment on the first line. After gv you can use o to jump to the other end of the selection and then j to shrink the selection, removing the first line from it. After that, g<C-A> will increment from second to last line, achieving the desired result.

3

While I was experimenting with Rich's answer, I came up with

:global/./put =line('.')|join

Which can be shortened to :g/./pu =line('.')|j.

And yes, you can adjust the range of :global:3,25g/./pu =line('.')|j will work.

Note: this puts the line number at the beginning of the line, at which point you might as well work with :3,25s/^/\=line('.'). Since you need the number in the middle, you could do something like

:3,25global/./put =line('.')|join|normal! 0dawwp

But at this point, again, you might as well use something else.

Your Answer

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

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