Developer-Dashboard

 view release on metacpan or  search on metacpan

lib/Developer/Dashboard/CLI/Progress.pm  view on Meta::CPAN

            status       => 'pending',
            detail_lines => [],
        }
    } @{$tasks};
    my $stream = $args{stream} || \*STDERR;
    my $self = bless {
        title    => $args{title} || 'dashboard progress',
        order    => \@order,
        tasks    => \%task_lookup,
        stream   => $stream,
        dynamic  => $args{dynamic} ? 1 : 0,
        color    => $args{color} ? 1 : 0,
        rendered => 0,
        max_detail_lines => $args{max_detail_lines},
        last_rendered_line_count => 0,
    }, $class;
    $self->render;
    return $self;
}

# callback()
# Returns a callback that updates task state from runtime lifecycle events.
# Input: none.
# Output: coderef that accepts one hash reference event.
sub callback {
    my ($self) = @_;
    return sub {
        my ($event) = @_;
        $self->update($event);
    };
}

# add_tasks($tasks)
# Appends newly discovered tasks to the rendered board without disturbing the
# status and order of already registered tasks.
# Input: array reference of task hashes with id and optional label.
# Output: true value.
sub add_tasks {
    my ( $self, $tasks ) = @_;
    return 1 if ref($tasks) ne 'ARRAY' || !@{$tasks};
    for my $task ( @{$tasks} ) {
        next if ref($task) ne 'HASH';
        my $id = $task->{id} || next;
        next if $self->{tasks}{$id};
        push @{ $self->{order} }, $id;
        $self->{tasks}{$id} = {
            id           => $id,
            label        => $task->{label} || $id,
            status       => 'pending',
            detail_lines => [],
        };
    }
    $self->render;
    return 1;
}

# update($event)
# Applies one lifecycle progress event to the tracked task board.
# Input: hash reference with task_id, status, and optional label.
# Output: true value.
sub update {
    my ( $self, $event ) = @_;
    return 1 if !$event || ref($event) ne 'HASH';
    $self->add_tasks( $event->{add_tasks} ) if exists $event->{add_tasks};
    my $id = $event->{task_id} || return 1;
    my $task = $self->{tasks}{$id} || return 1;
    $task->{status} = $event->{status} if defined $event->{status} && $event->{status} ne '';
    $task->{label}  = $event->{label}  if defined $event->{label}  && $event->{label} ne '';
    if ( exists $event->{detail_lines} ) {
        my @detail_lines = ref( $event->{detail_lines} ) eq 'ARRAY' ? @{ $event->{detail_lines} } : ();
        my $max = $self->_detail_line_limit;
        if ( defined $max && @detail_lines > $max ) {
            @detail_lines = @detail_lines[ @detail_lines - $max .. $#detail_lines ];
        }
        $task->{detail_lines} = \@detail_lines;
    }
    elsif ( exists $event->{detail_line} ) {
        my @detail_lines = @{ $task->{detail_lines} || [] };
        push @detail_lines, $event->{detail_line};
        my $max = $self->_detail_line_limit;
        if ( defined $max && @detail_lines > $max ) {
            @detail_lines = @detail_lines[ @detail_lines - $max .. $#detail_lines ];
        }
        $task->{detail_lines} = \@detail_lines;
    }
    if ( $task->{status} eq 'done' ) {
        $task->{detail_lines} = [];
    }
    $self->render;
    return 1;
}

# finish()
# Finalizes the rendered board by ensuring a trailing newline after dynamic redraws.
# Input: none.
# Output: true value.
sub finish {
    my ($self) = @_;
    return 1 if !$self->{dynamic} || !$self->{rendered};
    my $stream = $self->{stream};
    print {$stream} "\n";
    return 1;
}

# render()
# Renders the full task board to the configured output stream.
# Input: none.
# Output: true value.
sub render {
    my ($self) = @_;
    my $stream = $self->{stream};
    my $board  = $self->render_text;
    if ( $self->{dynamic} && $self->{rendered} ) {
        for ( 1 .. ( $self->{last_rendered_line_count} || 0 ) ) {
            print {$stream} "\e[1A\e[2K";
        }
    }
    print {$stream} $board;
    $self->{rendered} = 1;
    $self->{last_rendered_line_count} = scalar grep { defined } split /\n/, $board;
    return 1;



( run in 2.991 seconds using v1.01-cache-2.11-cpan-9581c071862 )