我想创建一个 vim 函数/命令来插入 XSD 样式时间戳。目前,我在 vimrc 文件中使用以下内容:
nmap <F5> a<C-R>=strftime("%Y-%m-%dT%H:%M:%S-07:00")<CR><Esc>
Run Code Online (Sandbox Code Playgroud)
我想使用 Perl 代码:
use DateTime;
use DateTime::Format::XSD;
print DateTime->now(formatter => 'DateTime::Format::XSD', time_zone => 'America/Phoenix');
Run Code Online (Sandbox Code Playgroud)
但我不知道从哪里开始。我知道我可以定义一个使用 Perl 的函数。例子:
function PerlTest()
perl << EOF
use DateTime;
use DateTime::Format::XSD;
print DateTime->now(formatter => 'DateTime::Format::XSD', time_zone => 'America/Phoenix');
EOF
Run Code Online (Sandbox Code Playgroud)
但是当我将 vimrc 更改为以下内容时,我没有得到我所期望的结果:
nmap <F5> a<C-R>=PerlTest()<CR><Esc>
Run Code Online (Sandbox Code Playgroud)
有人能指出我实施这个的正确方向吗?这是我第一次尝试在 vim 中编写函数。另外,我使用的是带有 perl 支持的 vim 7.2。
首先,您需要查看:help if_perl以获取有关在 Vim 中使用 Perl 的一般信息。
对于这个具体问题,我认为进入插入模式和评估表达式的相同方法不是最佳选择。语言绑定似乎没有办法返回这样的值。
您可以做的是让函数获取当前行,将时间字符串放在适当的位置,然后再次设置当前行。
fun! PerlTest()
perl << EOF
use DateTime;
use DateTime::Format::XSD;
my ($row, $col) = $curwin->Cursor();
my ($line) = $curbuf->Get($row);
substr($line, $col + 1, 0,
DateTime->now(formatter => 'DateTime::Format::XSD',
time_zone => 'America/Phoenix'));
$curbuf->Set($row, $line);
EOF
endfun
Run Code Online (Sandbox Code Playgroud)
那么你的地图就只是nnoremap <F5> :call PerlTest()<CR>。
我注意到上面的一个问题是,如果该行包含 1 个字节!= 1 列的字符(即制表符、多字节字符等),它就不能很好地工作。我尝试过各种方法来尝试解决这个问题,但似乎没有一个效果很好。
问题是没有简单的方法可以将 Vim 的光标位置映射到字符串中表示光标当前行的位置。
另一种避免此问题的方法是仅使用 Perl 接口获取数据,然后从 Vim 粘贴数据。
fun! PerlTest()
let a_reg = getreg('a', '1')
let a_reg_type = getregtype('a')
perl << EOF
use DateTime;
use DateTime::Format::XSD;
my $date = DateTime->now(formatter => 'DateTime::Format::XSD',
time_zone => 'America/Phoenix');
VIM::Eval("setreg('a', '$date', 'c')");
EOF
normal "ap
call setreg('a', a_reg, a_reg_type)
endfun
nnoremap <F5> :call PerlTest()<CR>
Run Code Online (Sandbox Code Playgroud)