File Coverage

blib/lib/Log/ger/Output/Screen.pm
Criterion Covered Total %
statement 48 79 60.7
branch 26 48 54.1
condition 0 9 0.0
subroutine 9 9 100.0
pod 0 4 0.0
total 83 149 55.7


line stmt bran cond sub pod time code
1             package Log::ger::Output::Screen;
2              
3 2     2   4863 use strict;
  2         5  
  2         61  
4 2     2   12 use warnings;
  2         4  
  2         165  
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.018'; # VERSION
10              
11             if ($^O eq 'MSWin32') {
12             eval { require Win32::Console::ANSI };
13             }
14              
15 2     2   13 use Log::ger::Util;
  2         5  
  2         2342  
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 6630 v => 2,
42             } }
43              
44             sub _pick_color {
45 1     1   2 my ($level, $color_depth) = @_;
46 1 50       3 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 17 my ($ctx, $msg) = @_;
73 7 50       33 print { $ctx->{_fh} } "\n" unless $msg =~ /\R\z/;
  7         111  
74             }
75              
76             sub get_hooks {
77 4     4 0 56 my %plugin_conf = @_;
78              
79 4         8 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         7 my $use_color = do {
83 4 100       19 if (defined $plugin_conf{use_color}) {
    50          
    50          
84 1         2 $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       31 $stderr ? (-t STDERR) : (-t STDOUT); ## no critic: InputOutput::ProhibitInteractiveTest
91             }
92             };
93 4         9 my $color_depth = do {
94 4 100 0     18 if (defined $plugin_conf{color_depth}) {
    50 0        
    50          
    0          
    0          
95 1         1 $plugin_conf{color_depth};
96             } elsif (defined $ENV{COLOR_DEPTH}) {
97 0         0 $ENV{COLOR_DEPTH};
98             } elsif (!$use_color) {
99 3         7 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         9 my $formatter = $plugin_conf{formatter};
109              
110 4 50       10 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   10224 my %hook_args = @_; # see Log::ger::Manual::Internals/"Arguments passed to hook"
121             my $outputter = sub {
122 7         10258 my ($per_target_conf, $msg, $per_msg_conf) = @_;
123 7 100       25 my $level; $level = $per_msg_conf->{level} if $per_msg_conf; $level = $hook_args{level} unless defined $level;
  7 100       38  
  7         22  
124 7 50       16 if ($formatter) {
125 0         0 $msg = $formatter->($msg);
126             }
127 7         34 hook_before_log({ _fh=>$handle }, $msg);
128 7 100       22 if ($use_color) {
129 1         3 my $line_color = _pick_color($level, $color_depth);
130              
131 1 50       3 if ($plugin_conf{colorize_tags}) {
132              
133 0         0 my $prog_prefix;
134 0 0       0 if ($msg =~ s/\A([\w-]+:?\s*)//) {
135 0         0 $prog_prefix = $1;
136             }
137 0         0 my (@tags, @seps);
138 0         0 while ($msg =~ s/\A\[([^\]]+)\](\s*)//g) {
139 0         0 push @tags, $1;
140 0         0 push @seps, $2;
141             }
142             #use DD; dd {msg=>$msg, tags=>\@tags, prog_prefix=>$prog_prefix};
143 0 0       0 print $handle $line_color, $prog_prefix, "\e[0m" if defined $prog_prefix;
144 0         0 for my $i (0 .. $#tags) {
145 0         0 print $handle $line_color, "[", "\e[0m";
146             # XXX force ansifg() to use the same color depth as us
147 0         0 print $handle Color::ANSI::Util::ansifg( Color::RGB::Util::assign_rgb_light_color($tags[$i]) ), $tags[$i], "\e[0m", $line_color, "[", $seps[$i];
148             }
149 0         0 print $handle $line_color, $msg, "\e[0m";
150              
151             } else {
152 1         39 print $handle $line_color, $msg, "\e[0m";
153             }
154             } else {
155 6         211 print $handle $msg;
156             }
157 7         43 hook_after_log({ _fh=>$handle }, $msg);
158 16         75 };
159 16         39 [$outputter];
160 4         39 }],
161             };
162             }
163              
164             1;
165             # ABSTRACT: Output log to screen
166              
167             __END__