Подібно до відповіді на https://vi.stackexchange.com/a/818/227 , ви можете використовувати глобальну команду.
З його допомогою ви можете доручити vim шукати рядки, що відповідають шаблону, а потім виконувати команди на ньому.
У вашому випадку ви хочете додати текст до рядків, що починаються з "Рівень N:", щоб наша глобальна команда могла бути
:g/^Level \d:/{COMMANDS}
Використання команди-замінника (регулярна заміна виразів) для команди
Команди веселіше. Зазвичай мені подобається робити регулярну заміну виразів для подібних матеріалів, оскільки це легко використовувати змінні.
Приклад вашого запитання
:let i = 1 | g/^Level \d:/s/^/\=printf("%02d ", i)/ | let i = i+1
Як це працює
У розділі заміни команда заміщення може бути виразом.
Перше, що ми зробимо, це встановити змінну, i
яка буде початковим номером. Я вибрав 1, але будь-яке число зробить.let i = 1
Тоді ми запускаємо нашу глобальну команду, яка налаштовує нас робити дії на відповідні лінії. g/^Level \d:/
Ми змусимо нашу глобальну команду вставити значення та збільшити наш лічильник, використовуючи команду supstitution та команду let.s/^/\=printf("%02d ", i)/ | let i = i+1
Регулярний вираз команди заміщення знаходить початок рядка ^
і замінює його виразом, і наш вираз буде результатом форматованого друку. Як і в мові C, vim's printf приймає параметри форматування. %02d
означає перетворити аргумент так, ніби це було десяткове число d
, займаючи принаймні 2 пробіли 2
та колодку з 0 0
. Детальну інформацію та інші параметри перетворення (включаючи форматування з плаваючою комою) див :help printf
. Ми даємо printf нашої змінної підрахунку, i
і вона дає нам 01
перший раз, 02
другий раз тощо. Це використовується командою заміщення для заміни початку рядка, ефективно вставляючи результат printf на початку.
Зауважте, що я поставив пробіл після d : "%02d "
. Ви не запитували про це у запитанні (і я не бачив приклад виводу), але я підозрював, що ви хочете відокремити число від слова "Рівень". Вилучіть пробіл із рядка, заданого для printf, щоб вставити число прямо поруч із L у рівні.
Нарешті, це let i = i + 1
збільшує наш лічильник після кожної заміни.
Це може застосовуватися загалом для заміни частин ліній, які відповідають іншим критеріям, довільними функціональними даними.
Використання комбінованих звичайних команд
Це добре для простих вставок або складного редагування. Як і в якості заміни, ми будемо використовувати глобальний, щоб відповідати, але замість регулярної заміни виразів ми виконаємо ряд операцій, як ніби введені користувачем.
Приклад вашого запитання
:let i = 1 | g/^Level \d:/execute "normal! I" . printf("%02d ", i) | let i = i+1
Як це працює
Використовувані значення дуже схожі на замінник (ми все ще використовуємо printf для форматування нашого номера, щоб зробити його 0 із 2 цифрами), але операція інша.
Тут ми використовуємо команду Execute, яка приймає рядок і виконує рядок як колишню команду ( :help :exe
). Ми побудуємо рядок, який поєднує "нормальне! Я" з нашими даними, яке буде "нормальним! I01" в перший раз і "нормальним! I02" вдруге і т.д.
У normal
команді виконує операції , якщо в нормальному режимі. У цьому прикладі наша звичайна команда I
, яка вставляє на початку рядка. Якби ми використовували, dd
вона видалила б рядок, o
відкрила б новий рядок після відповідного рядка. Це як би ви ввели I
(або будь-які інші операції) себе в звичайному режимі. ми використовуємо !
після, normal
щоб переконатися, що ніякі відображення не заважають. Див :help :normal
.
Потім вставляється значення нашого printf, як у першому прикладі використання замінника.
Цей спосіб може бути більш фантазійним, ніж регулярний вираз, тому що ви можете робити такі речі execute "normal! ^2wy" . i . "th$p"
, які перейдуть на початок тексту ^
, просуньте два слова вперед 2w
, потягніть до символу i-го 'h' y" . i . "th
, перемістіться до кінця рядка $
та вставте p
.
Це майже як запуск макросу, але насправді не використовує реєстр і може поєднувати рядки з будь-яких виразів. Я вважаю це дуже потужним.
Підхід, де кожен рівень має свій лічильник
Можливо, ви хочете, щоб кожен рівень мав власний лічильник. Якщо ви достроково знаєте максимальну кількість рівнів, ви можете зробити наступне (додавання додаткового коду, щоб знайти найбільший рівень, може бути не надто складно, але зробить цю відповідь занадто довгою. Це стає довше, ніж це є).
По-перше, давайте безкоштовно i, якщо ми вже використовували це як ціле число. Ми не можемо перетворити i до списку, ми мусимо створити його таким чином.
:unlet! i
Далі давайте встановити i бути списком, що містить кількість рівнів. Ви вказали 2 у своєму запитанні, але давайте припустимо 10 для задоволення. Оскільки індексація списку базується на 0, і я не хочу перешкоджати виправленню на 1 базі, як ваш список, ми просто створимо достатню кількість елементів (11) і ніколи не використовуватимемо індекс 0.
:let j = 0
:let i = []
:while j < 11 | let i += [1] | let j += 1 | endwhile
Далі нам потрібен спосіб отримати номер рівня. На щастя, замінник також доступний як функція, тому ми надамо йому наш рядок і витягнемо номер рівняsubstitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")
Оскільки я зараз - це список з 11 1
с (кожен індекс є лічильником для нашого рівня), тепер ми можемо коригувати будь-який із наведених вище прикладів, щоб використовувати результат цієї заміни:
Через команду заміна:
:unlet! i | unlet! j | let j = 0 | let i = [] | while j < 11 | let i += [1] | let j += 1 | endwhile
:g/^Level \d:/let ind=str2nr(substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")) | s/^/\=printf("%02d ", i[ind])/ | let i[ind] += 1
Через звичайну команду:
:unlet! i | unlet! j | let j = 0 | let i = [] | while j < 11 | let i += [1] | let j += 1 | endwhile
:g/^Level \d:/let ind=str2nr(substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")) | execute "normal! I" . printf("%02d ", i[ind]) | let i[ind] += 1
Приклад введення:
Level 1: stuff
Level 1: Stuff
Some text
Level 3: Other
Level 1: Meh
Level 2: More
Приклад виводу:
01 Level 1: stuff
02 Level 1: Stuff
Some text
01 Level 3: Other
03 Level 1: Meh
01 Level 2: More