8000 Add helpers for the new console style guide · Issue #12014 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

Add helpers for the new console style guide #12014

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
javiereguiluz opened this issue Sep 24, 2014 · 14 comments
Closed

Add helpers for the new console style guide #12014

javiereguiluz opened this issue Sep 24, 2014 · 14 comments
Labels
Console DX DX = Developer eXperience (anything that improves the experience of using Symfony)

Comments

@javiereguiluz
Copy link
Member

The problem

The solution

The first obvious proposal would be to add more helpers to FormatterHelper, such as formatTitle(), formatSectionTitle(), formatList(), formatDebugInfo(), formatNoteBlock(), etc.

Anyway, I would prefer to read your opinions about better and more concise solutions.

@stof
Copy link
Member
stof commented Sep 24, 2014

Expanding the FormatterHelper is a good idea. Btw, SensioGeneratorBundle currently has a few helper methods for its own formatting: https://github.com/sensiolabs/SensioGeneratorBundle/blob/v2.4.0/Command/Helper/DialogHelper.php

We also need a new tag in the FormatterStyle for the title, to avoid having to pass <fg=blue> which is not friendly

@stof
Copy link
Member
stof commented Sep 24, 2014

I see a drawback though: we should make it possible for bundles to follow the styleguide without bumping their requirement to Symfony 2.6+, otherwise many bundles will either drop the compatibility with the LTS (making the LTS unsupported by the ecosystem, thus less useful) or ignore the styleguide.
This means that extra styles like <tit 8000 le> should maybe be backported to 2.3+. What do you think @fabpot ?

@linaori
Copy link
Contributor
linaori commented Sep 24, 2014

What about creating format type classes which you can just pass to the formatter?

Using this as example: https://github.com/symfony/Console/blob/master/Helper/FormatterHelper.php

class SectionFormat implements FormatInterface
{
    private $section;
    private $message;
    private $style;

    public function __construct($section, $message, $style = 'info')
    {
        $this->section = $section;
        $this->message = $message;
        $this->style = $style;
    }

    // from interface
    public function format()
    {
        return sprintf('<%s>[%s]</%s> %s', $this->style, $this->section, $this->style, $this->message);
    }
}

The same could be done with the block. Additionally you could add an OutputInterface to the format method, but I think this setup is already sufficient enough. This way users get proper autocomplete without having to rely on helper methods and the documentation/fancy editors to discover possibilities.

This is easy to make backwards compatible as the current formatter can just create those objects during delegation while the methods are marked as deprecated.

@kbond
Copy link
Member
kbond commented Sep 24, 2014

Probably goes without saying but... with the exception of the main command title, I don't think any helpers we add should add newlines before their output. They should only add a newline after.

@kbond
Copy link
Member
kbond commented Sep 24, 2014

Will the existing helpers have their output adjusted to adhere to the style guide? ie Table, TableHelper, QuestionHelper, DialogHelper

From a DX perspective, the helper default output should follow the style guide but this could have some BC breaks for existing 3rd party commands.

@linaori
Copy link
Contributor
linaori commented Sep 25, 2014

@kbond with my example you could actually make backwards compatible implementations using the FormatInterface. The default methods as existing right now can use that and render with the Legacy variants.

@kbond
Copy link
Member
kbond commented Sep 25, 2014

I tried my hand at implementing this here: #12035

Not sure the best way to add "style-guide" formatting for the Table, Question and ProgressBar helpers...

@kbond
Copy link
Member
kbond commented Sep 25, 2014

@iltar I do like your idea but am thinking instantiating a class for each section might be too complex.

@linaori
Copy link
Contributor
linaori commented Sep 25, 2014

It's not complex, it's flexible. This way people can easily extend/implement their own formatters while having the formatter actually format it.

8000

@kbond
Copy link
Member
kbond commented Sep 25, 2014

You're right, it is more flexible, we could abstract creating these classes to the FormatterHelper:

// Symfony\Component\Console\Helper\FormatterHelper

public function formatSection($section, $message, $style = 'info')
{
    return $this->format(new SectionFormat($section, $message, $style = 'info'));
}

public function format(FormatInterface $format)
{
    return $format->format();
}

@linaori
Copy link
Contributor
linaori commented Sep 25, 2014

Yeah that's what I meant with:

This is easy to make backwards compatible as the current formatter can just create those objects during delegation while the methods are marked as deprecated.

The big advantage of creating new objects, is that you can always see what the parameters of the constructor are as opposing to the method arguments. This because you don't know what object the helper returns. This is a very annoying "feature" in the console component.

Additionally, you could write a logging system that writes it to a file by simply implementing your own formatter. You only have to place it at 1 location to enable it:

public function format(FormatInterface $format)
{
    $formatted = $format->format();
    $this->logger->log($this->escapeAnsi($formatted));
    return $formatted;
}

private function escapeAnsi($formatted)
{
    // I remember seeing someone need this somewhere, would fit this example
}

@kbond
Copy link
Member
kbond commented Sep 25, 2014

I don't think the methods should be marked as depreciated though. I think it is useful to be able to call: $formatHelper->formatSection('My section') within your command.

@kbond
Copy link
Member
kbond commented Sep 25, 2014

I have implemented this in my PR

@stof stof added Console DX DX = Developer eXperience (anything that improves the experience of using Symfony) labels Oct 6, 2014
fabpot added a commit that referenced this issue 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)
@fabpot fabpot closed this as completed Mar 30, 2015
@fabpot
Copy link
Member
fabpot commented Mar 30, 2015

@javiereguiluz There is probably some tickets to create as follow-ups of this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Console DX DX = Developer eXperience (anything that improves the experience of using Symfony)
Projects
None yet
Development

No branches or pull requests

5 participants
0