File Coverage

blib/lib/Log/ger/Output/Screen.pm
Criterion Covered Total %
statement 48 77 62.3
branch 26 48 54.1
condition 0 9 0.0
subroutine 9 9 100.0
pod 0 4 0.0
total 83 147 56.4


line stmt bran cond sub pod time code
1             package Log::ger::Output::Screen;
2              
3 2     2   4295 use strict;
  2         4  
  2         52  
4 2     2   8 use warnings;
  2         2  
  2         144  
5              
6             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
7             our $DATE = '2022-01-16'; # DATE
8             our $DIST = 'Log-ger-Output-Screen'; # DIST
9             our $VERSION = '0.019'; # VERSION
10              
11             if ($^O eq 'MSWin32') {
12             eval { require Win32::Console::ANSI };
13             }
14              
15 2     2   10 use Log::ger::Util;
  2         4  
  2         2110  
16              
17             our %colors_16 = (
18             10 => "\e[31m" , # fatal , red
19             20 => "\e[35m" , # error , magenta
20             30 => "\e[1;34m", # warning, light blue
21             40 => "\e[32m" , # info , green
22             50 => "", # debug , no color
23             60 => "\e[33m" , # trace , orange
24             );
25              
26             our %colors_256 = (
27             # pastel'ish, all brighter and avoid pure red/blue which is hard to see on
28             # laptop screen in a bright environment
29              
30             10 => "\e[1;38;5;160m", # fatal , bright red3
31             20 => "\e[1;38;5;163m", # error , bright magenta3
32             30 => "\e[1;38;5;69m" , # warning, bright cornflowerblue
33             40 => "\e[1;38;5;113m", # info , bright darkolivegreen3
34             50 => "" , # debug , no color
35             60 => "\e[1;38;5;130m", # trace , bright darkorange3
36             );
37              
38             our %level_map;
39              
40             sub meta { +{
41 4     4 0 6448 v => 2,
42             } }
43              
44             sub _pick_color {
45 1     1   4 my ($level, $color_depth) = @_;
46 1 50       4 my $colors = $color_depth >= 256 ? \%colors_256 : \%colors_16;
47 1 50       5 if (defined(my $c = $colors->{$level})) {
48 1         3 return $c;
49             }
50 0 0       0 if (defined(my $clevel = $level_map{$level})) {
51 0         0 return $colors->{$clevel};
52             }
53              
54             # find the nearest
55 0         0 my ($dist, $clevel);
56 0         0 for my $k (keys %$colors) {
57 0         0 my $d = abs($k - $level);
58 0 0 0     0 if (!defined($dist) || $dist > $d) {
59 0         0 $dist = $d;
60 0         0 $clevel = $k;
61             }
62             }
63 0         0 $level_map{$level} = $clevel;
64 0         0 return $colors->{$clevel};
65             }
66              
67             sub hook_before_log {
68 7     7 0 15 my ($ctx, $msg) = @_;
69             }
70              
71             sub hook_after_log {
72 7     7 0 16 my ($ctx, $msg) = @_;
73 7 50       36 print { $ctx->{_fh} } "\n" unless $msg =~ /\R\z/;
  7         94  
74             }
75              
76             sub get_hooks {
77 4     4 0 53 my %plugin_conf = @_;
78              
79 4         9 my $stderr = $plugin_conf{stderr};
80 4 100       14 $stderr = 1 unless defined $stderr;
81 4 100       13 my $handle = $stderr ? \*STDERR : \*STDOUT;
82 4         8 my $use_color = do {
83 4 100       16 if (defined $plugin_conf{use_color}) {
    50          
    50          
84 1         3 $plugin_conf{use_color};
85             } elsif (exists $ENV{NO_COLOR}) {
86 0         0 0;
87             } elsif (defined $ENV{COLOR}) {
88 0         0 $ENV{COLOR};
89             } else {
90 3 100       27 $stderr ? (-t STDERR) : (-t STDOUT); ## no critic: InputOutput::ProhibitInteractiveTest
91             }
92             };
93 4         10 my $color_depth = do {
94 4 100 0     20 if (defined $plugin_conf{color_depth}) {
    50 0        
    50          
    0          
    0          
95 1         4 $plugin_conf{color_depth};
96             } elsif (defined $ENV{COLOR_DEPTH}) {
97 0         0 $ENV{COLOR_DEPTH};
98             } elsif (!$use_color) {
99 3         8 0;
100             } elsif (defined $ENV{COLORTERM} && $ENV{COLORTERM} eq 'truecolor') {
101 0         0 16777216;
102             } elsif (defined $ENV{TERM} && $ENV{TERM} =~ /256color/) {
103 0         0 256;
104             } else {
105 0         0 16;
106             }
107             };
108 4         7 my $formatter = $plugin_conf{formatter};
109              
110 4 50       12 if ($plugin_conf{colorize_tags}) {
111 0         0 require Color::ANSI::Util;
112 0         0 require Color::RGB::Util;
113             }
114              
115             return {
116             create_outputter => [
117             __PACKAGE__, # key
118             50, # priority
119             sub { # hook
120 16     16   16246 my %hook_args = @_; # see Log::ger::Manual::Internals/"Arguments passed to hook"
121             my $outputter = sub {
122 7         8909 my ($per_target_conf, $msg, $per_msg_conf) = @_;
123 7 100       31 my $level; $level = $per_msg_conf->{level} if $per_msg_conf; $level = $hook_args{level} unless defined $level;
  7 100       34  
  7         23  
124 7 50       17 if ($formatter) {
125 0         0 $msg = $formatter->($msg);
126             }
127 7         28 hook_before_log({ _fh=>$handle }, $msg);
128 7 100       17 if ($use_color) {
129 1         4 my $line_color = _pick_color($level, $color_depth);
130              
131 1 50       4 if ($plugin_conf{colorize_tags}) {
132 0         0 my $prog_prefix;
133 0 0       0 if ($msg =~ s/\A([\w-]+:?\s*)//) {
134 0         0 $prog_prefix = $1;
135             }
136 0         0 my (@tags, @seps);
137 0         0 while ($msg =~ s/\A\[([^\]]+)\](\s*)//g) {
138 0         0 push @tags, $1;
139 0         0 push @seps, $2;
140             }
141             #use DD; dd {msg=>$msg, tags=>\@tags, prog_prefix=>$prog_prefix};
142 0 0       0 print $handle $line_color, $prog_prefix, "\e[0m" if defined $prog_prefix;
143 0         0 for my $i (0 .. $#tags) {
144             # XXX force ansifg() to use the same color depth as us
145 0         0 print $handle (
146             $line_color, "[", "\e[0m",
147             Color::ANSI::Util::ansifg( Color::RGB::Util::assign_rgb_light_color($tags[$i]) ), $tags[$i], "\e[0m",
148             $line_color, "]", $seps[$i], "\e[0m",
149             );
150             }
151             }
152              
153 1         47 print $handle $line_color, $msg, "\e[0m";
154              
155             } else {
156 6         239 print $handle $msg;
157             }
158 7         40 hook_after_log({ _fh=>$handle }, $msg);
159 16         55 };
160 16         44 [$outputter];
161 4         34 }],
162             };
163             }
164              
165             1;
166             # ABSTRACT: Output log to screen
167              
168             __END__