]> Dogcows Code - chaz/git-codeowners/blobdiff - lib/App/Codeowners/Formatter/String.pm
refactor formatters
[chaz/git-codeowners] / lib / App / Codeowners / Formatter / String.pm
diff --git a/lib/App/Codeowners/Formatter/String.pm b/lib/App/Codeowners/Formatter/String.pm
new file mode 100644 (file)
index 0000000..6421783
--- /dev/null
@@ -0,0 +1,132 @@
+package App::Codeowners::Formatter::String;
+# ABSTRACT: Format codeowners output using printf-like strings
+
+=head1 DESCRIPTION
+
+This is a L<App::Codeowners::Formatter> that formats output using a printf-like string.
+
+See L<git-codeowners/"Format string">.
+
+=cut
+
+use warnings;
+use strict;
+
+our $VERSION = '9999.999'; # VERSION
+
+use parent 'App::Codeowners::Formatter';
+
+use App::Codeowners::Util qw(stringf zip);
+use Color::ANSI::Util 0.03 qw(ansifg);
+use Encode qw(encode);
+
+sub stream {
+    my $self    = shift;
+    my $result  = shift;
+
+    $result = {zip @{$self->columns}, @$result};
+
+    my %info = (
+        F => $self->_create_filterer->($result->{File},    undef),
+        O => $self->_create_filterer->($result->{Owner},   $self->_owner_colorgen),
+        P => $self->_create_filterer->($result->{Project}, undef),
+        T => $self->_create_filterer->($result->{Pattern}, undef),
+    );
+
+    my $text = stringf($self->format, %info);
+    print { $self->handle } encode('UTF-8', $text), "\n";
+}
+
+sub _expand_filter_args {
+    my $arg = shift || '';
+
+    my @filters = split(/,/, $arg);
+    my $color_override;
+
+    for (my $i = 0; $i < @filters; ++$i) {
+        my $filter = $filters[$i] or next;
+        if ($filter =~ /^(?:nocolor|color:([0-9a-fA-F]{3,6}))$/) {
+            $color_override = $1 || '';
+            splice(@filters, $i, 1);
+            redo;
+        }
+    }
+
+    return (\@filters, $color_override);
+}
+
+sub _ansi_reset { "\033[0m" }
+
+sub _colored {
+    my $text = shift;
+    my $rgb  = shift or return $text;
+
+    return $text if $ENV{NO_COLOR};
+
+    $rgb =~ s/^(.)(.)(.)$/$1$1$2$2$3$3/;
+    if ($rgb !~ m/^[0-9a-fA-F]{6}$/) {
+        warn "Color value must be in 'ffffff' or 'fff' form.\n";
+        return $text;
+    }
+
+    my ($begin, $end) = (ansifg($rgb), _ansi_reset);
+    return "${begin}${text}${end}";
+}
+
+sub _create_filterer {
+    my $self = shift;
+
+    my %filter = (
+        quote   => sub { local $_ = $_[0]; s/"/\"/s; "\"$_\"" },
+    );
+
+    return sub {
+        my $value = shift || '';
+        my $color = shift || '';
+        my $gencolor = ref($color) eq 'CODE' ? $color : sub { $color };
+        return sub {
+            my $arg = shift;
+            my ($filters, $color) = _expand_filter_args($arg);
+            if (ref($value) eq 'ARRAY') {
+                $value = join(',', map { _colored($_, $color // $gencolor->($_)) } @$value);
+            }
+            else {
+                $value = _colored($value, $color // $gencolor->($value));
+            }
+            for my $key (@$filters) {
+                if (my $filter = $filter{$key}) {
+                    $value = $filter->($value);
+                }
+                else {
+                    warn "Unknown filter: $key\n"
+                }
+            }
+            $value || '';
+        };
+    };
+}
+
+sub _owner_colorgen {
+    my $self = shift;
+
+    # https://sashat.me/2017/01/11/list-of-20-simple-distinct-colors/
+    my @contrasting_colors = qw(
+        e6194b 3cb44b ffe119 4363d8 f58231
+        911eb4 42d4f4 f032e6 bfef45 fabebe
+        469990 e6beff 9a6324 fffac8 800000
+        aaffc3 808000 ffd8b1 000075 a9a9a9
+    );
+
+    # assign a color to each owner, on demand
+    my %owner_colors;
+    my $num = -1;
+    $self->{owner_color} ||= sub {
+        my $owner = shift or return;
+        $owner_colors{$owner} ||= do {
+            $num = ($num + 1) % scalar @contrasting_colors;
+            $contrasting_colors[$num];
+        };
+    };
+}
+
+1;
This page took 0.021768 seconds and 4 git commands to generate.