-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
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
Comments
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 |
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. |
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. |
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. |
Will the existing helpers have their output adjusted to adhere to the style guide? ie 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. |
@kbond with my example you could actually make backwards compatible implementations using the |
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... |
@iltar I do like your idea but am thinking instantiating a class for each section might be too complex. |
It's not complex, it's flexible. This way people can easily extend/implement their own formatters while having the formatter actually format it. |
You're right, it is more flexible, we could abstract creating these classes to the // 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();
} |
Yeah that's what I meant with:
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
} |
I don't think the methods should be marked as depreciated though. I think it is useful to be able to call: |
I have implemented this in my PR |
…(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    Commits ------- 96b4210 [RFC][Console] Added console style guide helpers (v2)
@javiereguiluz There is probably some tickets to create as follow-ups of this one. |
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.
The text was updated successfully, but these errors were encountered: