开发者

Macro for making numbered lists in vim?

开发者 https://www.devze.com 2023-01-26 10:06 出处:网络
Often times it seems I have a list of items, and I need to add numbers in front of them.For example: Item one

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:

  1. Make a blockwise, visual selection on the first character of each list item:

    ^<C-V>2j
    
  2. Insert a 0. at the beginning of these lines:

    I0. <Esc>
    
  3. Re-select the visual selection (which is now all of the 0s) with gv and increment them as a sequence g<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

0

精彩评论

暂无评论...
验证码 换一张
取 消