File Coverage

blib/lib/Filename/Executable.pm
Criterion Covered Total %
statement 11 16 68.7
branch 0 4 0.0
condition 0 2 0.0
subroutine 4 5 80.0
pod 1 1 100.0
total 16 28 57.1


line stmt bran cond sub pod time code
1             package Filename::Executable;
2              
3 1     1   370808 use 5.010001;
  1         3  
4 1     1   5 use strict;
  1         1  
  1         21  
5 1     1   3 use warnings;
  1         7  
  1         88  
6              
7 1     1   10 use Exporter qw(import);
  1         3  
  1         548  
8              
9             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
10             our $DATE = '2023-12-16'; # DATE
11             our $DIST = 'Filename-Executable'; # DIST
12             our $VERSION = '0.002'; # VERSION
13              
14             our @EXPORT_OK = qw(check_executable_filename);
15              
16             our %TYPES = (
17             'perl script' => [qw/.pl/],
18             'php script' => [qw/.php/],
19             'python script' => [qw/.py/],
20             'ruby script' => [qw/.rb/],
21             'shell script' => [qw/.sh .bash/],
22             'shell archive' => [qw/.shar/],
23             'dos program' => [qw/.exe .com .bat/],
24             'appimage' => [qw/.appimage/],
25             );
26             our %EXTS = map { my $type = $_; map {($_=> $type)} @{ $TYPES{$type} } } keys %TYPES;
27             our $RE_STR = join("|", sort {length($b) <=> length($a) || $a cmp $b} keys %EXTS);
28             our $RE_NOCI = qr/\A(.+)($RE_STR)\z/;
29             our $RE_CI = qr/\A(.+)($RE_STR)\z/i;
30              
31             our %SPEC;
32              
33             $SPEC{check_executable_filename} = {
34             v => 1.1,
35             summary => 'Check whether filename indicates being an executable program/script',
36             description => <<'_',
37              
38              
39             _
40             args => {
41             filename => {
42             schema => 'str*',
43             req => 1,
44             pos => 0,
45             },
46             # XXX recurse?
47             ignore_case => {
48             summary => 'Whether to match case-insensitively',
49             schema => 'bool*',
50             default => 1,
51             cmdline_aliases => {i=>{}},
52             },
53             },
54             result_naked => 1,
55             result => {
56             schema => ['any*', of=>['bool*', 'hash*']],
57             description => <<'_',
58              
59             Return false if no archive suffixes detected. Otherwise return a hash of
60             information, which contains these keys: `exec_type`, `exec_ext`,
61             `exec_name`.
62              
63             _
64             },
65             examples => [
66             {
67             args => {filename => 'foo.pm'},
68             naked_result => 0,
69             },
70             {
71             args => {filename => 'foo.appimage'},
72             naked_result => {exec_name=>'foo', exec_type=>'appimage', exec_ext=>'.appimage'},
73             },
74             {
75             summary => 'Case-insensitive by default',
76             args => {filename => 'foo.Appimage'},
77             naked_result => {exec_name=>'foo', exec_type=>'appimage', exec_ext=>'.Appimage'},
78             },
79             {
80             summary => 'Case-sensitive',
81             args => {filename => 'foo.Appimage', ignore_case=>0},
82             naked_result => 0,
83             },
84             ],
85             };
86             sub check_executable_filename {
87 0     0 1   my %args = @_;
88              
89 0           my $filename = $args{filename};
90 0   0       my $ci = $args{ignore_case} // 1;
91              
92             #use DD; dd \%EXTS;
93 0 0         my ($name, $ext) = $filename =~ ($ci ? $RE_CI : $RE_NOCI)
    0          
94             or return 0;
95             return {
96             exec_name => $name,
97             exec_ext => $ext,
98 0           exec_type => $EXTS{lc $ext},
99             };
100             }
101              
102             1;
103             # ABSTRACT: Check whether filename indicates being an executable program/script
104              
105             __END__