File Coverage

blib/lib/Text/Indent.pm
Criterion Covered Total %
statement 36 39 92.3
branch 5 8 62.5
condition 6 13 46.1
subroutine 9 10 90.0
pod 4 6 66.6
total 60 76 78.9


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Text::Indent - simple indentation of text shared among modules
4              
5             =head1 SYNOPSIS
6              
7             In your main program:
8              
9             use Text::Indent;
10             my $indent = Text::Indent->new;
11             $indent->spaces(2);
12              
13             In a module to produce indented output:
14              
15             use Text::Indent;
16             my $indent = Text::Indent->instance;
17             $indent->increase;
18             print $indent->indent("this will be indented two spaces");
19             $indent->increase(2);
20             print $indent->indent("this will be indented six spaces");
21             $indent->decrease(3);
22              
23             =head1 DESCRIPTION
24              
25             Text::Indent is designed for use in programs which need to produce output
26             with multiple levels of indent when the source of the output comes from
27             different modules that know nothing about each other.
28              
29             For example take module A, whose output includes the indented output of
30             module B. Module B can also produce output directly, so it falls to module B
31             to know whether it should indent it's output or not depending on it's
32             calling context.
33              
34             Text::Indent allows programs and modules to cooperate to choose an
35             appropriate indent level that is shared within the program context. In the
36             above example, module A would increase the indent level prior to calling the
37             output routines of module B. Module B would simply use the Text::Indent
38             instance confident that if it were being called directly no indent would be
39             applied but if module A was calling it then it's output would be indented
40             one level.
41              
42             =for testing
43             use_ok('Text::Indent');
44             eval "use Test::NoWarnings";
45              
46             =cut
47              
48             package Text::Indent;
49              
50 8     8   10087 use strict;
  8         18  
  8         237  
51 8     8   41 use warnings;
  8         12  
  8         317  
52              
53             our $VERSION = '0.031';
54              
55 8     8   4572 use Params::Validate qw|:all|;
  8         76626  
  8         1771  
56              
57             use Class::MethodMaker(
58 8         61 new_with_init => 'new',
59             static_get_set => '_instance',
60             get_set => [ qw|
61             spaces
62             spacechar
63             |],
64             counter => 'level',
65             boolean => 'add_newline',
66 8     8   4744 );
  8         140477  
