8000 [Console][Feature] Sub progresses in ProgressHelper · Issue #9951 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Console][Feature] Sub progresses in ProgressHelper #9951

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
sirian opened this issue Jan 6, 2014 · 4 comments
Closed

[Console][Feature] Sub progresses in ProgressHelper #9951

sirian opened this issue Jan 6, 2014 · 4 comments
Labels

Comments

@sirian
Copy link
Contributor
sirian commented Jan 6, 2014

It's often necessary to display more than one progress helper.
Assume you have DownloadFiles command which downloads 100 files (one by one) from internet. So I want to render total progress (downloaded files) and download progress for current file

@cordoval
Copy link
Contributor
cordoval commented Jan 6, 2014

do you have some use case at hand? code snippet or better some fork of SE to mock this scenario? or example of this? I mean more so that this request turns more into an specification.

@wouterj
Copy link
Member
wouterj commented Jan 6, 2014

@cordoval he already said the use-case...

Assume you have DownloadFiles command which downloads 100 files (one by one) from internet. So I want to render total progress (downloaded files) and download progress for current file

I think sub progresses should be read as multiple progressbars. And that isn't possible sense the helpers are statefull and shared. A related issue would then be #9788 (for the tablehelper)

I propose to change the helper mechanism to something that returns a ProgressBar object, instead of using the ProgressHelper to display the progress bar:

public function execute(InputInterface $input, OutputInterface $output)
{
    $progressHelper = $this->getHelperSet()get('progress');
    $mainProgressBar = $progressHelper->createProgressBar($output);

    $mainProgressBar->start(count($files));
    foreach ($files as $file) {
        $fileProgressBar = $progressHelper->createProgressBar($output);
        $fileProgressBar->start(100);
        // ... advantage file progress bar
        $mainProgressBar->advantage();
    }
}

The only problem will be that it's difficult to render 2 progress bars in the console, since we can't rewrite a previous line (only the current line).

@sirian
Copy link
Contributor Author
sirian commented Jan 6, 2014

Maybe create progress set like

class ProgressSetHelper
{
    /**
     * Creates and attaches new progress helper to this set
     * @return ProgressHelper
     */
    public function create($name);     

    public function start(OutputInterface $output);
    public function render();
    public function clear();
    public function finish();
    ...
}

then usage would be like

$helperSet = $this->getHelper('progressSet');
$helperSet->start($output);
$mainProgressBar = $helperSet->create('Total');

$filesProgressBar = $helperSet->create('Download');
$filesProgressBar->setFormat(ProgressHelper:: FORMAT_QUIET);

$mainProgressBar->start(count($files));
foreach ($files as $file) {
    $helperSet->clear(); //to output message we should clear progress bar
    $output->writeln(sprintf('Download %s', $file));
    $helperSet->render();

    $fileProgressBar->start(100);
     // download and advance  fileProgressBar
    $mainProgressBar->advance();
}
$helperSet->finish();

as @wouterj mentioned we can't rewrite previous line (at least not all terminals supports that), so we should display all progress bars in one line like

Download: 33% Total: 10/30 [===-------] 33%

@fabpot
Copy link
Member
fabpot commented Mar 2, 2014

As #10356 makes the progress bar stateless, it's now easy to accomplish (some examples in the PR notes)

@fabpot fabpot closed this as completed Mar 2, 2014
fabpot added a commit that referenced this issue Mar 3, 2014
This PR was merged into the 2.5-dev branch.

Discussion
----------

[Console] A better progress bar

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #9573, #9574, #10187, #9951, related to #9788
| License       | MIT
| Doc PR        | symfony/symfony-docs#3626

TODO:

 - [x] add some docs

See what this PR allows you to do easily:

