Ви можете спробувати наступну команду:
: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
само збільшується ( c+1
), інакше це означає, що ми перебуваємо в іншому списку, так c
само скидається ( 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