File Coverage

blib/lib/App/week.pm
Criterion Covered Total %
statement 76 166 45.7
branch 2 42 4.7
condition 0 22 0.0
subroutine 23 33 69.7
pod 0 13 0.0
total 101 276 36.5


line stmt bran cond sub pod time code
1             package App::week;
2             our $VERSION = "1.07";
3              
4 4     4   239928 use v5.24;
  4         13  
5 4     4   29 use warnings;
  4         11  
  4         213  
6              
7 4     4   1956 use utf8;
  4         1062  
  4         29  
8 4     4   1759 use Encode;
  4         69342  
  4         422  
9 4     4   2304 use Time::localtime;
  4         23385  
  4         346  
10 4     4   37 use List::Util qw(min max);
  4         7  
  4         653  
11 4     4   2520 use Hash::Util qw(lock_keys);
  4         20141  
  4         42  
12 4     4   3325 use Pod::Usage;
  4         257497  
  4         670  
13 4     4   2979 use Data::Dumper;
  4         36193  
  4         378  
14 4     4   2541 use open IO => ':utf8', ':std';
  4         6779  
  4         27  
15 4     4   2719 use Getopt::EX::Colormap;
  4         337926  
  4         276  
16              
17 4     4   2342 use App::week::Util;
  4         12  
  4         190  
18 4     4   1926 use App::week::CalYear qw(@calyear);
  4         15  
  4         764  
19              
20             my @DOW_LABELS = qw(
21             DOW_SU
22             DOW_MO
23             DOW_TU
24             DOW_WE
25             DOW_TH
26             DOW_FR
27             DOW_SA
28             DOW_CW
29             );
30              
31             my %DEFAULT_COLORMAP = (
32             (), DAYS => "L05/335",
33             (), WEEK => "L05/445",
34             (), FRAME => "L05/445",
35             (), MONTH => "L05/335",
36             (), THISDAY => "522/113",
37             (), THISDAYS => "555/113",
38             (), THISWEEK => "L05/445",
39             (), THISMONTH => "555/113",
40             map { $_ => "" } @DOW_LABELS,
41             );
42              
43 4     4   2527 use Getopt::EX::Hashed; {
  4         16766  
  4         29  
44              
45             Getopt::EX::Hashed->configure(DEFAULT => [ is => 'rw' ]);
46              
47             has ARGV => default => [];
48             has COLORMAP => ;
49             has CM => ;
50              
51             my($sec, $min, $hour, $mday, $mon, $year) = CORE::localtime(time);
52             has year => default => $year + 1900;
53             has mday => default => $mday;
54             has mon => default => $mon + 1;
55              
56             has cell_width => default => undef;
57 4     4   886 has frame => default => "\N{NBSP}\N{NBSP}";
  4         6  
  4         34  
58             has frame_height => default => 1;
59              
60             # option params
61             has help => ' h ' ;
62             has version => ' v ' ;
63             has months => ' m =i ' , default => 0;
64             has after => ' A :1 ' , min => 0;
65             has before => ' B :1 ' , min => 0, default => 1;
66             has center => ' C :4 ' , min => 0;
67             has column => ' c =i ' , min => 1, default => 3;
68             has colordump => ' ' ;
69             has colormap => ' =s@ cm ' , default => [];
70             has show_year => ' y ' ;
71             has years => ' Y :1 ' , max => 100;
72             has rgb24 => ' ! ' ;
73             has year_on_all => ' P ' ;
74             has year_on => ' p =i ' , min => 0, max => 12;
75             has config => ' =s% ' , default => {};
76             has weeknumber => ' W :1 ' ;
77              
78             has '+center' => sub {
79             $_->after = $_->before = $_[1];
80             };
81              
82             has '+weeknumber' => sub {
83             App::week::CalYear::Configure $_[0] => $_[1];
84             };
85              
86             has '+rgb24' => sub {
87             $Getopt::EX::Colormap::RGB24 = !!$_[1];
88             };
89              
90             has '+config' => sub {
91             App::week::CalYear::Configure $_[1] => $_[2];
92             };
93              
94             has '+help' => sub {
95             pod2usage
96             -verbose => 99,
97             -sections => [ qw(SYNOPSIS VERSION) ];
98             };
99              
100             has '+version' => sub {
101             print "Version: $VERSION\n";
102             exit;
103             };
104              
105             has "<>" => sub {
106             my $obj = $_;
107             local $_ = $_[0];
108             if (/^-+([0-9]+)$/) {
109             $obj->months = $1;
110             } elsif (/^-/) {
111             die "$_: Option error\n";
112             } else {
113             push @{$obj->ARGV}, $_;
114             }
115             };
116              
117 4     4   4327 } no Getopt::EX::Hashed;
  4         8  
  4         18  
