Skip to content

[RFC][Console] Added console style guide helpers (v2) #14057

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
wants to merge 34 commits into from
Closed

[RFC][Console] Added console style guide helpers (v2) #14057

wants to merge 34 commits into from

Conversation

kbond
Copy link
Member

@kbond kbond commented Mar 25, 2015

(Rebased to 2.7)

Q A
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #12014, #12035, symfony/symfony-docs#4265
License MIT
Doc PR todo

Proposed API

Code

// Symfony command
protected function execute(InputInterface $input, OutputInterface $output)
{
    $output = new SymfonyStyle($output);

    $output->title('Lorem Ipsum Dolor Sit Amet');
    $output->text(array(
        'Duis aute irure dolor in reprehenderit in voluptate velit esse',
        'cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat'
    ));
    $output->ln();

    $output->table(array('Name', 'Method', 'Scheme', 'Host', 'Path'), array(
            array('admin_post_new', 'ANY', 'ANY', 'ANY', '/admin/post/new'),
            array('admin_post_show', 'GET', 'ANY', 'ANY', '/admin/post/{id}'),
            array('admin_post_edit', 'ANY', 'ANY', 'ANY', '/admin/post/{id}/edit'),
            array('admin_post_delete', 'DELETE', 'ANY', 'ANY', '/admin/post/{id}'),
        ));

    $output->caution(array(
            'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.',
            'foo'
        ));
    $output->section('Consectetur Adipisicing Elit Sed Do Eiusmod');
    $output->listing(array(
        'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod, tempor incididunt ut labore et dolore magna aliqua.',
        'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.',
        'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
    ));

    $customValidator = function ($value) {
        if ($value == 'foo') {
            throw new \Exception('cannot be foo');
        }

        return $value;
    };

    // hidden question
    $output->note($output->askHidden('Hidden question'));

    // choice questions
    $output->note($output->choice('Choice question no default', array('choice1', 'choice2')));
    $output->note($output->choice('Choice question with default', array('choice1', 'choice2'), 'choice1'));

    // confirmation questions
    $output->note($output->confirm('Confirmation with yes default', true) ? 'yes' : 'no');
    $output->note($output->confirm('Confirmation with no default', false) ? 'yes' : 'no');

    // standard questions
    $output->note($output->ask('Question no default'));
    $output->note($output->ask('Question no default and custom validator', null, $customValidator));
    $output->note($output->ask('Question with default', 'default'));
    $output->note($output->ask('Question with default and custom validator', 'default', $customValidator));

    $output->note('Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat.');
    $output->success('Lorem ipsum dolor sit amet, consectetur adipisicing elit');
    $output->error('Duis aute irure dolor in reprehenderit in voluptate velit esse.');
    $output->warning('Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi.');

    $output->progressStart(100);

    for ($i = 0; $i < 100; $i++) {
        usleep(10000);
        $output->progressAdvance();
    }

    $output->progressFinish();
}

Output

$ php app/console command

Lorem Ipsum Dolor Sit Amet
==========================

 // Duis aute irure dolor in reprehenderit in voluptate velit esse
 // cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat

 ------------------- -------- -------- ------ ----------------------- 
  Name                Method   Scheme   Host   Path                   
 ------------------- -------- -------- ------ ----------------------- 
  admin_post_new      ANY      ANY      ANY    /admin/post/new        
  admin_post_show     GET      ANY      ANY    /admin/post/{id}       
  admin_post_edit     ANY      ANY      ANY    /admin/post/{id}/edit  
  admin_post_delete   DELETE   ANY      ANY    /admin/post/{id}       
 ------------------- -------- -------- ------ -----------------------

 ! [CAUTION] Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et    
 ! dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris. Lorem ipsum dolor sit amet, 
 ! consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim    
 ! veniam, quis nostrud exercitation ullamco laboris.                                                                   
 !                                                                                                                      
 ! foo                                                                                                                  

