Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 153 lines (122 sloc) 3.81 kB
7fa48f6 @rwstauner Defend against no vim and/or older versions
authored
1 use strict;
2 use warnings;
3
4 # This module is overly defensive, but hopefully will handle all portability issues
5 package inc::VimCommand;
8a8b568 @rwstauner Document that vim version 6 is the minimum requirement
authored
6 #our $MIN = '5.4';
7 our $MIN = '6.0';
7fa48f6 @rwstauner Defend against no vim and/or older versions
authored
8
a2df22d @rwstauner Use vim script during make_pl to detect version
authored
9 use File::Temp qw( tempfile ); # core
10 use IO::File; # core
7fa48f6 @rwstauner Defend against no vim and/or older versions
authored
11 use IPC::Open3 'open3'; # core
12
a2df22d @rwstauner Use vim script during make_pl to detect version
authored
13 # vim -h works at least as far back as 5.0 (--version not until 5.2)
14 # first line: "VIM - Vi IMproved 5.0 (date)"
15 our $VERSION_RE = qr/vim .+ ([0-9.]+)/i;
16
17 our $INFO = {};
18
19 our $MESSAGE = <<MESSAGE;
20 This module requires vim version $MIN or later
21 which must be compiled with at least the 'normal' feature set
22 (--with-features=normal) particularly including +syntax (obviously).
23
24 If you believe this to be an error please submit a bug report
25 including the output of `vim --version` if possible.
26 MESSAGE
27
7fa48f6 @rwstauner Defend against no vim and/or older versions
authored
28 sub import {
a2df22d @rwstauner Use vim script during make_pl to detect version
authored
29 require_minimum_with_message();
30 }
31
32 sub require_minimum_with_message {
6a5abe1 @rwstauner Try to show version info before Makefile.PL death
authored
33 my $req = eval {
a2df22d @rwstauner Use vim script during make_pl to detect version
authored
34 require_minimum();
35 };
6a5abe1 @rwstauner Try to show version info before Makefile.PL death
authored
36 if( my $msg = $@ ){
a2df22d @rwstauner Use vim script during make_pl to detect version
authored
37 $msg .= "\n$MESSAGE\n";
6a5abe1 @rwstauner Try to show version info before Makefile.PL death
authored
38
39 # include version_output in test report unless we know vim isn't available
40 $msg .= "\n" . version_output() . "\n"
41 unless $msg =~ /^\s*open3:/m;
42
a2df22d @rwstauner Use vim script during make_pl to detect version
authored
43 $msg =~ s/^/# /mg;
44 die $msg;
45 }
6a5abe1 @rwstauner Try to show version info before Makefile.PL death
authored
46 return $req;
7fa48f6 @rwstauner Defend against no vim and/or older versions
authored
47 }
48
49 sub require_minimum {
a2df22d @rwstauner Use vim script during make_pl to detect version
authored
50 my $info = info_from_script();
51 my $ver = sprintf("%0.2f", $info->{version}/100);
7fa48f6 @rwstauner Defend against no vim and/or older versions
authored
52
a2df22d @rwstauner Use vim script during make_pl to detect version
authored
53 if( !$ver ){
54 die "Unable to identify vim version ($ver)\n";
55 }
56 elsif( $ver < $MIN ){
57 $ver =~ s/\.0/./; # 5.08 => 5.8
58 die "Vim version $ver too low.\n";
59 }
60 elsif( !$info->{syntax} ){
61 die "Vim does not have the +syntax feature.\n";
62 }
63 return $ver;
64 }
7fa48f6 @rwstauner Defend against no vim and/or older versions
authored
65
a2df22d @rwstauner Use vim script during make_pl to detect version
authored
66 sub info_from_script {
67 # touch output file
68 my $out = write_temp('tvc-out-XXXXXX', '');
7fa48f6 @rwstauner Defend against no vim and/or older versions
authored
69
a2df22d @rwstauner Use vim script during make_pl to detect version
authored
70 # NOTE: use single quotes, or backslashed double quotes in the '=' expr:
71 my $script = write_temp('tvc-script-XXXXXX', <<SCRIPT);
72 :put ='vim:' . version . ',syn:' . has('syntax') . ','
73 :0d
74 :write! $out
75 :quit!
76 SCRIPT
7fa48f6 @rwstauner Defend against no vim and/or older versions
authored
77
a2df22d @rwstauner Use vim script during make_pl to detect version
authored
78 # try
79 eval {
80 # use IPC::Open3 to prevent STDOUT/ERR from interfering with make/test
81 vim(qw(-u NONE -s), $script);
7fa48f6 @rwstauner Defend against no vim and/or older versions
authored
82
a2df22d @rwstauner Use vim script during make_pl to detect version
authored
83 my $output = do { local $/; IO::File->new($out, 'r')->getline; };
84
85 die "Vim script failed: Output file is empty.\n"
86 unless $output;
87 die "Failed to parse vim output:\n>$output\n"
88 unless $output =~ /^vim:(\d+),syn:(.+?),$/;
89
90 # if there was more info to get we could parse the output more generically
91 $INFO = { version => $1, syntax => $2 };
92 };
93 # catch part 1
94 my $e = $@;
95 # finally
96 unlink($out, $script);
97 # catch part 2
98 die $e if $e;
99
100 return $INFO;
7fa48f6 @rwstauner Defend against no vim and/or older versions
authored
101 }
102
103 sub vim {
104 my @args = @_;
105 my $output;
106 my $timeout = 10;
107
108 # if we pass an arg vim doesn't understand (like --version before v5.2)
109 # it will treat it like a filename and wait for input
110 # so try not to hang indefinitely if we have an old version.
111 eval {
112 local $SIG{PIPE} = 'IGNORE';
113 local $SIG{ALRM} = sub { die "alarm\n" };
114
115 alarm $timeout;
116
117 my $pid = open3(my ($i, $o), undef, vim => @args);
60e9980 @rwstauner Read before waitpid to avoid hanging on older systems
authored
118
119 # read handle before waitpid to avoid hanging (and timing out) on older systems
120 $output = do { local $/; <$o>; };
121
7fa48f6 @rwstauner Defend against no vim and/or older versions
authored
122 waitpid($pid, 0);
a2df22d @rwstauner Use vim script during make_pl to detect version
authored
123 #my $stat = $?;
7fa48f6 @rwstauner Defend against no vim and/or older versions
authored
124
125 alarm 0;
126
a2df22d @rwstauner Use vim script during make_pl to detect version
authored
127 # open3 will probably die if vim isn't found (in unix environments)
128 # we can't really trust the exit status to mean anything...
129 # vim might exit 1 or 2 (or 0) for -h/--version, cmd.exe exits 1 if not found...
7fa48f6 @rwstauner Defend against no vim and/or older versions
authored
130 };
131 if( my $e = $@ ){
132 $e = "Command aborted after $timeout seconds."
133 if $e eq "alarm\n";
a2df22d @rwstauner Use vim script during make_pl to detect version
authored
134 die "Error attemting to execute 'vim':\n $e\n";
7fa48f6 @rwstauner Defend against no vim and/or older versions
authored
135 }
136 return $output;
137 }
138
6a5abe1 @rwstauner Try to show version info before Makefile.PL death
authored
139 sub version_output {
140 # if we know version is less than 5.2 don't even try --version
141 vim(($INFO->{version} && $INFO->{version} < 502) ? '-h' : '--version');
142 }
143
a2df22d @rwstauner Use vim script during make_pl to detect version
authored
144 sub write_temp {
145 my ($template, $text) = @_;
146 my ($fh, $path) = tempfile( $template, TMPDIR => 1 );
147 print $fh $text;
148 close $fh;
149 return $path;
150 }
151
7fa48f6 @rwstauner Defend against no vim and/or older versions
authored
152 1;
Something went wrong with that request. Please try again.