我想教 Vim 如何从 File::Find
这样的名字打开 Perl 5 模块。 我已经有一个用Perl 5编写的包装脚本来处理命令行(见下文(,但我希望能够说出:tabe File::Find
之类的话,并让它真正执行:tabe /home/cowens/apps/perlbrew/perls/perl-5.14.0/lib/5.14.0/File/Find.pm
。
我目前的计划是以某种方式使用 autocmd BufNewFile
和/或 autocmd BufPreRead
,但我不知道如何切换文件名。
#!/usr/bin/perl
use strict;
use warnings;
my @files = @ARGV;
for my $file (@files) {
next if -f $file; #skip files that really exist
#convert from module name to module file
(my $module = $file) =~ s{::}{/}g;
$module .= ".pm";
#look for module in the include paths
for my $dir (@INC) {
my $candidate = "$dir/$module";
if (-f $candidate) {
$file = $candidate;
last;
}
}
}
#replace this script with vim
exec "vim", "-p", @files;
正在执行
:verbose au BufReadCmd
会告诉你其他类型的插件是如何做到这一点的(例如.zip:netrw,fugitive(。应该给你很多想法的示例输出:
zip BufReadCmd
zipfile:* call zip#Read(expand("<amatch>"), 1)
Last set from C:Program FilesVimvim73pluginzipPlugin.vim
*.zip call zip#Browse(expand("<amatch>"))
Last set from C:Program FilesVimvim73pluginzipPlugin.vim
Network BufReadCmd
ftp://* exe "silent doau BufReadPre ".fnameescape(expand("<amatch>"))|call netrw#Nread(2,expand("<amatch>"))|exe "silent doau BufReadPost ".fnameescape(expand("<amatch>"))
Last set from C:Program FilesVimvim73pluginnetrwPlugin.vim
http://* exe "silent doau BufReadPre ".fnameescape(expand("<amatch>"))|call netrw#Nread(2,expand("<amatch>"))|exe "silent doau BufReadPost ".fnameescape(expand("<amatch>"))
Last set from C:Program FilesVimvim73pluginnetrwPlugin.vim
fugitive_files BufReadCmd
*.git/index
exe s:BufReadIndex()
Last set from C:Program FilesVimvimfilespluginfugitive.vim
*.git/*index*.lock
exe s:BufReadIndex()
Last set from C:Program FilesVimvimfilespluginfugitive.vim
fugitive://**//[0-3]/**
exe s:BufReadIndexFile()
Last set from C:Program FilesVimvimfilespluginfugitive.vim
fugitive://**//[0-9a-f][0-9a-f]*
exe s:BufReadObject()
Last set from C:Program FilesVimvimfilespluginfugitive.vim
考虑使用 ctags
。如果你能够在源代码上运行ctags进程,你应该能够达到一个点,你只需要这样做:
vim -t File::Find
Vim有关于这个的信息(:help vim
(,我认为ctags可能远远超出了你想要做的事情,允许你从一个源文件的中间跳到另一个源文件中的原始函数定义。
要手动打开这些文件,我建议使用 :find
和 :tabfind
命令,而不是分别:edit
和:tabedit
。 这这两对命令之间的区别在于前一对命令看起来对于文件,不仅在当前路径中,而且在 path
选项(请参阅:help 'path'
(。 如果你添加你的 Perl @INC
目录到 Vim path
选项,您可以使用 :find
或 :tabfind
命令。 例如,打开新标签页并编辑 File::Find
模块文件中,您可以键入
:tabfind File/Find.pm
(您不必手动键入整个子路径,因为 :find
和 :tabfind
完成会考虑当前的path
值。
要使用 gf
、 ^Wf
、 ^Wgf
,您需要另外更改(使用文件类型插件或autocommand(Perl文件的以下选项。
:set isfname+=:
:set suffixesadd+=.pm
:set includeexpr=substitute(v:fname,'::','/','g')
在这些选项之后(以及包含 Perl @INC
path
选项目录(设置,您可以使用类似gf
轻松打开模块文件对应模块名称上的命令。
基于下面 sehe 答案的惰性解决方案。 当前存在的问题:
- 它写入的文件是原始名称,而不是修改后的名称
- 看起来设置文件类型的自动命令运行得太快,根本没有运行,或者很混乱。
- 它正在使用外部命令来完成工作
- 它特定于我想要的咀嚼(即它不是通用的(
当我有更多的停机时间时,我希望修复上述所有问题并将其转换为插件。
在.vimrc
autocmd BufReadCmd * r!cat_perl %
在cat_perl
#!/usr/bin/perl
use strict;
use warnings;
sub cat {
my $file = shift;
open my $fh, "<", $file
or die "could not open $file: $!";
print while <$fh>;
exit;
}
my $file = shift;
cat $file if -f $file;
#convert from module name to module file
(my $module = $file) =~ s{::}{/}g;
$module .= ".pm";
#look for module in the include paths
for my $dir (@INC) {
my $candidate = "$dir/$module";
cat $candidate if -f $candidate;
}
print "";
实际上可以通过 vim 的 gf
命令(转到文件(来实现。
在代码中,如果看到类似 File::Find 的字符串,请将光标放在该字符串上,并在正常模式下键入 gf
。对我来说,这会立即将我带到File::Find 包。
我认为这是perl文件类型库的一部分,因为它在使用--noplugin
执行vim时对我有用。
下面是一个工作示例,显示了如何使用 BufReadCmd autocmd 编辑指定文件以外的文件(在本例中,在打开.css文件时编辑相应的 .scss 文件(。