ProgressMonitor

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

        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

Changes  view on Meta::CPAN

		- 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

README  view on Meta::CPAN

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 )