在vim中制作编号列表的宏?

32

很多时候我有一个项目列表,需要在它们前面添加数字。例如:

Item one
Item two
Item three

应该是这样的:

1. Item one
2. Item two
3. Item three
在vim中,我可以在编辑模式下按下,插入“1.”,然后按下escape。然后我去到下一行,按下 ".",然后按下^A来递增数字。这看起来非常低效... 我该如何制作一个宏,以便我可以进入下一行,并在开头插入一个数字,该数字比前一行多1个?
8个回答

29

您可以轻松地记录宏来完成此操作。

首先在第一行开头插入1.(第一个项目前有几个空格,但您看不到它们)。

移到第二行开头,并使用qa进入录制模式。

按照以下键序列:

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

现在你可以使用@a进行回放(第一次执行;对于后续执行,可以使用@@重复上一次执行的宏),它将在每行开头添加一个新的递增数字。


10
使用 3@a 来执行宏,重复执行3次。 - Eugene Yarmash
10
我会选择使用 k^yWjP^<ctrl-a>j。文本可能不在行首,更重要的是,您的宏在第十行之后将无法工作。 - Luc Hermitte
非常准确,@Luc - 就像我自己想的那样,只是我在结尾加了 ^,这样当完成时它会将光标定位到行的开头。由于在开头加上 ^ 没有功能上的区别,只是感觉更整洁一些。 - Chris Morgan
@Luc Hermitte: <CTRL-A>会跳到最后一个数字。我建议在之后加上^ - Benoit
@LucHermitte 如果您能解释一下这里每个字符的作用,那就更好了。谢谢。 - Prabhat Kumar Singh
1
@PrabhatKumarSingh,您可以在宏的每个部分上调用:h以了解其功能。在这里它会很好地工作。k -> 上一行,^ -> 行首,yW -> 我需要介绍这个吗?, j -> 将光标移动到下一行,P -> 如果您是vim用户,您应该知道它的作用,^-> 再次回到行首,<C-A> 是在这里完成任务的:它增加了光标下的数字,然后 j-> 再次移动到下一行。 - Luc Hermitte

15

使用可视模式选择行:V,然后输入:

:'<,'>s/^\s*\zs/\=(line('.') - line("'<")+1).'. '

哪种方法更容易通过命令行实现:

command! -nargs=0 -range=% Number <line1>,<line2>s/^\s*\zs/\=(line('.') - <line1>+1).'. '

我喜欢这个的可重复性。对于单行来说非常好。不幸的是,对于我的目的,当插入编号时,我倾向于在reStructuredText中进行,因此需要基本上的}功能 - 但由于它正在进行行计数的方式,仅仅用\n\n替换^是不够的。遗憾,否则它会进入我的.vimrc。无论如何,代码很好,我不知道\=() - 我在vim帮助中找不到它! - Chris Morgan
你可以使用任何你想要的函数,例如一个能够自我计数的函数。在这种情况下,你可能需要使用一个封装“循环”的命令,例如 https://dev59.com/wErSa4cB1Zd3GeqPXIq1#1809780 。否则,请参考:h sub-replace-\= - Luc Hermitte
1
这是一种简单易行的方法来创建一个简单的编号列表。我将以下条目添加到我的.vimrc文件中;要使用它,请先进行可视选择,然后按下您的“leader”键(我的重新映射为空格键)+“n”,即<space>n。 vnoremap <leader>n:s / ^ \ s * \ zs / \ =(line('.') - line(“'<”)+1)。'. '<CR> - Victoria Stuart
@VictoriaStuart。在这里最好使用:xnoremap,以免干扰大多数片段插件使用的选择模式。 - Luc Hermitte
相应的 :UnNumberLines 更简单:command! -nargs=0 -range=% UnNumberLines <line1>,<line2>s/\d\+\. //g - Ben

13

以下是一种无需录制宏的简单方法:

  1. 在每个列表项的第一个字符上进行块状可视化选择:

    ^<C-V>2j
    
  2. 在这些行的开头插入0.

    I0. <Esc>
    
    重新选择视觉选择(现在是所有的“ 0 ”)使用“ gv”并将它们作为序列递增“ g”:
  3. gvg<C-A>
    

整个序列: ^<C-V>2jI0. <Esc>gvg<C-A>.

操作过程的录制视频.


2
这是最好的解决方案。我甚至不知道 gvg<C-a>,现在我学会了它们,它们也可以用于其他情况。 - rvighne
1
我同意。它简明扼要,我对 g 操作符的了解更深入了。 - trevdev
太棒了!使用 :help gv 查找有关 gv 的帮助。使用 :help v_g_CTRL-A 查找有关 g<C-A> 的帮助。 - Shaun Luttin

7

再同意不过了,专门为此任务设计的插件比自制宏要好得多,因为创建系列是一项您将不止一次执行的任务。 - Benoit

4
您可以使用“记录”功能。这是在Vim中记录宏的简单方法。
请参阅::help record
在正常模式下,输入'qa'以开始记录'a'寄存器中键入的内容,然后输入必要的命令,在行首插入数字,将其复制到下一行,并使用CTRL-A增加其值。输入'q'结束录制,然后输入'@a'播放存储在寄存器'a'中的宏('@@'重复上一个宏)。
您还可以像'20@a'这样做二十次。
这非常方便地重复文本修改。
根据情况,它比正则表达式更容易或更难使用。

3
也许这不是宏解决方案,但至少很容易。 为所有行添加数字 可以使用命令:%!nl -ba:%!cat -n将行号添加到所有行中。
在Windows上,您必须安装Cygwin/MSYS/SUA。
为选定的行添加数字
要仅为选定的行添加数字,请在可视模式下选择它们(v和光标),然后完成后执行命令::%!nl(忽略空行)或:%!cat -n(包括空行)。
格式化
要删除额外的空格,请在可视块中选择它们(Ctrl+v),然后删除它们(x)。
要在数字后添加一些字符(.:)),请在可视块中选择它们(Ctrl+v),然后追加字符(A,输入字符,然后按Esc)。

要在选定的行中添加一些字符(.),您可以使用 :'<,'>normal a.。由于选择是在之前完成的,请使用 gv 重复它。 - wryrych

0

现在已经过了一段时间,我认为是时候升级这个答案了,至少对于neovim用户来说是这样。 在这里,我编写了一个lua函数,您可以将其绑定到Enter键上,并且它将适用于任何可想象的列表类型,例如

1. foo
 1.99-> bar

在按下回车键后,将添加此行:

 1.100-> 

所有人都使用这个函数

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

对于 Vim 用户,我有一个更简单但功能稍弱的按键绑定:

imap <silent> <S-Enter> <CR><Esc>kk<End>Ev<Home>yjpk<End>e<C-a><End>a<Space>

我希望这对其他人也有用,因为它非常方便。 干杯


0
在文本块的开头插入一个数字,例如:

1. 第一项

输入以下vim正常模式命令:

qb^yW+P^<Ctrl-A>q

这意味着:

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

这样可以让您在需要的时候重复播放宏,跨越编号列表的最后一行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接