File Coverage

blib/lib/Commandable/Output.pm
Criterion Covered Total %
statement 64 73 87.6
branch 3 4 75.0
condition 2 3 66.6
subroutine 15 16 93.7
pod 4 4 100.0
total 88 100 88.0


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2022-2024 -- leonerd@leonerd.org.uk
5              
6             package Commandable::Output 0.14;
7              
8 11     11   134 use v5.26;
  11         39  
9 11     11   80 use warnings;
  11         27  
  11         720  
10 11     11   62 use experimental qw( signatures );
  11         28  
  11         73  
11              
12 11         30 use constant HAVE_STRING_TAGGED => defined eval {
13 11         7410 require String::Tagged;
14 11         109728 require Convert::Color;
15 11     11   1919 };
  11         22  
16              
17 11         22 use constant HAVE_STRING_TAGGED_TERMINAL => defined eval {
18 11         7165 require String::Tagged::Terminal;
19 11     11   474806 };
  11         41  
20              
21             =head1 NAME
22              
23             C - abstractions for printing output from commands
24              
25             =head1 DESCRIPTION
26              
27             This package contains default implementations of methods for providing printed
28             output from commands implemented using L. These methods are
29             provided for the convenience of user code, and are also used by built-in
30             commands provided by the C system itself.
31              
32             Implementations are permitted (encouraged, even) to replace any of these
33             methods in order to customise their behaviour.
34              
35             =head2 WITH C
36              
37             If L and L are available, this module applies
38             formatting to strings by using the L conventions.
39             The C and C methods will return results as
40             instances of C, suitable to pass into the main C
41             method.
42              
43             =cut
44              
45             =head1 METHODS
46              
47             =cut
48              
49 7         13 sub _format_string ( $self, $text, $tagmethod )
  7         14  
50 7     7   13 {
  7         12  
  7         13  
51 7         10 return $text unless HAVE_STRING_TAGGED;
52              
53 7         14 my %tags;
54 7 50       109 %tags = $self->$tagmethod if $self->can( $tagmethod );
55              
56 7 100 66     51 if( $tags{fg} and !ref $tags{fg} ) {
57 5         38 $tags{fg} = Convert::Color->new( $tags{fg} );
58             }
59              
60 7         22702 return String::Tagged->new_tagged( $text, %tags );
61             }
62              
63             =head2 printf
64              
65             Commandable::Output->printf( $format, @args );
66              
67             The main output method, used to send messages for display to the user. The
68             arguments are formatted into a single string by Perl's C function.
69             This method does not append a linefeed. To output a complete line of text,
70             remember to include the C<"\n"> at the end of the format string.
71              
72             The default implementation writes output on the terminal via STDOUT.
73              
74             In cases where the output should be sent to some other place (perhaps a GUI
75             display widget of some kind), the application should replace this method with
76             something that writes the display to somewhere more appropriate. Don't forget
77             to use C to format the arguments into a string.
78              
79             no warnings 'redefine';
80             sub Commandable::Output::printf
81             {
82             shift; # the package name
83             my ( $format, @args ) = @_;
84              
85             my $str = sprintf $format, @args;
86              
87             $gui_display_widget->append_text( $str );
88             }
89              
90             If L is available, the output will be printed using
91             this module, by first converting the format string and arguments using
92             L and then constructing a terminal string using
93             L. This means the default
94             implementation will be able to output formatted strings using the
95             L conventions.
96              
97             =cut
98              
99 0         0 sub printf ( $self, $format, @args )
  0         0  
100 0     0 1 0 {
  0         0  
  0         0  
101 0         0 if( HAVE_STRING_TAGGED_TERMINAL ) {
102 0         0 String::Tagged::Terminal->new_from_formatting(
103             String::Tagged->from_sprintf( $format, @args )
104             )->print_to_terminal;
105 0         0 return;
106             }
107              
108 0         0 printf $format, @args;
109             }
110              
111             =head2 print_heading
112              
113             Commandable::Output->print_heading( $text, $level );
114              
115             Used to send output that should be considered like a section heading.
116             I<$level> may be an integer used to express sub-levels; increasing values from
117             1 upwards indicate increasing sub-levels.
118              
119             The default implementation formats the text string using L
120             then prints it using L with a trailing linefeed.
121              
122             =cut
123              
124 5         11 sub print_heading ( $self, $text, $level = 1 )
  5         12  
  5         11  
125 5     5 1 12 {
  5         8  
126 5         24 $self->printf( "%s\n", $self->format_heading( $text, $level ) );
127             }
128              
129             =head2 format_heading
130              
131             $str = Commandable::Output->format_heading( $text, $level );
132              
133             Returns a value for printing, to represent a section heading for the given
134             text and level.
135              
136             The default implementation applies the following formatting if
137             C is available:
138              
139             =over 4
140              
141             =item Level 1
142              
143             Underlined
144              
145             =item Level 2
146              
147             Underlined, cyan colour
148              
149             =item Level 3
150              
151             Bold
152              
153             =back
154              
155             =cut
156              
157 11     11   130759 use constant TAGS_FOR_HEADING_1 => ( under => 1 );
  11         23  
  11         1021  
158 11     11   105 use constant TAGS_FOR_HEADING_2 => ( under => 1, fg => "vga:cyan", );
  11         20  
  11         684  
159 11     11   63 use constant TAGS_FOR_HEADING_3 => ( bold => 1 );
  11         20  
  11         1670  
160              
161 2         5 sub format_heading ( $self, $text, $level = 1 )
  2         4  
  2         4  
162 2     2 1 4 {
  2         6  
163 2         13 return $self->_format_string( $text, "TAGS_FOR_HEADING_$level" );
164             }
165              
166             =head2 format_note
167              
168             $str = Commandable::Output->format_note( $text, $level );
169              
170             Returns a value for printing, to somehow highlight the given text (which
171             should be a short word or string) at the given level.
172              
173             The default implementation applies the following formatting if
174             C is available:
175              
176             =over 4
177              
178             =item Level 0
179              
180             Bold, yellow colour
181              
182             =item Level 1
183              
184             Bold, cyan colour
185              
186             =item Level 2
187              
188             Bold, magenta colour
189              
190             =back
191              
192             =cut
193              
194 11     11   78 use constant TAGS_FOR_NOTE_0 => ( bold => 1, fg => "vga:yellow" );
  11         33  
  11         764  
195 11     11   71 use constant TAGS_FOR_NOTE_1 => ( bold => 1, fg => "vga:cyan" );
  11         20  
  11         758  
196 11     11   67 use constant TAGS_FOR_NOTE_2 => ( bold => 1, fg => "vga:magenta" );
  11         34  
  11         1787  
197              
198 5         10 sub format_note ( $self, $text, $level = 0 )
  5         11  
  5         10  
199 5     5 1 10 {
  5         34  
200 5         27 return $self->_format_string( $text, "TAGS_FOR_NOTE_$level" );
201             }
202              
203             =head1 AUTHOR
204              
205             Paul Evans
206              
207             =cut
208              
209             0x55AA;