Vim : 时间表中的时间增量

Vim : time increment in a schedule

我是 Vim 的新手,我想看看我能/不能用它做什么。我想像这样增加一个时间列表:

09:00 Breakfast 
09:30 RSS 
09:50 Stretch
10:00 Main proj
13:00 food
14:00 Main proj...

假设我起得太晚了,我想在 Vim

内将所有内容快速增加 45 分钟

我尝试了一个宏:

但我无法让它工作(它是一个很长的宏)而且我手动完成它更快。

最重要的是,即使我成功了,我也不知道如何保留 "09""0" 以将我的数字保留在一列中。

Vim 可以吗?也许是正则表达式?

[edit] 出于练习的目的,我宁愿在 VimScript 中使用宏、正则表达式甚至函数而不是插件

只有使用某些插件才有可能(或像 Kent 评论的那样编写函数),例如:

Speeddating plugin

日期和时间的计算总是比预期的更难。以夏令时为例。您应该让其他工具进行计算。如果你在 Linux,你可以尝试 date:

let @a=substitute(system("date -d @$(($(date -d " . substitute(getline('.'), '\(\S\+\).*', '', '') . " +\%s)+45*60)) +\%H:\%M"), ".$", "", "")

这会将当前行开头的时间(由 space 分隔)增加 45 分钟,并将其放入寄存器 a。然后您的宏可以删除时间并将其替换为 @a:

"_dE
"aP0

顺便说一句:这也适用于 "now":

这样的字符串
09:00 Breakfast (before)
09:45 Breakfast (after)

now Breakfast (before)
14:45 Breakfast (after)

我刚刚找到了OP的新编辑,看来他正在寻找一点vimscript功能。这是一个非通用函数,但它可以满足您的需要。

注意,在分钟增量之后,结果可能大于(晚于)24:00 在这种情况下,date 信息将丢失,例如添加 45mins23:30 上将产生 00:15

function! IncTime(mins) 
    let pat = '^\d\d:\d\d\ze '
    for i in range(line('$'))
        let tss = matchstr(getline(i+1), pat)
        if tss
            let ts = split(tss,':')
            let ns = 60*ts[0] + ts[1] + a:mins
            let nts = printf('%.2d:%.2d', (ns/60)%24, ns % 60)
            execute i+1.'s/'.pat.'/'.nts
        endif
    endfor
endfunction

获取它,并在您的文件中调用 :call IncTime(45) 来检查应用的更改。您还可以将 45 以外的不同偏移量传递给函数,例如 10,甚至 2000

所以,我尝试使用正则表达式(删除 return 回车):

%s@\(\d\d\):\(\d\d\)@\=printf('%.2d:%.2d'((submatch(1)*60+submatch(2)+45)/60),
((submatch(1)*60+submatch(2)+45)-((submatch(1)*60+submatch(2)+45)/60)*60))@

它很不优雅,我想要 inc = 45sum = (submatch(1)*60+submatch(2)+inc),我需要在与 printf 相同的行上声明变量...但它有效 ;)

内部视觉选择:使用 '<,'> 而不是 %

当然有一个问题是它不会在午夜前后循环,但我想 @steffen 的回答会更好

编辑: 我发现 Vimscript 中存在模数,我无法抗拒......现在它在午夜左右循环:

%s@\(\d\d\):\(\d\d\)@\=printf('%.2d:%.2d',((submatch(1)*60+submatch(2)+45)/60)%24,
(submatch(1)*60+submatch(2)+45)%60)@

编辑 2: 这里是使用 func-range 的函数中的代码(感谢@Kent)

function! IncrementTime(mins) range
    "Increments time within a range ( current line or selection)
    let pat = '(submatch(1)*60+submatch(2)+'.a:mins.'+1440)'
    execute a:firstline.','.a:lastline.'s@\(\d\d\):\(\d\d\)@\=printf("%.2d:%.2d",('.pat.'/60)%24,'.pat.'%60)@'
endfunction

我必须加 1440 以避免减一时出现负时数