-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtimecalc.vim
76 lines (63 loc) · 1.54 KB
/
timecalc.vim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
let s:pat = '\v(\d+)%(:([0-5]\d))?:([0-5]\d)'
let s:alt_pat = '\v^(-)?' . s:pat[2 :] . '$'
let s:cpo_save = &cpo
set cpo&vim
func s:secs_to_dur(d) abort
let d = a:d
let [s, d] = [d % 60, d / 60]
let [m, d] = [d % 60, d / 60]
let h = d
return h != 0
\ ? printf("%d:%02d:%02d", h, m, s)
\ : printf("%d:%02d", m, s)
endfunc
func SumDurations(durations) abort
let total = 0
for duration in a:durations
if type(duration) == type('')
" Parse duration
let matches = matchlist(duration, s:alt_pat)
if !empty(matches)
let [sign, h, m, s] = matches[1 : 4]
if empty(m)
let [h, m] = [0, h]
endif
let duration = (h * 60 + m) * 60 + s
if sign == '-'
let duration = -duration
endif
endif
endif
let total += duration
endfor
return s:secs_to_dur(total)
endfunc
func SumDurationRange(...) abort range
if a:0 > 2
throw 'Expected at most 2 arguments for'
\ . 'SumDurationRange, got ' . a:0 . '.'
endif
let first = get(a:000, 0, a:firstline)
let last = get(a:000, 1, get(a:000, 0, a:lastline))
let lines = getline(first, last)
if len(lines) == 1
let durations = []
" With help from https://stackoverflow.com/a/34069943
call substitute(
\ lines[0],
\ s:pat,
\ '\=add(durations, submatch(0))',
\ 'g')
else
let durations = map(lines, 'matchstr(v:val, s:pat)')
endif
if empty(durations)
throw 'No valid durations in given range.'
endif
return SumDurations(durations)
endfunc
command -bar -range
\ SumDurations
\ echo SumDurationRange(<line1>, <line2>)
let &cpo = s:cpo_save
unlet s:cpo_save