118              
119             sub color {
120 0     0 0 0 (+shift)->CM->color(@_);
121             }
122              
123             sub usage {
124 0     0 0 0 pod2usage(-verbose => 0, -exitval => "NOEXIT");
125 0         0 print "Version: $VERSION\n";
126 0         0 exit 2;
127             }
128              
129             sub run {
130 3     3 0 2965 my $app = shift;
131 3         24 local @ARGV = decode_argv @_;
132              
133 3         130 $app->read_option()
134             ->argv()
135             ->deal_option()
136             ->prepare()
137             ->show();
138              
139 0         0 return 0;
140             }
141              
142             sub read_option {
143 3     3 0 7 my $app = shift;
144 4     4   3300 use Getopt::EX::Long qw(:DEFAULT Configure ExConfigure);
  4         81990  
  4         3055  
145 3         41 ExConfigure BASECLASS => [ "App::week", "Getopt::EX", "" ];
146 3         168 Configure qw(bundling no_getopt_compat no_ignore_case pass_through);
147 3 50       260 $app->getopt || usage;
148 1         3435 return $app;
149             }
150              
151             sub argv {
152 1     1 0 3 my $app = shift;
153 1         2 for (@{$app->ARGV}) {
  1         3  
154 0         0 call \&guess_date,
155             for => $app,
156             with => [ qw(year mon mday show_year) ];
157             }
158 1         9 return $app;
159             }
160              
161             sub deal_option {
162 1     1 0 2 my $app = shift;
163              
164             # load --colormap option
165 1         13 my %colormap = %DEFAULT_COLORMAP;
166 1         4 $app->COLORMAP = \%colormap;
167             $app->CM = Getopt::EX::Colormap
168             ->new(HASH => \%colormap)
169 1         11 ->load_params(@{$app->colormap});
  1         62  
170              
171             # --colordump
172 1 50       19 if ($app->colordump) {
173 1         5 print $app->CM->colormap(
174             name => '--changeme',
175             option => '--colormap');
176 1         204 exit;
177             }
178              
179             # -p, -P
180 0 0 0       $app->year_on //= $app->mon if $app->mday;
181 0 0         if ($app->year_on_all) {
    0          
182 0           App::week::CalYear::Configure show_year => [ 1..12 ];
183             }
184             elsif (defined(my $m = $app->year_on)) {
185 0 0 0       if ($m < 0 or 12 < $m) {
186 0           die "$m: Month must be within 0 to 12\n";
187             }
188             App::week::CalYear::Configure
189 0           show_year => { $app->year => $m, '*' => 1 };
190             } else {
191 0           App::week::CalYear::Configure show_year => 1;
192             }
193              
194             # -y, -Y
195 0 0 0       $app->years //= 1 if $app->show_year;
196              
197 0           return $app;
198             }
199              
200             sub prepare {
201 0     0 0   my $app = shift;
202 0           call \&_prepare,
203             for => $app,
204             with => [ qw(years months before after year mon column) ];
205 0           return $app;
206             }
207              
208             sub _prepare {
209 0     0     my @args = \(
210             my($years, $months, $before, $after, $year, $mon, $column) = @_
211             );
212              
213 4     4   41 use integer;
  4         7  
  4         35  
214 0 0         if ($months == 1) {
    0          
    0          
215 0           $before = $after = 0;
216             }
217             elsif ($months > 1) {
218 0 0         if (defined $before) {
    0          
219 0           $after = $months - $before - 1;
220             } elsif (defined $after) {
221 0           $before = $months - $after - 1;
222             } else {
223 0           $before = ($months - 1) / 2;
224 0           $after = $months - $before - 1;
225             }
226             }
227             elsif ($years) {
228 0   0       $months = 12 * ($years // 1);
229 0           $before = $mon - 1;
230 0           $after = $months - $mon;
231             }
232             else {
233 0   0       $before //= 1;
234 0   0       $after //= max(0, $column - $before - 1);
235 0           $months = $before + $after + 1;
236             }
237              
238 0   0       $before //= 1;
239 0   0       $after //= 1;
240              
241 0 0         $year += $year < 50 ? 2000 : $year < 100 ? 1900 : 0;
    0          
242              
243 0           map ${$_}, @args;
  0            
244             }
245              
246             sub show {
247 0     0 0   my $app = shift;
248             $app->display(
249             map {
250 0 0         $app->cell( $app->year,
  0            
251             $app->mon + $_,
252             $_ ? () : $app->mday )
253             } -$app->before .. $app->after
254             );
255 0           return $app;
256             }
257              
258             ######################################################################
259              
260             sub display {
261 0     0 0   my $obj = shift;
262 0 0         @_ or return;
263 0           $obj->h_rule(min($obj->column, int @_));
264 0           while (@_) {
265 0           my @cell = splice @_, 0, $obj->column;
266 0           for my $row (transpose @cell) {
267 0           $obj->h_line(@{$row});
  0            
268             }
269 0           $obj->h_rule(int @cell);
270             }
271             }
272              
273             sub h_rule {
274 0     0 0   my $obj = shift;
275 0           my $column = shift;
276 4     4   1906 my $hr1 = "\N{NBSP}" x $obj->cell_width;
  4         7  
  4         34  
  0            
277 0           my $s = join($obj->frame, '', ($hr1) x $column, '');
278 0           my $rule = $obj->color(FRAME => $s) . "\n";
279 0           print $rule x $obj->frame_height;
280             }
281              
282             sub h_line {
283 0     0 0   my $obj = shift;
284 0           my $frame = $obj->color(FRAME => $obj->frame);
285 0           print join($frame, '', @_, '') . "\n";
286             }
287              
288             sub cell {
289 0     0 0   my $obj = shift;
290 0           my($y, $m, $d) = @_;
291              
292 0           while ($m > 12) { $y += 1; $m -= 12 }
  0            
  0            
293 0           while ($m <= 0) { $y -= 1; $m += 12 }
  0            
  0            
294              
295 0           my @cal = @{$calyear[$y][$m]};
  0            
296              
297             # XXX this is not the best place to initialize...
298 0   0       $obj->cell_width //= length $cal[2];
299              
300 0           my %label;
301 0 0         @label{qw(month week days)} = $d
302             ? qw(THISMONTH THISWEEK THISDAYS)
303             : qw( MONTH WEEK DAYS);
304              
305 0           $cal[0] = $obj->color($label{month}, $cal[0]);
306             $cal[1] = $obj->color($label{week},
307 0           state $week = $obj->week_line($cal[1]));
308 0 0         my $day_re = $d ? qr/^(?:.[ \d]{2}){0,6}.\K(${\(sprintf '%2d', $d)})\b/ : undef;
  0            
309 0           for (@cal[ 2 .. $#cal ]) {
310 0 0         s/$day_re/$obj->color("THISDAY", $1)/e if $day_re;
  0            
311 0           $_ = $obj->color($label{days}, $_);
312             }
313              
314 0           return \@cal;
315             }
316              
317             sub week_line {
318 0     0 0   my $obj = shift;
319 0           my $week = shift;
320 0           my @week = split_week $week;
321 0           for (0..7) {
322 0 0         if (my $color = $obj->COLORMAP->{$DOW_LABELS[$_]}) {
323 0           my $i = $_ * 2 + 1;
324 0 0         $i > $#week and last;
325 0           $week[$i] = $obj->color($color, $week[$i]);
326             }
327             }
328 0           join '', @week;
329             }
330              
331             1;
332              
333             __END__