File Coverage

blib/lib/App/Codeowners/Formatter/String.pm
Criterion Covered Total %
statement 56 74 75.6
branch 11 20 55.0
condition 11 25 44.0
subroutine 12 14 85.7
pod 1 1 100.0
total 91 134 67.9


line stmt bran cond sub pod time code
1             package App::Codeowners::Formatter::String;
2             # ABSTRACT: Format codeowners output using printf-like strings
3              
4              
5 1     1   1093 use warnings;
  1         2  
  1         95  
6 1     1   8 use strict;
  1         2  
  1         81  
7              
8             our $VERSION = '0.49'; # VERSION
9              
10 1     1   8 use parent 'App::Codeowners::Formatter';
  1         2  
  1         28  
11              
12 1     1   169 use App::Codeowners::Util qw(stringf zip);
  1         2  
  1         177  
13 1     1   8 use Color::ANSI::Util 0.03 qw(ansifg);
  1         53  
  1         1247  
14              
15             sub stream {
16 6     6 1 15 my $self = shift;
17 6         24 my $result = shift;
18              
19 6         10 $result = {zip @{$self->columns}, @$result};
  6         32  
20              
21             my %info = (
22             F => $self->_create_filterer->($result->{File}, undef),
23             O => $self->_create_filterer->($result->{Owner}, $self->_owner_colorgen),
24             P => $self->_create_filterer->($result->{Project}, undef),
25 6         31 T => $self->_create_filterer->($result->{Pattern}, undef),
26             );
27              
28 6         39 my $text = stringf($self->format, %info);
29 6         14 print { $self->handle } $text, "\n";
  6         28  
30             }
31              
32             sub _expand_filter_args {
33 15   50 15   56 my $arg = shift || '';
34              
35 15         37 my @filters = split(/,/, $arg);
36 15         27 my $color_override;
37              
38 15         44 for (my $i = 0; $i < @filters; ++$i) {
39 0 0       0 my $filter = $filters[$i] or next;
40 0 0       0 if ($filter =~ /^(?:nocolor|color:([0-9a-fA-F]{3,6}))$/) {
41 0   0     0 $color_override = $1 || '';
42 0         0 splice(@filters, $i, 1);
43 0         0 redo;
44             }
45             }
46              
47 15         53 return (\@filters, $color_override);
48             }
49              
50 0     0   0 sub _ansi_reset { "\033[0m" }
51              
52             sub _colored {
53 15     15   26 my $text = shift;
54 15 100       42 my $rgb = shift or return $text;
55              
56 4 50 0     28 return $text if $ENV{NO_COLOR} || (defined $ENV{COLOR_DEPTH} && !$ENV{COLOR_DEPTH});
      33        
57              
58 0         0 $rgb =~ s/^(.)(.)(.)$/$1$1$2$2$3$3/;
59 0 0       0 if ($rgb !~ m/^[0-9a-fA-F]{6}$/) {
60 0         0 warn "Color value must be in 'ffffff' or 'fff' form.\n";
61 0         0 return $text;
62             }
63              
64 0         0 my ($begin, $end) = (ansifg($rgb), _ansi_reset);
65 0         0 return "${begin}${text}${end}";
66             }
67              
68             sub _create_filterer {
69 24     24   47 my $self = shift;
70              
71             my %filter = (
72 0     0   0 quote => sub { local $_ = $_[0]; s/"/\"/s; "\"$_\"" },
  0         0  
  0         0  
73 24         92 );
74              
75             return sub {
76 24   100 24   76 my $value = shift || '';
77 24   100     85 my $color = shift || '';
78 24 100       87 my $gencolor = ref($color) eq 'CODE' ? $color : sub { $color };
  9         27  
79             return sub {
80 15         27 my $arg = shift;
81 15         29 my ($filters, $color) = _expand_filter_args($arg);
82 15 100       37 if (ref($value) eq 'ARRAY') {
83 4   33     9 $value = join(',', map { _colored($_, $color // $gencolor->($_)) } @$value);
  4         73  
84             }
85             else {
86 11   33     32 $value = _colored($value, $color // $gencolor->($value));
87             }
88 15         35 for my $key (@$filters) {
89 0 0       0 if (my $filter = $filter{$key}) {
90 0         0 $value = $filter->($value);
91             }
92             else {
93 0         0 warn "Unknown filter: $key\n"
94             }
95             }
96 15 100       56 $value || '';
97 24         164 };
98 24         126 };
99             }
100              
101             sub _owner_colorgen {
102 6     6   16 my $self = shift;
103              
104             # https://sashat.me/2017/01/11/list-of-20-simple-distinct-colors/
105 6         51 my @contrasting_colors = qw(
106             e6194b 3cb44b ffe119 4363d8 f58231
107             911eb4 42d4f4 f032e6 bfef45 fabebe
108             469990 e6beff 9a6324 fffac8 800000
109             aaffc3 808000 ffd8b1 000075 a9a9a9
110             );
111              
112             # assign a color to each owner, on demand
113 6         13 my %owner_colors;
114 6         12 my $num = -1;
115             $self->{owner_color} ||= sub {
116 6 100   6   94 my $owner = shift or return;
117 4   33     29 $owner_colors{$owner} ||= do {
118 4         12 $num = ($num + 1) % scalar @contrasting_colors;
119 4         20 $contrasting_colors[$num];
120             };
121 6   100     155 };
122             }
123              
124             1;
125              
126             __END__