67              
68             =head1 CONSTRUCTOR
69              
70             The constructor for Text::Indent should only be called once by the main
71             program using modules that produce indented text. Modules which wish
72             to produce indented text should use the instance accessor described below.
73              
74             To construct a new Text::Indent object, call the B method, passing
75             one or more of the following parameters as a hash:
76              
77             =over 4
78              
79             =item * B
80              
81             the number of spaces to used for each level of indentation. Defaults to 2.
82              
83             =item * B
84              
85             the character to be used for indentation. Defaults to a space (ASCII 32)
86              
87             =item * B
88              
89             The initial indentation level to set. Defaults to 0.
90              
91             =item * B
92              
93             Whether the B method should automatically add a newline to the input
94             arguments. Defaults to TRUE.
95              
96             =item * B
97              
98             Whether the newly constructed Text::Indent object should become the new
99             singleton instance returned by the B accessor. Defaults to TRUE.
100              
101             =back
102              
103             =begin testing
104              
105             eval { Text::Indent->new };
106             ok( ! $@, "can create an object");
107             eval { Text::Indent->new( Foo => 'Bar' ) };
108             ok( $@, "constructor dies on invalid args");
109              
110             =end testing
111              
112             =cut
113              
114             sub init
115             {
116            
117 7     7 0 4046 my $self = shift;
118 7   33     35 my $class = ref $self || $self;
119            
120             # validate args
121 7         527 my %args = validate(@_,{
122             Spaces => { type => SCALAR,
123             default => 2 },
124             SpaceChar => { type => SCALAR,
125             default => ' ' },
126             Level => { type => SCALAR,
127             default => 0 },
128             AddNewLine => { type => BOOLEAN,
129             default => 1 },
130             Instance => { type => BOOLEAN,
131             default => 1 }
132             });
133            
134             # populate object
135 6         194 $self->spaces( $args{Spaces} );
136 6         232 $self->spacechar( $args{SpaceChar} );
137 6         216 $self->level( $args{Level} );
138 6         570 $self->add_newline( $args{AddNewLine} );
139            
140             # set as the current instance unless told not to
141 6 50 33     134 unless( exists $args{Instance} && ! $args{Instance} ) {
142 6         146 $class->_instance( $self );
143             }
144            
145 6         196 return $self;
146            
147             }
148              
149             =head1 INSTANCE ACCESSOR
150              
151             The instance accessor is designed to be used by modules wishing to produce
152             indented output. If the instance already exists (as will be the case if the
153             main program using the module constructed a Text::Indent object) then both
154             the program and the module will use the same indentation scheme.
155              
156             If the instance does not exist yet, the instance accessor dispatches it's
157             arguments to the constructor. As such, any of the parameters that the
158             constructor takes may also be passed to the instance accessor. Be mindful
159             that if the instance does exist, any parameters passed to the instance
160             accessor are ignored.
161              
162             =cut
163              
164             sub instance
165             {
166            
167 0     0 0 0 my $self = shift;
168 0   0     0 my $class = ref $self || $self;
169            
170             # return the class instance if we have one, otherwise
171             # dispatch to the constructor
172 0 0       0 return $class->_instance ? $class->_instance
173             : $class->new(@_);
174            
175             }
176              
177             =head1 METHODS
178              
179             =head2 increase($how_many)
180              
181             This method increases the level of indentation by $how_many levels. If
182             not provided, $how_many defaults to 1.
183              
184             =for testing
185             my $i = Text::Indent->new;
186             is( $i->level, 0, "level initialized to 0");
187             $i->increase;
188             is( $i->level, 1, "level increased to 1");
189             $i->increase(2);
190             is( $i->level, 3, "level increased to 3");
191              
192             =cut
193              
194             sub increase
195             {
196            
197 3     3 1 1310 my $self = shift;
198 3   100     16 my $how_many = shift || 1;
199            
200 3         96 $self->level_incr($how_many);
201            
202 3         349 return $self;
203            
204             }
205              
206             =head2 decrease
207              
208             This method decreases the level of indentation by $how_many levels. If
209             not provided, $how_many defaults to 1.
210              
211             =for testing
212             my $i = Text::Indent->new( Level => 5 );
213             is( $i->level, 5, "level initialized to 5");
214             $i->decrease;
215             is( $i->level, 4, "level decreased to 4");
216             $i->decrease(2);
217             is( $i->level, 2, "level decreased to 2");
218              
219             =cut
220              
221             sub decrease
222             {
223            
224 3     3 1 1308 my $self = shift;
225 3   100     18 my $how_many = shift || 1;
226            
227 3         92 $self->level_incr( - $how_many );
228            
229 3         348 return $self;
230            
231             }
232              
233             =head2 reset
234              
235             This method resets the level of indentation to 0. It is functionally
236             equivalent to $indent->level(0).
237              
238             =for testing
239             my $i = Text::Indent->new( Level => 5 );
240             is( $i->level, 5, "level initialized to 5");
241             $i->reset;
242             is( $i->level, 0, "level reset to 0");
243              
244             =cut
245              
246             sub reset
247             {
248            
249 3     3 1 1356 my $self = shift;
250            
251 3         95 $self->level_reset;
252            
253 3         17 return $self;
254            
255             }
256              
257             =head2 indent(@what)
258              
259             This is the primary workhorse method of Text::Indent. It takes a list of
260             arguments to be indented and returns the indented string.
261              
262             The string returned is composed of the following list:
263              
264             =over 4
265              
266             =item * the 'space' character repeated x times, where x is the number of
267             spaces multiplied by the indent level.
268              
269             =item * the stringification of arguments passed to the method (note that
270             this means that list arguments will have spaces inserted in between them).
271              
272             =item * a newline if the 'add_newline' attribute of the Text::Indent object
273             is set.
274              
275             =back
276              
277             If the indent level drops is a negative value, no indent is applied.
278              
279             =for testing
280             my $i = Text::Indent->new;
281             is( $i->indent("foo"), "foo\n", "no indentation");
282             $i->increase;
283             is( $i->indent("foo"), " foo\n", "indent level 1");
284             $i->spaces(4);
285             is( $i->indent("foo"), " foo\n", "change spaces to 4");
286             $i->spacechar("+");
287             is( $i->indent("foo"), "++++foo\n", "chance spacechar to +");
288             $i->add_newline(0);
289             is( $i->indent("foo"), "++++foo", "unset add_newline");
290             $i->reset;
291             is( $i->indent("foo"), "foo", "reset indent level");
292             $i->decrease;
293             is( $i->indent("foo"), "foo", "negative indent has no effect");
294              
295             =cut
296              
297             sub indent
298             {
299            
300 7     7 1 18 my $self = shift;
301 7         15 my @args = @_;
302            
303 7 100       158 return ($self->spacechar x ($self->spaces * ($self->level < 0 ? 0 : $self->level))) .
    100          
304             "@args" . ($self->add_newline ? "\n" : '');
305            
306             }
307              
308             # keep require happy
309             1;
310              
311              
312             __END__