你能告诉 Vim 打开一个不同于在命令行或 :e 上传递的文件的文件吗?

  • 本文关键字:文件 命令行 不同于 Vim 一个 vim
  • 更新时间 :
  • 英文 :


我想教 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 答案的惰性解决方案。 当前存在的问题:

  1. 它写入的文件是原始名称,而不是修改后的名称
  2. 看起来设置文件类型的自动命令运行得太快,根本没有运行,或者很混乱。
  3. 它正在使用外部命令来完成工作
  4. 它特定于我想要的咀嚼(即它不是通用的(

当我有更多的停机时间时,我希望修复上述所有问题并将其转换为插件。

.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 文件(。

最新更新