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