2

How do I numbers starting from 1 to a range of lines (thereby creating an ordered list)? For example, the following

foo
bar
baz

would turn into

1 foo
2 bar
3 baz

I know to use the visual block to insert 0 to each line and then gvg<c-a> to get the desired result, but somehow I found that inelegant (though it is looking better and better as I write this). Is there a better method, presumably one that accomplishes this in one step? Perhaps something with :'<,'>s/^/?

PS I know from this answer that I could use :'<,'>s/^/\=(line('.')-line("'<")+1)/, but that would be even clunkier (which is why my solution doesn't seem so bad now).

bongbang
  • 199
  • 6
  • 1
    This has some related info/links: https://vi.stackexchange.com/q/35186/10604 – D. Ben Knoble Dec 24 '21 at 02:32
  • 1
    g<C-A> in Visual mode was what I was going to suggest when I read the top of your question... So, yeah, I think that's pretty much the most straightforward way. – filbranden Dec 24 '21 at 04:29
  • I was thinking of a function Inc() that increments a variable and returns its previous value, so you could use \=Inc() on the replacement side. I thought of the advantage of that approach (over g<C-A> in Visual mode) and realized it could be used to number non-contiguous lines, if used with :g. Then I looked at Ben's linked question, and noticed I answered with something to that same effect, but without the need of a helper, just using the | let a += 1 be part of what :g executes... So, in effect, that answer is what I'd suggest here. – filbranden Dec 24 '21 at 06:28
  • 1
    While the questions are not exactly the same, I think the answers for that one fit pretty much perfectly for this question. I'd be willing to mark it as a duplicate. – filbranden Dec 24 '21 at 06:29

1 Answers1

3

If you're on linux, you could filter the text through the external command nl to 'number the lines of files' with the --number-width=1 argument to ensure no leading whitespace:

:%!nl -w1

This outputs:

1   foo
2   bar
3   baz
.
.
.
10  more
11  things

Using the% sign means do the command for 'all lines in the buffer'. But you could also do 20,30!nl -w1 to do it only for lines 20-30, or you can visually select the region you care about, hit colon, and it will only apply to the selected lines - the :'<,'> is actually the lines between the two marks '< and '>. This means you can use any two marks: :'a,'b!nl -wq.

You can also specify the range with patterns like: :/pattern1/,/pattern2/!nl -w1

See :help cmdline-ranges for all the possibilities.

mattb
  • 1,111
  • 4
  • 15