ProgressMonitor
view release on metacpan or search on metacpan
permissions in the archive).
0.04 2007-03-23
Replaced wipeAtEnd with atEndStrategy
Clear any message when ending
0.05 2007-03-27
Made the Null monitor a singleton
Made passMessageToParent default to 0 and parentTicks to 1
Made it allowable to skip calling prepare() and go directly to begin()
The messageFiller can be blank/undef, causing partial overlay
Minor help text changes
messageStart/EndOverlayFields are now 1 based indices.
0.06 2007-04-05
- Fixed a loophole; if maxwidth not set we must fall back to hardcoded
79 unless the Term::Size... stuff returns something worthwhile
- Added a convenience subMonitor method to the interface; makes it
cleaner to instantiate a SubTask monitor
- Added a setErrorMessage method and associated support
- Fixed bug where the Bar never indicated empty progress when it was
- set[Error]Message msgs are no longer mangled, but passed right through
- a msg is passed through as-is if messageStrategy is newline (message filler applied though...should it?)
0.08 2007-04-23
- It's possible to call 'end' directly if no work is needed at all
This signals 'completion' of the monitor.
- Avoid treating a 'begin(0)' the same as 'begin()'
- Division by zero in some fields when totalTicks is explicitly '0'.
0.09 2007-05-09
- When using an overlay message on a field shorter than the msg, the
rendition became longer than its maxwidth
0.10 2007-05-21
- Removed the setting of ticks == totalTicks at 'end'
0.11 2007-05-25
- Added a new message strategy - 'overlay_newline'.
0.12 2007-05-25
- When streaming a msg with \n at the end, no need to bs then.
0.20 2007-06-08
- changing the setMessage API, to enable setting 'delayed' messages
i.e. 'set message on next tick' etc.
0.21 2007-06-08
- the newline message strategy now better handles embedded/trailing \n
characters.
- new strategy 'overlay_honor_newline'
0.22 2007-06-11
- when overlaying a message, make sure to restrict it to field size,
except when a newline will be printed
0.23 2007-06-14
- added the Dynamic field.
0.24 2007-11-09
- Made end() autocomplete ticks.
0.26 2008-05-21
- Rendering bs after as default exposed a subtle problem when running
The type of progress monitor given to the top task has the option to provide
the (user) feedback in any manner it so chooses (indeed, if any - a 'null'
monitor is perfectly legal).
Primarily, the interface is concerned with 'ticks' or 'heartbeats' from the
working code. If the amount of work was known beforehand, then these ticks will
help compute remaining work and present this in a number of ways. A secondary
part of the interface also allows work code to provide messages (typically short
ones, they will be cut if they won't fit in the provided space) on what it is
doing. The monitor can decide to show or not show this, and if it shows it, it
can do so in a couple of ways - perhaps as new lines, or overlaying the ordinary
field(s).
Included in the package is two main variants of monitors, both of which deals
with reporting using strings. Special monitors for 'null' use and for subtasks
is also provided.
One of the string based monitors simply prints the string on a stream, the other
uses a callback to allow the client to do whatever it wish with the string. The
strings produced can be of a variety of types ('fields'), and even complex
combinations.
lib/ProgressMonitor.pm view on Meta::CPAN
but still may do something visually interesting. Any other integer is simply added to
the current count - but beware of calling tick with a number that causes the total to
be greater than your promise; this is an error. In any event, this gives the clearest
signal to presentations, one which they typically use to calculate amount done vs amount
remaining, and then render this in the best way.
While 'ticking' is the primary way of informing the user, sometimes it makes sense
not only saying "I'm active", but also saying 'I'm currently doing this', i.e. a straightforward
message. Messages is a sort of out-of-band communication in regards to ticks. Depending
on how the monitor was set up, they may be ignored altogether, written using newlines 'beside'
the tick, or perhaps overlaying the tick field(s) (all or in part) - and then automatically
time out, restoring the tick fields. Anyway, feel free to give informational messages as
needed (but don't assume they'll be seen - just as with ticks, as the monitor in total
may be just a black hole).
=item FINISHING
When all your tasks are complete, you should call the 'end' method. Ideally, you should
by now have called tick the right number of times, and thus the final presentation should
show (the equivalent to) 100% complete.
lib/ProgressMonitor/Stringify/AbstractMonitor.pm view on Meta::CPAN
my $state = $self->_get_state;
my $ticks = $self->_get_ticks;
my $totalTicks = $self->_get_totalTicks;
my $cfg = $self->_get_cfg;
my $ms = $cfg->get_messageStrategy;
my $msg = $self->_get_message;
my $rendition = '';
my $forceNewline = 0;
if ($ms eq 'overlay_newline')
{
$forceNewline = 1;
}
elsif ($ms eq 'overlay_honor_newline')
{
$forceNewline = ($msg && $msg =~ /\n$/);
}
my $allFields = $cfg->get_fields;
for (@$allFields)
{
# ask each field to render itself but ensure the result is exactly the width is
# what its supposed to be
#
lib/ProgressMonitor/Stringify/AbstractMonitor.pm view on Meta::CPAN
foreach my $msgLine (split(/\n/, $msg))
{
$msgLine .= $cfg->get_messageFiller x ($w - length($msgLine)) if ($w > length($msgLine));
$fullMsg .= "$msgLine\n";
}
$rendition = sprintf("%s%s", $fullMsg, $rendition);
$self->_set_message(undef);
}
else
{
# overlay or overlay_newline or overlay_honor_newline
#
my $nlConversion = $cfg->get_messageOverlayNewlineConversion;
my $start_ovrfld = $cfg->get_messageOverlayStartField;
my $end_ovrfld = $cfg->get_messageOverlayEndField;
my $start_ovrpos;
my $end_ovrpos;
my $offset = 0;
for (1 .. @$allFields)
{
$start_ovrpos = $offset if $start_ovrfld == $_;
$offset += $allFields->[$_ - 1]->get_width;
$end_ovrpos = $offset if $end_ovrfld == $_;
last if ($start_ovrpos && $end_ovrpos);
}
$msg =~ s/\n/$nlConversion/g;
my $mf = $cfg->get_messageFiller;
my $len = $mf ? $end_ovrpos - $start_ovrpos : length($msg);
$msg .= $mf x ($len - length($msg)) if ($len > length($msg));
if ($ms eq 'overlay' || ($ms eq 'overlay_honor_newline' && !$forceNewline))
{
substr($rendition, $start_ovrpos, $len) = sprintf("%*.*s", $len, $len, $msg);
}
else
{
substr($rendition, $start_ovrpos) = $msg;
}
if ($forceNewline)
{
lib/ProgressMonitor/Stringify/AbstractMonitor.pm view on Meta::CPAN
# The maximum width this monitor can occupy altogether.
# allowOverflow
# In case the width is too small, let it overflow and linewrap.
# Else, cut the finished rendition so no linewrap occurs, but loses info.
# fields
# An array of fields (or a single field if only one) that should be used
# A field instance can not be reused in the list!
# messageStrategy
# Determines the strategy to use when displaying messages.
# 'none' : doesn't display messages
# 'overlay': requires 'messageOverlaysFields' to be set
# 'newline': renders the message only with a newline at the end, in
# effect pushing the other fields 'down'. Handles and 'honors'
# embedded newlines, trailing newlines are dropped.
# 'overlay_newline' : combines the effects of 'overlay' and 'newline'
# 'overlay_honor_newline' : acts as 'overlay', but will ensure to make a
# newline if the message has a trailing one.
# messageOverlayStartfield
# The field on which message overlay should start. Defaults to 0.
# messageOverlayEndfield
# The field on which message overlay should end. Defaults to last field.
# messageFiller
# The character for filling out the length of the message if
# is not long enough to overlay the full length of the field(s)
# it is set to overlay.
# messageTimeout
# The time in seconds before the message is cleared automatically. This
# is only relevant for overlay (for newline, it only appears once).
# Defaults to 3 seconds. Set to -1 for 'no timeout'.
# messageOverlayNewlineConversion
# For 'overlay' and 'overlay_newline', any embedded/trailing newlines
# will be converted to another string, settable by this cfg variable.
# Defaults to ' ' (space).
#
use classes
extends => 'ProgressMonitor::AbstractStatefulMonitorConfiguration',
attrs => [
'maxWidth', 'allowOverflow', 'fields',
'messageStrategy', 'messageOverlayStartField',
'messageOverlayEndField', 'messageFiller',
'messageTimeout', 'messageOverlayNewlineConversion'
lib/ProgressMonitor/Stringify/AbstractMonitor.pm view on Meta::CPAN
my %seenFields;
for (@$fields)
{
X::Usage->throw("not a field: $_") unless (blessed($_) && $_->isa("ProgressMonitor::Stringify::Fields::AbstractField"));
X::Usage->throw("same instance of field used more than once: $_") if $seenFields{$_};
$seenFields{$_} = 1;
}
my $ms = $self->get_messageStrategy;
X::Usage->throw("invalid value for messageStrategy: $ms")
unless $ms =~ /^(?:none|overlay|newline|overlay_newline|overlay_honor_newline)$/;
if ($ms =~ /^overlay/)
{
my $maxFieldNum = @$fields;
$self->set_messageOverlayEndField($maxFieldNum) unless defined($self->get_messageOverlayEndField);
my $start = $self->get_messageOverlayStartField;
my $end = $self->get_messageOverlayEndField;
X::Usage->throw("illegal overlay start field: $start") if ($start < 1 || $start > $maxFieldNum);
X::Usage->throw("illegal overlay end field: $end")
if ($end < 1 || $end > $maxFieldNum || $end < $start);
}
my $mf = $self->get_messageFiller;
X::Usage->throw("messageFiller not a character: $mf") if length($mf) > 1;
return;
}
############################
lib/ProgressMonitor/Stringify/AbstractMonitor.pm view on Meta::CPAN
An identifiers that describes how messages should be inserted into the
rendition:
=over 2
=item none
Not surprisingly, this suppresses message presentation.
=item overlay
This will cause the message to overlay one or more of the other
fields, so as to keep things on one line. This setting will work
in conjunction with messageTimeout, messageOverlayStartField and
messageOverlayEndField.
=item newline
This will cause the message and a newline to be inserted in front
of the regular rendition, causing the running rendition to be
'pushed' forward.
=item overlay_newline
This will combine the effects of 'overlay' and 'newline'.
=back
=item messageFiller (default => ' ')
If the message is too short for the allotted space, it will be filled with
this character. Can be set to the empty string or undef to skip filling,
causing a 'partial overlay', i.e. just as much as the string is, which
obviously can give a confusing mixed message with the underlying field.
=item messageTimeout (default => 3 seconds)
This is only relevant for the 'overlay' strategy. If the code doesn't
explicitly set the message to undef/blank, the timeout will automatically
remove it. Set to -1 for infinite.
=item messageOverlayStartField, messageOverlayEndField (defaults => all fields)
Together these define the starting and ending field number that the message
should overlay. This defaults to 'all fields'.
=item messageOverlayNewlineConversion (default => ' ')
Embedded/trailing newlines will be converted to this string for the 'overlay'
and 'overlay_newline' strategies.
=back
=item _toString
Contains the logic to assemble the fields into a current string.
=back
=head1 AUTHOR
t/03-Message1.t view on Meta::CPAN
return 0;
};
my $monitor =
ProgressMonitor::Stringify::ToCallback->new(
{
maxWidth => 79,
fields => [ProgressMonitor::Stringify::Fields::Fixed->new({text => "tick"})],
tickCallback => $cb,
messageFiller => '.',
messageStrategy => 'overlay'
}
);
$monitor->prepare;
for (1 .. 10)
{
$monitor->tick;
$monitor->setMessage($msg);
$monitor->setMessage(undef);
}
$monitor->begin(10);
t/03-Message2.t view on Meta::CPAN
use ProgressMonitor::Stringify::ToCallback;
use ProgressMonitor::Stringify::Fields::Fixed;
my $msg = 'xyz';
plan tests => 83 * 3;
# this particular test shows that the strategy is not relevant
#
runtest('overlay');
runtest('newline');
runtest('none');
sub runtest
{
my $strategy = shift;
my $cb = sub {
my $rendering = shift;
my $expected = 'tick';
( run in 0.601 second using v1.01-cache-2.11-cpan-49f99fa48dc )