File Coverage

blib/lib/App/ShellCheckWiki.pm
Criterion Covered Total %
statement 14 87 16.0
branch 0 24 0.0
condition 0 2 0.0
subroutine 5 10 50.0
pod 0 5 0.0
total 19 128 14.8


line stmt bran cond sub pod time code
1             package App::ShellCheckWiki;
2              
3 1     1   52453 use 5.006;
  1         3  
4 1     1   4 use strict;
  1         2  
  1         16  
5 1     1   4 use warnings;
  1         1  
  1         29  
6              
7 1     1   501 use Term::ANSIColor;
  1         6668  
  1         52  
8 1     1   608 use WWW::Mechanize;
  1         125773  
  1         689  
9              
10             our $VERSION = '0.03';
11              
12             my $formats = {
13             '# ' => 'bold green', # H1
14             '## ' => 'bold magenta', # H2
15             '### ' => 'bold red', # H3
16             '```' => 'yellow', # Code Block
17             };
18              
19             my $wiki_url = 'https://raw.githubusercontent.com/wiki/koalaman/shellcheck';
20             my $wiki_toc = 'https://github.com/koalaman/shellcheck/wiki';
21              
22             my $mech = WWW::Mechanize->new( autocheck => 0 );
23              
24             sub run {
25 0     0 0   my $page = $ARGV[0];
26 0 0         if (defined($page)) {
27 0           my ($page_id) = $page =~ m|(\d+)$|;
28 0           my $wiki_page = $wiki_url . '/SC' . $page_id . '.md';
29 0           $mech->get($wiki_page);
30 0 0         if ($mech->success) {
31 0           print colored(['green'],"ShellCheck Error CS$page_id\n");
32 0           format_page($mech->content());
33             } else {
34 0           print "Unable to find page '$page'!\n";
35 0           show_topics();
36             }
37             } else {
38 0           show_topics();
39             }
40 0           exit 0;
41             }
42              
43             sub format_page {
44 0     0 0   my ($content) = @_;
45 0           my $indent = 0;
46 0           my $code_block = '```';
47 0   0       my $code_block_format = $formats->{$code_block} || 'yellow';
48              
49 0           for my $line ( split /\n/, $content ) {
50 0           my $matched = 0;
51 0           for my $start ( sort keys %$formats ) {
52 0 0         if ( my ($remainder) = starts_with( $line, $start ) ) {
53 0           $matched = 1;
54 0           my $format = $formats->{$start};
55 0 0         if ( $start eq $code_block ) {
56 0           $indent = ( $indent + 1 ) % 2;
57 0           $code_block_format = $format;
58 0           print "\n";
59             } else {
60 0           print $start;
61 0           print colored( [$format], $remainder )."\n";
62             }
63             }
64             }
65              
66             # Regular Line or Code Block
67 0 0         if ( not $matched ) {
68 0 0         if ($indent) {
69             # Code Block
70 0           print colored( [$code_block_format], " $line\n" );
71             } else {
72             # Regular Line
73 0           print $line . "\n";
74             }
75             }
76             }
77 0           print "\n";
78             }
79              
80             sub starts_with {
81 0     0 0   my ($line, $format) = @_;
82 0 0         return unless length($line) >= length($format);
83 0           my $start = substr($line,0,length($format),'');
84 0 0         return unless $start eq $format;
85 0           return $line;
86             }
87              
88             sub show_topics {
89 0     0 0   print colored(['bold magenta'], "Checking for Available Topics: ");
90 0           print colored(['green'], "SCxxxx\n");
91 0           $mech->get($wiki_toc);
92 0           my $topics = {};
93 0 0         if ($mech->success()) {
94 0           for my $link ($mech->links()) {
95 0 0         next unless $link->url =~ m|SC(\d+)|;
96 0           $topics->{$1}++;
97             }
98 0           my @ranges = number_range( keys %$topics );
99 0           for my $range (@ranges) {
100 0           print colored(['cyan'], $range . "\n");
101             }
102             } else {
103 0           print "FAIL!";
104             }
105             }
106              
107             sub number_range {
108 0     0 0   my (@numbers) = sort { $a <=> $b } @_;
  0            
109 0           my @ranges;
110 0           my $start = shift @numbers;
111 0           my $stop = $start;
112 0           while(scalar @numbers) {
113 0           my $next = shift @numbers;
114 0 0         if ( $next == $stop + 1 ) {
115 0           $stop = $next;
116             } else {
117 0 0         if ($start == $stop) {
118 0           push @ranges, $start;
119             } else {
120 0           push @ranges, $start . '-' . $stop;
121             }
122 0           $start = $stop = $next;
123             }
124             }
125              
126             # Group by Leading digits;
127 0           my $groups;
128 0           for my $range (@ranges) {
129 0           my $leading = substr($range,0,2);
130 0           push @{ $groups->{$leading} }, $range;
  0            
131             }
132 0           my @output_ranges;
133 0           for my $leading ( sort keys %$groups ) {
134 0           push @output_ranges, join(',', sort @{ $groups->{$leading} });
  0            
135             }
136              
137 0           return @output_ranges;
138             }
139              
140             1; # End of App::ShellCheckWiki
141             __END__