Consectetur Adipisicing Elit Sed Do Eiusmod
-------------------------------------------

 * Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod, tempor incididunt ut labore et dolore magna aliqua.

 * Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

 * Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Hidden question:
 > <f><o><o><enter>

 ! [NOTE] foo

 Choice question no default:
  [0] choice1
  [1] choice2
 > <enter>

 [ERROR] Value "" is invalid                                                                                            

 Choice question no default:
  [0] choice1
  [1] choice2
 > 0<enter>

 ! [NOTE] choice1                                                                                                       

 Choice question with default [choice1]:
  [0] choice1
  [1] choice2
 > 1<enter>

 ! [NOTE] choice2                                                                                                       

 Confirmation with yes default (yes/no) [yes]:
 > <enter>

 ! [NOTE] yes                                                                                                           

 Confirmation with no default (yes/no) [no]:
 > <enter>

 ! [NOTE] no                                                                                                            

 Question no default:
 > <enter>

 [ERROR] A value is required.                                                                                           

 Question no default:
 > foo<enter>

 ! [NOTE] foo                                                                                                           

 Question no default and custom validator:
 > foo<enter>

 [ERROR] cannot be foo                                                                                                  

 Question no default and custom validator:
 > <enter>

 [ERROR] A value is required.                                                                                           

 Question no default and custom validator:
 > foo<enter>

 [ERROR] cannot be foo                                                                                                  

 Question no default and custom validator:
 > bar<enter>

 ! [NOTE] bar                                                                                                           

 Question with default [default]:
 > <enter>

 ! [NOTE] default                                                                                                       

 Question with default and custom validator [default]:
 > <enter>

 ! [NOTE] default                                                                                                       

 ! [NOTE] Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.        
 ! Excepteur sint occaecat cupidatat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu   
 ! fugiat nulla pariatur. Excepteur sint occaecat cupidatat. Duis aute irure dolor in reprehenderit in voluptate velit  
 ! esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat.                                      

 [OK] Lorem ipsum dolor sit amet, consectetur adipisicing elit                                                          

 [ERROR] Duis aute irure dolor in reprehenderit in voluptate velit esse.                                                

 [WARNING] Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi.    

 100/100 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

Screenshots

screen1

screen2

screen

@hhamon
Copy link
Contributor

hhamon commented Mar 25, 2015

Nice work :)

@cryptiklemur
Copy link
Contributor

Hopefully not too much work to get it in to 2.7 :)

$line .= str_repeat(' ', self::MAX_LINE_LENGTH - Helper::strlen($line));

