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).

4
  • 1
    This has some related info/links: vi.stackexchange.com/q/35186/10604
    – D. Ben Knoble
    Dec 24, 2021 at 2: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, 2021 at 4: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, 2021 at 6: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, 2021 at 6:29

1 Answer 1

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.

3
  • I'm not on Linux, but wouldn't that work on every line in the file instead of the selection? I want the numbers on only certain lines.
    – bongbang
    Dec 25, 2021 at 7:23
  • @bongbang Yes you're right about the % sign, but you can use a custom range as detailed in the update to the answer.
    – mattb
    Dec 25, 2021 at 12:03
  • 1
    See also this answer and its comments. Mar 2, 2023 at 20:37

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.