File Coverage

blib/lib/App/Colorist.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             package App::Colorist;
2             $App::Colorist::VERSION = '0.141760';
3 1     1   1528 use Moose;
  0            
  0            
4              
5             with 'MooseX::Getopt';
6              
7             use App::Colorist::Colorizer;
8              
9             use IPC::Open3;
10              
11             # ABSTRACT: Add color to your plain old outputs
12              
13              
14             has configuration => (
15             is => 'ro',
16             isa => 'Str',
17             traits => [ 'Getopt' ],
18             cmd_aliases => [ qw(c) ],
19             lazy_build => 1,
20             );
21              
22             sub _build_configuration {
23             my $self = shift;
24              
25             return $self->extra_argv->[0] if $self->execute;
26             return;
27             }
28              
29             has ruleset => (
30             is => 'ro',
31             isa => 'Str',
32             required => 1,
33             traits => [ 'Getopt' ],
34             cmd_aliases => [ qw(R) ],
35             default => 'rules',
36             );
37              
38             has colorset => (
39             is => 'ro',
40             isa => 'Str',
41             required => 1,
42             traits => [ 'Getopt' ],
43             cmd_aliases => [ qw(C) ],
44             default => 'colors',
45             );
46              
47             has include => (
48             is => 'ro',
49             isa => 'ArrayRef',
50             required => 1,
51             traits => [ 'Getopt' ],
52             cmd_aliases => [ qw(I) ],
53             default => sub { [] },
54             );
55              
56             has debug => (
57             is => 'ro',
58             isa => 'Bool',
59             required => 1,
60             default => 0,
61             );
62              
63             has execute => (
64             is => 'ro',
65             isa => 'Bool',
66             traits => [ 'Getopt' ],
67             cmd_aliases => [ qw(e) ],
68             lazy_build => 1,
69             );
70              
71             sub _build_execute {
72             my $self = shift;
73             return $self->stderr ? 1 : 0;
74             }
75              
76             has stderr => (
77             is => 'ro',
78             isa => 'Bool',
79             required => 1,
80             traits => [ 'Getopt' ],
81             cmd_aliases => [ qw(E) ],
82             default => 0,
83             );
84              
85             # I would like to have this someday...
86             # has follow => (
87             # is => 'ro',
88             # isa => 'Bool',
89             # required => 1,
90             # default => 0,
91             # );
92              
93             has _colorizer => (
94             reader => 'colorizer',
95             isa => 'App::Colorist::Colorizer',
96             lazy_build => 1,
97             handles => [ 'run' ],
98             );
99              
100             sub _build__colorizer {
101             my $self = shift;
102              
103             my @args = @{ $self->extra_argv };
104              
105             my %params;
106              
107             # The command-line contains the command to run and arguments to it
108             if ($self->execute) {
109              
110             # They have asked us to capture STDERR too
111             if ($self->stderr) {
112             open3('<&STDIN', my $outfh, my $errfh, @args);
113             $params{inputs} = [ $outfh, $errfh ];
114             }
115              
116             # They have asked us to capture just STDOUT
117             else {
118             open my $fh, '-|', @args or die "cannot execute ", join(' ', @args), ": ", $!;
119             $params{inputs} = [ $fh ];
120             }
121             }
122              
123             # Otherwise, we use the default input reading from ARGV
124              
125             return App::Colorist::Colorizer->new(
126             configuration => $self->configuration,
127             ruleset => $self->ruleset,
128             colorset => $self->colorset,
129             include => $self->include,
130             debug => $self->debug,
131             %params,
132             );
133             }
134              
135             sub BUILD {
136             my $self = shift;
137              
138             # This makes sure that <ARGV> works
139             @ARGV = @{ $self->extra_argv };
140             }
141              
142              
143             __PACKAGE__->meta->make_immutable;
144              
145             __END__
146              
147             =pod
148              
149             =encoding UTF-8
150              
151             =head1 NAME
152              
153             App::Colorist - Add color to your plain old outputs
154              
155             =head1 VERSION
156              
157             version 0.141760
158              
159             =head1 DESCRIPTION
160              
161             This documentation is primarily concerned with the installation of the application and giving an in-depth description of the configuration of colorist rulesets and colorsets. For more information about the command-line options, see L<colorist>.
162              
163             B<Installer Beware.> This application is still early in development, so please be aware that any upgrade might drastically change the way the application works.
164              
165             =head2 SYNOPSIS
166              
167             # See the manual for colorist for command-line info
168             alias cpanm="colorist -E cpanm"
169             cpanm App::Colorist
170              
171             # OOOH! Look at the pretty colors!
172              
173             =head1 QUICK START
174              
175             If you just want to start using this with some canned configurations, here's the quick way to get started.
176              
177             # install colorist
178             cpanm App::Colorist
179              
180             # clone the shared configuration from github
181             git clone git://github.com/zostay/dot-colorist.git ~/.colorist
182              
183             # update your bashrc to setup the aliases you need
184             echo 'source $HOME/.colorist/bashrc' > ~/.bashrc
185              
186             After you are done you can logout and log back in or run:
187              
188             source ~/.colorist/bashrc
189              
190             After that, you can update your configuration to the latest just by pulling the latest configuration from github:
191              
192             # make sure colorist is up-to-date first
193             cpanm App::Colorist
194              
195             # update your configuration
196             cd ~/.colorist
197             git pull
198              
199             For more details on writing your own colorist configurations or customizing existing ones, you may read on.
200              
201             =head1 CONFIGURATION
202              
203             The configuration of colorist happens from a number of sources. First, the options passed to the command determine which configuration to use and where to find it, there's an environment variable to help with that as well, then a set of at least 2 configuration files is read to determine how to break up the input for adding color and what colors to add.
204              
205             To help understand these, you may want to visit L<https://github.com/zostay/dot-colorist> and look through the files there to get a sense of what some of the configuraiton files look like as you read this documentation.
206              
207             =head2 Finding Configuration
208              
209             The first step in configuring colorist is to locate the configuration files. Without any special files or handling, colorist will normally look first in the current users's F<~/.colorist> directory for configuration and then into the F</etc/colorist> directory for the system.
210              
211             The search order can be modified in two ways. First, you can put additional search paths into the C<COLORIST_CONFIG> environment variable, like this:
212              
213             # assuming bash or something bash-ish
214             export COLORIST_CONFIG=/opt/etc/colorist:/var/app/common/config/colorist
215              
216             The C<COLORIST_CONFIG> variable is a colon-separated list of paths to search.
217              
218             The other way to modify the search order is using the C<--include> (or C<-I>) option on the command-line. For example, the following options are roughly equivalent to the environment variable shown above:
219              
220             --I /opt/etc/colorist --I /var/app/common/config/colorist
221              
222             The search paths are parent configuration I<directories>, which may each contain zero or more named configurations.
223              
224             It is important to note that a ruleset might be loaded from a different directory than the colorset. This allows a user to define a set of colors in their own F<~/.colorist> directory that has been altered to match their preferences, while the ruleset is loaded from F</etc/colorist> or somewhere else.
225              
226             B<N.B.> The search order of directories is currently experimental and could change. Currently, the search order is to prefer (from most prefered to list) configuration in this order: (1) paths added using the C<--include> option on the command-line, (2) paths set in the C<COLORIST_CONFIG> environment variable, (3) F<~/.colorist>, and (4) F</etc/colorist>.
227              
228             =head2 Named Configuration Directory
229              
230             Inside the colorist configuration directory are zero or more other directories. Each such directory is generally named for the command output or file type that will be colorized. These directories contain two types of files:
231              
232             =over
233              
234             =item 1.
235              
236             B<Rulesets.> These are Perl scripts whose sole purpose is to define a rule set used to parse some input and give sections of hte input names that may be colored.
237              
238             =item 2.
239              
240             B<Colorsets.> These are YAML files which map the named sections of the parsed input different color names.
241              
242             =back
243              
244             A given named configuration may have multiple rulesets and colorsets, but should define at least one of each, with F<rules.pl> being the default ruleset and F<colors.yml> being the default colorset.
245              
246             =head2 Rulesets
247              
248             The rulesets are defined using Perl code. The easiest way to do this is to use the special syntax defined in L<App::Colorist::Ruleset> to define your rules. However, rulesets files just need to return a reference to an array where the even indexed elements are regular expressions and the odd indexed elements are arrays containing the names to assign each grouping.
249              
250             Here's a short sample ruleset:
251              
252             ruleset {
253             rule qr{Starting (\S+)\.\.\.}, qw( message program );
254             rule qr{Finished processing (http://([\w.]+)/) \.\.\.}, qw(
255             message url hostname
256             );
257             }
258              
259             This ruleset contains two rules. The first rule matches a line containing text like:
260              
261             Starting Hello_World...
262              
263             It will assign the entire line the color name "message" and the "Hello_World" part gets assigned the color name "program".
264              
265             The second rule matches a line like:
266              
267             Finished processing http://example.com/ ...
268              
269             Here the whole line is marked as being the color name "message", the "http://example.com/" part gets named "url" and the "example.com" bit gets "hostname".
270              
271             Some things to note:
272              
273             =over
274              
275             =item 1.
276              
277             The first part of a rule is always a regular expression that is used to match the line.
278              
279             =item 2.
280              
281             The remaining items are the names to assign each group in the regular expression match. The first name is the name assigned to the whole line. The rest match each parenthetical.
282              
283             =item 3.
284              
285             Matches can be nested arbitrarily deep and the colors will work with each set of parenthesis marking the start/end of a color name assigned to the matched text.
286              
287             =item 4.
288              
289             The color names are mapped to actual colors in the colorset configuration.
290              
291             =item 5.
292              
293             Every ruleset contains an implicit match anything rule, which assigns those lines the color name to "DEFAULT".
294              
295             =back
296              
297             If you have complex rules or need something more complicated, the important thing about these files to know is that the very last line of the file must return an array reference containing alternating regular expressions and names. For example, the following code is identical to the ruleset defined using the C<ruleset> and C<rule> syntax above:
298              
299             [
300             qr{Starting (\S+)\.\.\.}, [ qw( message program ) ],
301             qr{Finished processing (http://([\w.]+)/) \.\.\.}, [ qw(
302             message url hostname
303             ) ],
304             ]
305              
306             For more information about the rule syntax. You may read the documentation at L<App::Colorist::Ruleset> for details.
307              
308             A named configuration may contain more than one ruleset. This might be used to parse different variations of the command (such as colorizing git output for various sub-commands) or just provide alternate ways of parsing the command in case you need to colorize the output in different ways on different occassions or just because some people in your organization like to do it one way and others their own way.
309              
310             =head2 Colorsets
311              
312             The colorset configuration gives each color named in the ruleset an actual color. It is defined using YAML (which is a superset of JSON, so you may use JSON if you prefer). The file should be built as a single section that contains a hash at the root. Each key in the hash is the name given in the ruleset. Each value is a color declaration, defining how to color that group.
313              
314             There is also a special color, named "DEFAULT". You can use this to assign a color to any unmatched line. (If default is set to the "No color" option described below then it will be set to whatever color uncolored text is given in the user's terminal.)
315              
316             Here is an example colorset file to go with the ruleset example defined in the L</Ruleset> section:
317              
318             ---
319             message: ~
320             program: white
321             url: { fg: blue, bg: gray }
322             hostname: [ 2, 2, 0 ]
323             DEFAULT: [ 10 ]
324              
325             Each color declaration may be defined in one of the following ways:
326              
327             =over
328              
329             =item *
330              
331             B<No color.> To use no color for a section, you may either omit the color name entirely from the colorset or set it to C<null> (which can be written as C<~> in YAML). This does not necessarily mean the section will be uncolored, but that it will get the color of whatever the surrounding match was (or "DEFAULT" if it is the line color.)
332              
333             =item *
334              
335             B<Named color.> As of this writing the following color names are permitted (with the ANSI color code in parenthesis):
336              
337             black (0) gray (8)
338             maroon (1) red (9)
339             green (2) lime (10)
340             olive (3) yellow (11)
341             navy (4) blue (12)
342             purple (5) fuschia (13)
343             teal (6) aqua (14)
344             silver (7) white (15)
345              
346             These are the most common ways to color text. If just a single name is given this way, it is the color of the foreground or text itself.
347              
348             =item *
349              
350             B<Numeric color.> Another option is to assign each a color. For most terminals, this can be any integer in the 0-15 range with the colors usually being like those named above. If you use a terminal that supports it, you may use numbers in the 0-255 range, which includes an additional 216 color mapped into an RGB color cube and 24 shades of gray.
351              
352             =item *
353              
354             B<Color pair.> If you would like to set the background color, you may do so by setting the color to a hash (or object, if you prefer). The keys in the hash are "fg" for setting the foreground color and "bg" for setting the background. The color itself for each can be any of the other color values described here (except this one, of course).
355              
356             =item *
357              
358             B<Gray scale.> For terminals supporting 256 colors, you may use the gray scale by setting the color name to a 1-tuple (single element array) containing the numeric index of the shade of gray you want to use. In these scheme, C<[0]> is black and C<[23]> is white, and all the numbers in between are shades of gray with lower numbers being darker and higher numbers being brighter.
359              
360             =item *
361              
362             B<RGB color.> The final option is to use a 3-tuple (an array with 3 elements) to use one of the 216 colors available on 256 color terminals. As with most representations of the sort, the first index is red, the second is green, and the third is blue. The colors may each be assigned a number in a range from 0 to 5 with 0 representing none of that color and 5 representing the most of the that color. So, C<[0,0,0]> is black and C<[5,5,5]> is white, C<[5,0,0]> is red, C<[5,5,0]> is yellow, C<0,5,0> is lime, C<[0,5,5]> is aqua, C<[0,0,5]> is blue, C<[5,0,5]> is fuschia, etc.
363              
364             =back
365              
366             There can be multiple colorsets for each named configuration. This allows for different themes to be used for different circumstances or different preferences.
367              
368             =for Pod::Coverage BUILD
369              
370             =head1 AUTHOR
371              
372             Andrew Sterling Hanenkamp <hanenkamp@cpan.org>
373              
374             =head1 COPYRIGHT AND LICENSE
375              
376             This software is copyright (c) 2014 by Qubling Software LLC.
377              
378             This is free software; you can redistribute it and/or modify it under
379             the same terms as the Perl 5 programming language system itself.
380              
381             =cut