Macro for making numbered lists in vim?
Often times it seems I have a list of items, and I need to add numbers in front of them. For example:
Item one
Item two
Item three
Which should be:
1. Item one
2. Item two
3. Item three
In vim, I can press I
in edit mode, insert "1.", hit escape. Then I go to the next line, press .
, and then ^A
to increment the number开发者_开发问答. This seems hugely inefficient... how would I make a macro so that I can go to the next line, and insert a number at the beginning which is one greater than the line before?
You can easily record a macro to do it.
First insert 1.
at the start of the first line (there are a couple of spaces after the 1.
but you can't see them).
Go to the start of the second line and go into record mode with qa
.
Press the following key sequence:
i # insert mode
<ctrl-Y><ctrl-Y><ctrl-Y> # copy the first few characters from the line above
<ESC> # back to normal mode
| # go back to the start of the line
<ctrl-A> # increment the number
j # down to the next line
q # stop recording
Now you can play back the recording with @a
(the first time; for subsequent times, you can do @@
to repeat the last-executed macro) and it will add a new incremented number to the start of each line.
Select your lines in visual mode with: V
, then type:
:'<,'>s/^\s*\zs/\=(line('.') - line("'<")+1).'. '
Which is easy to put in a command:
command! -nargs=0 -range=% Number <line1>,<line2>s/^\s*\zs/\=(line('.') - <line1>+1).'. '
Here's an easy way, without recording a macro:
Make a blockwise, visual selection on the first character of each list item:
^<C-V>2j
Insert a
0.
at the beginning of these lines:I0. <Esc>
Re-select the visual selection (which is now all of the
0
s) withgv
and increment them as a sequenceg<C-A>
:gvg<C-A>
The entire sequence: ^<C-V>2jI0. <Esc>gvg<C-A>
.
A recording of the process in action.
There are also some plugins for doing this type of work if you have to do it on occasion:
http://vim.sourceforge.net/scripts/script.php?script_id=670
You can use the 'record' feature. It is an easy way to record macros in Vim.
See :help record
In normal mode 'qa' to start recording what you type in the 'a' register Type the necessary command to insert a number at the beginning of line, copy it to next line and use CTRL-A to increase its value. 'q' to end the recording then '@a' to replay the macro stored in register 'a' ('@@' repeat the last macro).
And you can do things like '20@a' to do it twenty times in a row.
It is pretty handy to repeat text modification.
Depending of the cases, it is easier or harder to use than a regexp.
Maybe it's not a macro solution, but at least it's easy.
add numbers to all lines
It's possible to use :%!nl -ba
or :%!cat -n
commands which will add line numbers to all the lines.
On Windows, you've to have Cygwin/MSYS/SUA installed.
add numbers to selected lines
To add numbers only for selected lines, please select them in visual mode (v and cursors), then when finished - execute the command: :%!nl
(ignore blank lines) or :%!cat -n
(blank lines included).
formatting
To remove extra spaces, select them in visual block (Ctrl+v) and remove them (x).
To add some characters (.
, :
, )
) after the numbers, select them in visual block (Ctrl+v), then append the character (A, type the character, then finish with Esc).
Insert a number at the start of the block of text eg.
1. Item One
Enter the vim normal mode command as follows:
qb^yW+P^<Ctrl-A>q
This means:
qb # start recording macro 'b'
^ # move to start of text on the line
yW # 'yank' or copy a word including the ending whitespace.
+ # move one line down to the start of the next line
P # place text ahead of the cursor
^ # move to start of text
<Ctrl-A> # increment text
q # Finish recording macro
What this allows you to do is replay the macro across the last line of numbered list as many times as needed.
It is some time later and I think it is time to upgrade this answer, at least for neovim users. Here I wrote a lua function you can bind to Enter and it will work on any imaginable type of list, such as
1. foo
1.99-> bar
and after pressing enter, this line will be added:
1.100->
all using this function
vim.api.nvim_set_keymap('i','<Enter>','v:lua.enter_or_list()', {expr = true})
function _G.enter_or_list()
local line = vim.api.nvim_buf_get_lines(0, vim.fn.line('.') - 1, -1, false)[1]:match('^%s*[^%a%s]+')
if not line then
return '\r'
else
local start, finish = line:find('[^%a%s]*%d')
local main = line:sub(start,finish)
local suffix = line:sub(finish+1)
return table.concat({
'\r',
main,
vim.api.nvim_replace_termcodes('<Esc><C-a>a', true, true, true),
suffix,
' '
})
end
end
for vim users, I have a little simpler, but a little less capable keybinding:
imap <silent> <S-Enter> <CR><Esc>kk<End>Ev<Home>yjpk<End>e<C-a><End>a<Space>
I hope this will be useful to other people as well, as it is very convenient. Cheers
精彩评论