Чтобы функция выполнялась всего один раз в диапазоне, добавьте ключевое слово range
.Например,
fun Foo() range
...
endfun
Тогда ваша функция может позаботиться о самом диапазоне с помощью специальных параметров a: firstline и a: lastline.(Подробнее см. :help a:firstline
.)
Однако я думаю, что в этом случае ваши требования достаточно просты, чтобы их можно было выполнить при помощи однострочника с использованием :global
.
Мы могли быделать с лучше определенными входами и выходами действительно.Но если предположить, что файл содержит
Item a: <total>
Subitem: 10 min
Subitem 2: 20 min
Item b: <total>
Subitem: 10 min
Subitem 2: 23 min
Item c: <total>
Subitem: 10 min
Subitem 2: 23 min
Subitem 3: 43 min
и функцию, определенную как
fun! Sum(n)
let g:s += a:n
return a:n
endfun
, то это будет суммировать подэлементы (все в одну строку)
:g/^Item/ let g:s = 0 | mark a | +,-/\nItem\|\%$/ s/\v(\d+)\ze\s+min$/\=Sum(submatch(0))/g | 'a s/<total>/\=(g:s . ' min')/
и выдаем этот вывод
Item a: 30 min
Subitem: 10 min
Subitem 2: 20 min
Item b: 33 min
Subitem: 10 min
Subitem 2: 23 min
Item c: 76 min
Subitem: 10 min
Subitem 2: 23 min
Subitem 3: 43 min
Кстати, вышеприведенная команда действует на весь буфер.Если вы сначала выделите диапазон, а затем нажмете клавишу :
, vim автоматически добавит к вашей команде '<,'>
, что означает, что следующая команда будет действовать от начала до конца выделенного диапазона.
Напримервыделение строк с 1 по 5 и последующее выполнение команды (:'<,'> g/...
) приводит к выводу
Item a: 30 min
Subitem: 10 min
Subitem 2: 20 min
Item b: 33 min
Subitem: 10 min
Subitem 2: 23 min
Item c: <total>
Subitem: 10 min
Subitem 2: 23 min
Subitem 3: 43 min
Одна заключительная нота.Если в одной из групп нет подэлементов, например,
Item a: <total>
Subitem: 10 min
Subitem 2: 20 min
Item b: <total>
Item c: <total>
Subitem: 10 min
Subitem 2: 23 min
Subitem 3: 43 min
, то команда будет прервана с ошибкой «Неверный диапазон» при достижении второго элемента.Вы можете заставить Vim игнорировать это и продолжать работу независимо от того, поставив перед всей командой префикс :silent!
.
EDIT
Просто краткое объяснение моего рабочего процесса и почемуlong one-liner.
- Мне нравится
:g
и много команд ex. - Я собрал команду в интерактивном режиме, используя историю командной строки и окно командной строки дляправка.
- Когда я закончу, я вставляю одноразовые команды, подобные этой, в буфер: у меня есть отображение, чтобы выполнить текущую строку как команду ex.Таким образом, команда всегда легко доступна, когда она мне нужна.Для более регулярного использования вам может потребоваться команда, функция или ftplugin.