Аналогично ответу на https://vi.stackexchange.com/a/818/227 , вы можете использовать глобальную команду.
С его помощью вы можете указать vim искать строки, соответствующие шаблону, а затем выполнять команды для него.
В вашем случае вы хотите добавить текст к строкам, начинающимся с «Level 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:/
Наша глобальная команда вставит значение и увеличит наш счетчик с помощью команды подстановки и команды let. s/^/\=printf("%02d ", i)/ | let i = i+1
Регулярное выражение команды подстановки находит начало строки ^
и заменяет его выражением, и наше выражение будет результатом отформатированной печати. Как и в языке Си, 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, которая принимает строку и запускает строку как команду ex ( :help :exe
). Мы создаем строку, которая объединяет «normal! I» с нашими данными, которые будут «normal! I01» в первый раз и «normal! I02» во второй раз и т. Д.
Команда normal
выполняет операции как в обычном режиме. В этом примере наша обычная команда I
, которая вставляет в начало строки. Если бы мы использовали dd
его, то удалили бы строку, o
открыли бы новую строку после совпавшей строки. Это как если бы вы печатали I
(или любые другие операции) самостоятельно в обычном режиме. мы используем !
после, normal
чтобы убедиться, что никакие отображения не мешают нам. См :help :normal
.
Затем вставляется значение нашего printf, как в первом примере использования замены.
Этот метод может быть сложнее, чем регулярное выражение, потому что вы можете делать такие вещи, как execute "normal! ^2wy" . i . "th$p"
переход к началу текста ^
, перемещение вперед на 2 слова 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