![cwzpvk](https://f.cloud.github.com/assets/47313/2302190/30cd80e4-a170-11e3-8d88-80c4e4ca8b23.gif)

## New ProgressBar class

First, this PR deprecates `ProgressHelper` in favor of `ProgressBar`. The main difference is that the new `ProgressBar` class represents a single progress bar, which allows for more than one bar to be displayed at a time:

```php
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Output\ConsoleOutput;

$output = new ConsoleOutput();

$bar1 = new ProgressBar($output, 10);
$bar2 = new ProgressBar($output, 20);
$bar2->setProgressCharacter('#');
$bar1->start();
print "\n";
$bar2->start();

for ($i = 1; $i <= 20; $i++) {
    // up one line
    $output->write("\033[1A");
    usleep(100000);
    if ($i <= 10) {
        $bar1->advance();
    }
    print "\n";
    $bar2->advance();
}
```

And here is how it looks like when run:

![progress-bars](https://f.cloud.github.com/assets/47313/2300612/4465889a-a0fd-11e3-8bc2-b1d2a0f5dc3d.gif)

## Format Placeholders

This pull request refactors the way placeholders in the progress bar are managed. It is now possible to add new placeholders or replace existing ones:

```php
// set a new placeholder
ProgressBar::setPlaceholderFormatterDefinition('remaining_steps', function (ProgressBar $bar) {
    return $bar->getMaxSteps() - $bar->getStep();
});

// change the behavior of an existing placeholder
ProgressBar::setPlaceholderFormatterDefinition('max', function (ProgressBar $bar) {
    return $bar->getMaxSteps() ?: '~';
});
```

Several new built-in placeholders have also been added:

 * `%remaining%`: Display the remaining time
 * `%estimated%`: Display the estimated time of the whole "task"
 * `%memory%`: Display the memory usage

## Formats

Formats can also be added (or built-in ones modified):

```php
ProgressBar::setFormatDefinition('simple', '%current%');

$bar->setFormat('simple');
// is equivalent to
$bar->setFormat('%current%');
```

Built-in formats are:

 * `quiet`
 * `normal`
 * `verbose`
 * `quiet_nomax`
 * `normal_nomax`
 * `verbose_nomax`

## Format Messages

You can also set arbitrary messages that depends on the progression in the progress bar:

```php
$bar = new ProgressBar($output, 10);
$bar->setFormat("%message% %current%/%max% [%bar%]");

$bar->setMessage('started');
$bar->start();

$bar->setMessage('advancing');
$bar->advance();

$bar->setMessage('finish');
$bar->finish();
```

You are not limited to a single message (`message` being just the default one):

```php
$bar = new ProgressBar($output, 10);
$bar->setFormat("%message% %current%/%max% [%bar%] %end%");

$bar->setMessage('started');
$bar->setMessage('', 'end');
$bar->start();

$bar->setMessage('advancing');
$bar->advance();

$bar->setMessage('finish');
$bar->setMessage('ended...', 'end');
$bar->finish();
```

## Multiline Formats

A progress bar can now span more than one line:

```php
$bar->setFormat("%current%/%max% [%bar%]\n%message%");
```

## Flexible Format Definitions

The hardcoded formatting for some placeholders (like `%percent%` or `%elapsed%`) have been removed in favor of a `sprintf`-like format:

```php
$bar->setFormat("%current%/%max% [%bar%] %percent:3s%");
```

Notice the `%percent:3s%` placeholder. Here, `%3s` is going to be used when rendering the placeholder.

## ANSI colors and Emojis

The new progress bar output can now contain ANSI colors and.or Emojis (see the small video at the top of this PR).

Commits
-------

0d1a58c [Console] made formats even more flexible
8c0022b [Console] fixed progress bar when using ANSI colors and Emojis
38f7a6f [Console] fixed PHP comptability
244d3b8 [Console] added a way to globally add a progress bar format or modify a built-in one
a9d47eb [Console] added a way to add a custom message on a progress bar
7a30e50 [Console] added support for multiline formats in ProgressBar
1aa7b8c [Console] added more default placeholder formatters for the progress bar
2a78a09 [Console] refactored the progress bar to allow placeholder to be extensible
4e76aa3 [Console] added ProgressBar (to replace the stateful ProgressHelper class)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants
0