Вы можете попробовать следующую команду:
:let c=0 | g/^* /let c+=1 | s//\=c.'. '
Сначала он инициализирует переменную c
( let c=0
), затем выполняет глобальную команду, g
которая ищет шаблон ^*
(начало строки, затем звездочка и пробел).
Всякий раз, когда строка, содержащая этот шаблон, найдена, глобальная команда выполняет команду:
let c+=1 | s//\=c.'. '
она увеличивает переменную c
( let c+=1
), затем ( |
) заменяет ( s
) предыдущий искомый шаблон ( //
) оценкой выражения ( \=
):
содержимое переменной c
сцепляется ( .
) со строкой'. '
Если вы не хотите изменять все строки из буфера, а только определенный абзац, вы можете передать диапазон глобальной команде. Например, чтобы изменить только строки с номерами от 5 до 10:
:let c=0 | 5,10g/^* /let c+=1 | s//\=c.'. '
Если у вас есть файл, содержащий несколько похожих списков, которые вы хотите преобразовать, например, что-то вроде этого:
some random stuff some random stuff
* foo 1. foo
* bar 2. bar
* baz 3. baz
some other random stuff some other random stuff
==>
some random stuff some random stuff
* foo 1. foo
* bar 2. bar
* baz 3. baz
* qux 4. qux
some other random stuff some other random stuff
Вы можете сделать это с помощью следующей команды:
:let [c,d]=[0,0] | g/^* /let [c,d]=[line('.')==d+1 ? c+1 : 1, line('.')] | s//\=c.'. '
Это просто вариант предыдущей команды, которая сбрасывает переменную c
при переключении на другой список. Чтобы определить, находитесь ли вы в другом списке, переменная d
используется для хранения номера последней строки, где была сделана замена.
Глобальная команда сравнивает текущий номер строки ( line('.')
) с d+1
. Если они совпадают, это означает, что мы находимся в том же списке, что и раньше, то c
есть incremental ( c+1
), в противном случае это означает, что мы находимся в другом списке, то c
есть reset ( 1
).
Внутри функции команду let [c,d]=[line('.')==d+1 ? c+1 : 1, line('.')]
можно переписать так:
let c = line('.') == d+1 ? c+1 : 1
let d = line('.')
Или вот так:
if line('.') == d+1
let c = c+1
else
let c = 1
endif
let d = line('.')
Чтобы сохранить некоторые нажатия клавиш, вы также можете определить пользовательскую команду :NumberedLists
, которая принимает диапазон со значением по умолчанию 1,$
( -range=%
):
command! -range=% NumberedLists let [c,d]=[0,0] | <line1>,<line2>g/^* /let [c,d]=[line('.')==d+1 ? c+1 : 1, line('.')] | s//\=c.'. '
Когда :NumberedLists
будет выполнено, <line1>
и <line2>
будет автоматически заменено диапазоном, который вы использовали.
Итак, чтобы преобразовать все списки в буфере, вы должны набрать: :NumberedLists
Только списки между строкой 10 и 20: :10,20NumberedLists
Только визуальный подбор: :'<,'>NumberedLists
Для получения дополнительной информации см .:
:help :range
:help :global
:help :substitute
:help sub-replace-expression
:help list-identity (section list unpack)
:help expr1
:help :command