# Add incrementing numbers to lines

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

• This has some related info/links: vi.stackexchange.com/q/35186/10604 Dec 24, 2021 at 2:32
• `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. 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. Dec 24, 2021 at 6:28
• 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. Dec 24, 2021 at 6:29

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.

• 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. 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. Dec 25, 2021 at 12:03