File Coverage

/root/.cpan/build/Thunderhorse-0.102-0/bin/thunderhorse
Criterion Covered Total %
statement 103 107 96.2
branch 20 26 76.9
condition 6 6 100.0
subroutine 18 18 100.0
pod n/a
total 147 157 93.6


line stmt bran cond sub pod time code
1             #!/usr/bin/env perl
2              
3 11     11   66201 use v5.40;
  11         43  
4 11     11   5423 use Gears::Generator;
  11         5474216  
  11         580  
5              
6 11     11   8821 use Getopt::Long;
  11         165238  
  11         55  
7 11     11   8611 use Pod::Usage;
  11         880529  
  11         1609  
8 11     11   124 use Path::Tiny qw(path);
  11         28  
  11         655  
9 11     11   63 use List::Util qw(first);
  11         19  
  11         649  
10 11     11   63 use File::Spec;
  11         20  
  11         407  
11 11     11   7219 use Data::Dumper;
  11         103461  
  11         1232  
12              
13 11     11   113 use constant EX_DIR => path(__FILE__)->parent->parent->child('ex');
  11         22  
  11         83  
14              
15             # try loading app from '.' and 'lib' directories. Dot is required for "do
16             # 'app.pl'" to work.
17 11     11   10090 use lib '.', 'lib';
  11         9282  
  11         81  
18              
19             # autoflush stdout
20 11         1627969 $|++;
21              
22             # prettier Data::Dumper output
23 11         42 $Data::Dumper::Sortkeys = true;
24 11         34 $Data::Dumper::Indent = 1;
25              
26 11         24 my $generate;
27 11         27 my $config = false;
28 11         32 my $locations = false;
29 11         24 my $tabs = false;
30 11         25 my $help = false;
31 11         26 my $error = false;
32              
33 11 50       106 GetOptions(
34             'g|generate=s' => \$generate,
35             'c|show-config' => \$config,
36             'l|show-locations' => \$locations,
37             't|tabs' => \$tabs,
38             'h|help' => \$help,
39             ) or $error = true;
40              
41             my $target = shift
42             or $help
43 11 100 100     12859 or do { warn "no target specified\n"; $error = true };
  1         29  
  1         11  
44              
45             # handle actions
46 11 100 100     114 if ($help || $error) {
    100          
    100          
    50          
47 2 100       20 pod2usage($error ? 1 : 0);
48             }
49              
50             elsif (defined $generate) {
51 7         258 print "Generating project from template $generate... ";
52              
53 7         127 my $generator = Gears::Generator->new(base_dir => EX_DIR);
54 7         33216 my $namespace = get_template_namespace($generator, $generate);
55              
56 7 50       32 if (defined $namespace) {
57 7         248 my $file = File::Spec->join(split /::/, $namespace);
58 7         65 my $target_file = File::Spec->join(split /::/, $target);
59              
60 44     44   73163 push $generator->name_filters->@*, sub ($name) {
  44         90  
  44         72  
61 44         677 return $name =~ s{\b\Q$file\E}{$target_file}r;
62 7         62 };
63              
64 44     44   720 push $generator->content_filters->@*, sub ($content) {
  44         97  
  44         108  
65 44         611 return $content =~ s{\b\Q$namespace\E}{$target}rg;
66 7         49 };
67             }
68              
69 7 100       29 if (!$tabs) {
70 36     36   134 push $generator->content_filters->@*, sub ($content) {
  36         65  
  36         50  
71 36         1377 return $content =~ s{\t}{ }rg;
72 6         30 };
73             }
74              
75 7         45 $generator->generate($generate, '.');
76 7         0 say 'done.';
77             }
78              
79             elsif ($config) {
80 1         3 my $app = load_app($target);
81 1         24 print Data::Dumper->Dump([$app->config->config], ['*config']);
82             }
83              
84             elsif ($locations) {
85 1         10 my $app = load_app($target);
86 1         4 print Data::Dumper->Dump([get_readable_locations($app)], ['*locations']);
87             }
88              
89             else {
90 0         0 warn "No action specified\n";
91 0         0 pod2usage(1);
92             }
93              
94             sub load_app ($target)
95 2     2   8 {
  2         5  
  2         3  
96 2         23 local $ENV{THUNDERHORSE_SCRIPT} = true;
97 2         32 local $0 = $target;
98 2         758 return do $target;
99             }
100              
101 7         17 sub get_template_namespace ($generator, $template)
102 7     7   26 {
  7         16  
  7         14  
103 7         94 my $files = $generator->get_template($template);
104 7     7   16116 my $app_file = first { $_ =~ /app\.pl$/ } $files->@*;
  7         33  
105              
106 7 50       97 return undef unless defined $app_file;
107 7         38 my $app_file_content = $app_file->slurp;
108              
109 7 100       1814 return $1
110             if $app_file_content =~ /^package ([\w:]+)/m;
111              
112 6 50       139 return $1
113             if $app_file_content =~ /^\s*([\w:]+)->new/m;
114              
115 0         0 return undef;
116             }
117              
118             sub _recurse_locations ($level)
119 1     1   2 {
  1         1  
  1         2  
120 1         1 my @out;
121 1         5 foreach my $loc (sort { $a->order <=> $b->order } $level->@*) {
  1         7  
122 2         26 my $this_location = {
123             pattern => $loc->pattern,
124             name => $loc->name,
125             controller => ref $loc->controller,
126             handler => $loc->to,
127             action => $loc->action,
128             };
129              
130 2 50       27 if ($loc->is_bridge) {
131 0         0 push @out, [$this_location, _recurse_locations($loc->locations)];
132             }
133             else {
134 2         18 push @out, $this_location;
135             }
136             }
137              
138 1         12 return @out;
139             }
140              
141             sub get_readable_locations ($app)
142 1     1   1 {
  1         2  
  1         1  
143 1         4 return [_recurse_locations $app->router->locations];
144             }
145              
146             __END__