As I mentioned in the beginning: there are a lot of competitors implementing almost the same functionality. But all of their implementations don't follow my requirements -- to be simple, to be easy, to be flexible (but someone could say this is personal favor. May be...) That's why I have reinvented the wheel.
And one question has arised. What is the best namespace for the module?
Thank evevryone how was involved into this fruitful discussion. I have improved the module. Please have a look and give your feedback.
The source code in the actual state is located on github by the link
https://github.com/ildar-shaimordanov/indent-pm. Here I am posting the minimized version (no POD, no more descriptions, the bare code only and some examples of use cases).
Example 1:
use Indent( text => " ", eol => 1, level => 1 );
my @str = qw( down stairs to hell );
Indent::printf "@str";
( Indent::over, Indent::printf $_ ) for ( @str );
Indent::reset;
Indent::printf("there is no way");
Example 2:
use Indent;
our $indent = Indent->new( text => " ", eol => 1, level => 1 );
local $\ = "\n";
my @str = qw( down stairs to hell );
print($indent, "@str");
{
local $indent = $indent;
( ++$indent )->printf($_) for ( @str );
}
print($indent - 1, "there is no way");
Source code:
package Indent;
use strict;
use warnings;
# ====================================================================
+=====
# Clamp a value on the edge, that is minimum.
# So the value can't be less than this restriction.
sub _lclamp {
my ( $min, $v ) = @_;
$v < $min ? $min : $v;
}
# Set the valid level and evaluate the proper indentation.
sub _set_indent {
my $p = shift;
my $v = shift // 0;
$p->{level} = _lclamp( 0, $p->{level} += $v );
$p->{indent} = $p->{text} x $p->{level};
}
# Detect argument type and get the level value
sub _get_level {
my $v = shift;
ref $v eq __PACKAGE__ ? $v->{level} : $v;
}
# ====================================================================
+=====
sub new {
my $class = shift;
my %p = @_;
my $self = {
text => $p{text} // ( $p{tab} ? "\t" : " " x _lclamp( 1, $p{si
+ze} // 4 ) ),
EOL => $p{eol} ? "\n" : $\,
level => _lclamp( 0, $p{level} // 0 ),
};
_set_indent $self;
bless $self, $class;
}
# ====================================================================
+=====
use overload (
'=' => sub {
my $self = shift;
bless { %{ $self } }, ref $self;
},
'""' => sub {
shift->{indent};
},
'++' => sub {
_set_indent shift, +1;
},
'--' => sub {
_set_indent shift, -1;
},
'+' => sub {
my $self = shift;
my $v = shift;
my %self = %{ $self };
_set_indent \%self, +_get_level($v);
bless { %self }, ref $self;
},
'-' => sub {
my $self = shift;
my $v = shift;
my %self = %{ $self };
_set_indent \%self, -_get_level($v);
bless { %self }, ref $self;
},
);
# ====================================================================
+=====
sub import {
shift;
goto &config if @_;
}
# ====================================================================
+=====
my $indent;
sub config {
$indent = __PACKAGE__->new(@_);
}
sub reset {
$indent = $indent - $indent;
}
sub over {
$indent++;
}
sub back {
$indent--;
}
sub print {
my $self = ref $_[0] eq __PACKAGE__ ? shift : $indent;
local $\ = $self->{EOL};
CORE::print $self, @_;
}
sub vprint {
my $self = shift;
local $\ = $self->{EOL};
CORE::print $self, $_ for ( @_ );
}
sub printf {
my $self = ref $_[0] eq __PACKAGE__ ? shift : $indent;
$self->print(sprintf shift // "", @_);
};
1;
# ====================================================================
+=====
# EOF