if ($style) {
$line = sprintf('<%s>%s</%s>', $style, $line, $style);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A very minor comment (that you should probably ignore): is not mandatory for the closing style tag to match the opening tag. You can use an empty closing tag to end any styles:

// original code
$line = sprintf('<%s>%s</%s>', $style, $line, $style);

// simpler code with same effect
$line = sprintf('<%s>%s</>', $style, $line);

@kbond
Copy link
Member Author

kbond commented Mar 26, 2015

Assuming no one has any problems with this PR I think it is good to go.

*/
public function createProgressBar($max = 0)
{
$progress = parent::createProgressBar($max);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes more sense to call the variable "progressBar"

{
$progressBar = parent::createProgressBar($max);

if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We used the value of the DIRECTORY_SEPARATOR constant instead:

if ('\\' !== DIRECTORY_SEPARATOR) {

@fabpot
Copy link
Member

fabpot commented Mar 30, 2015

I'm going to merge this one now; we will have 2 months to tweak it and make it better.

@fabpot
Copy link
Member

fabpot commented Mar 30, 2015

Thank you @kbond.

@fabpot fabpot closed this Mar 30, 2015
fabpot added a commit that referenced this pull request Mar 30, 2015
…(kbond)

This PR was squashed before being merged into the 2.7 branch (closes #14057).

Discussion
----------

[RFC][Console] Added console style guide helpers (v2)

*(Rebased to 2.7)*

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #12014, #12035, symfony/symfony-docs#4265
| License       | MIT
| Doc PR        | todo

## Proposed API

### Code

```php
// Symfony command
protected function execute(InputInterface $input, OutputInterface $output)
{
    $output = new SymfonyStyle($output);

    $output->title('Lorem Ipsum Dolor Sit Amet');
    $output->text(array(
        'Duis aute irure dolor in reprehenderit in voluptate velit esse',
        'cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat'
    ));
    $output->ln();

    $output->table(array('Name', 'Method', 'Scheme', 'Host', 'Path'), array(
            array('admin_post_new', 'ANY', 'ANY', 'ANY', '/admin/post/new'),
            array('admin_post_show', 'GET', 'ANY', 'ANY', '/admin/post/{id}'),
            array('admin_post_edit', 'ANY', 'ANY', 'ANY', '/admin/post/{id}/edit'),
            array('admin_post_delete', 'DELETE', 'ANY', 'ANY', '/admin/post/{id}'),
        ));

    $output->caution(array(
            'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.',
            'foo'
        ));
    $output->section('Consectetur Adipisicing Elit Sed Do Eiusmod');
    $output->listing(array(
        'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod, tempor incididunt ut labore et dolore magna aliqua.',
        'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.',
        'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
    ));

    $customValidator = function ($value) {
        if ($value == 'foo') {
            throw new \Exception('cannot be foo');
        }

        return $value;
    };

    // hidden question
    $output->note($output->askHidden('Hidden question'));

    // choice questions
    $output->note($output->choice('Choice question no default', array('choice1', 'choice2')));
    $output->note($output->choice('Choice question with default', array('choice1', 'choice2'), 'choice1'));

    // confirmation questions
    $output->note($output->confirm('Confirmation with yes default', true) ? 'yes' : 'no');
    $output->note($output->confirm('Confirmation with no default', false) ? 'yes' : 'no');

    // standard questions
    $output->note($output->ask('Question no default'));
    $output->note($output->ask('Question no default and custom validator', null, $customValidator));
    $output->note($output->ask('Question with default', 'default'));
    $output->note($output->ask('Question with default and custom validator', 'default', $customValidator));

    $output->note('Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat.');
    $output->success('Lorem ipsum dolor sit amet, consectetur adipisicing elit');
    $output->error('Duis aute irure dolor in reprehenderit in voluptate velit esse.');
    $output->warning('Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi.');

    $output->progressStart(100);

    for ($i = 0; $i < 100; $i++) {
        usleep(10000);
        $output->progressAdvance();
    }

    $output->progressFinish();
}
```

### Output

```
$ php app/console command

Lorem Ipsum Dolor Sit Amet
==========================

 // Duis aute irure dolor in reprehenderit in voluptate velit esse
 // cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat

 ------------------- -------- -------- ------ -----------------------
  Name                Method   Scheme   Host   Path
 ------------------- -------- -------- ------ -----------------------
  admin_post_new      ANY      ANY      ANY    /admin/post/new
  admin_post_show     GET      ANY      ANY    /admin/post/{id}
  admin_post_edit     ANY      ANY      ANY    /admin/post/{id}/edit
  admin_post_delete   DELETE   ANY      ANY    /admin/post/{id}
 ------------------- -------- -------- ------ -----------------------

 ! [CAUTION] Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
 ! dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris. Lorem ipsum dolor sit amet,
 ! consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
 ! veniam, quis nostrud exercitation ullamco laboris.
 !
 ! foo

Consectetur Adipisicing Elit Sed Do Eiusmod
-------------------------------------------

 * Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod, tempor incididunt ut labore et dolore magna aliqua.

 * Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

 * Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Hidden question:
 > <f><o><o><enter>

 ! [NOTE] foo

 Choice question no default:
  [0] choice1
  [1] choice2
 > <enter>

 [ERROR] Value "" is invalid

 Choice question no default:
  [0] choice1
  [1] choice2
 > 0<enter>

 ! [NOTE] choice1

 Choice question with default [choice1]:
  [0] choice1
  [1] choice2
 > 1<enter>

 ! [NOTE] choice2

 Confirmation with yes default (yes/no) [yes]:
 > <enter>

 ! [NOTE] yes

 Confirmation with no default (yes/no) [no]:
 > <enter>

 ! [NOTE] no

 Question no default:
 > <enter>

 [ERROR] A value is required.

 Question no default:
 > foo<enter>

 ! [NOTE] foo

 Question no default and custom validator:
 > foo<enter>

 [ERROR] cannot be foo

 Question no default and custom validator:
 > <enter>

 [ERROR] A value is required.

 Question no default and custom validator:
 > foo<enter>

 [ERROR] cannot be foo

 Question no default and custom validator:
 > bar<enter>

 ! [NOTE] bar

 Question with default [default]:
 > <enter>

 ! [NOTE] default

 Question with default and custom validator [default]:
 > <enter>

 ! [NOTE] default

 ! [NOTE] Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
 ! Excepteur sint occaecat cupidatat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
 ! fugiat nulla pariatur. Excepteur sint occaecat cupidatat. Duis aute irure dolor in reprehenderit in voluptate velit
 ! esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat.

 [OK] Lorem ipsum dolor sit amet, consectetur adipisicing elit

 [ERROR] Duis aute irure dolor in reprehenderit in voluptate velit esse.

 [WARNING] Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi.

 100/100 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

```

### Screenshots

![screen1](https://cloud.githubusercontent.com/assets/127811/4507077/53bc009c-4b09-11e4-937c-44fe7fe30dc0.png)

![screen2](https://cloud.githubusercontent.com/assets/127811/4507078/53bf982e-4b09-11e4-8b5a-8c44c20ae4d9.png)

![screen](https://cloud.githubusercontent.com/assets/127811/6848451/b2e64848-d3a3-11e4-9916-43bd377684ca.png)

Commits
-------

96b4210 [RFC][Console] Added console style guide helpers (v2)
@cryptiklemur
Copy link
Contributor

Thanks @kbond !

@kbond
Copy link
Member Author

kbond commented Mar 31, 2015

@javiereguiluz should I start a PR to have the core Symfony commands use the style guide?

@javiereguiluz
Copy link
Member

@kbond too late :) I've started updating them. See: #14132

But you are right: we need some strategy to coordinate our work updating all the commands.

@wouterj
Copy link
Member

wouterj commented Mar 31, 2015

I would prefer if you could write some documentation about this nice feature (the style thing looks like a nice addition) in a new article called components/console/styles.html or so.

@javiereguiluz
Copy link
Member

@wouterj we'll do that of course. But we're still in the "trial phase". We want to update a bunch of commands and see how they feel. Then we'll tweak the styles and fix some errors (see #14136 for example). And lastly, we'll publish the documentation that you mentioned.

fabpot added a commit that referenced this pull request Apr 7, 2015
…s methods (ogizanagi)

This PR was merged into the 3.0-dev branch.

Discussion
----------

[3.0][Console][OutputStyle] Implements verbosity levels methods

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | N/A - Travis build for #14032
| License       | MIT

Implements the verbosity level methods from `OutputInterface` for the new `OutputStyle` abstract class in 3.0 branch.
Fixes Travis builds with `deps=high` env var for #14032 PR and future console style updates.

=========
Related to: #14032, #14057, #14138, #14132, #14172, ...

Commits
-------

a30f507 [Console] [OutputStyle] Implements verbosity methods
@cordoval cordoval mentioned this pull request Apr 8, 2015
3 tasks
public function progressStart($max = 0)
{
$this->progressBar = $this->createProgressBar($max);
$this->progressBar->start();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know I'm very late in the party, but this API has a major drawback: you are introducing a shared state for the progress bar again (even though it is less an issue that the previous ProgressHelper as it at least creates a new object when starting a new progress bar)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants