Skip to content

Commit

Permalink
feature #19954 [Console] Exclude empty namespaces in text descriptor …
Browse files Browse the repository at this point in the history
…(ro0NL)

This PR was merged into the 3.3-dev branch.

Discussion
----------

[Console] Exclude empty namespaces in text descriptor

| Q | A |
| --- | --- |
| Branch? | "master" |
| Bug fix? | yes |
| New feature? | no |
| BC breaks? | no |
| Deprecations? | no |
| Tests pass? | yes |
| Fixed tickets | comma-separated list of tickets fixed by the PR, if any |
| License | MIT |
| Doc PR | reference to the documentation PR, if any |

Before:

```
$ bin/console

 doctrine
  doctrine:mapping:convert                [orm:convert:mapping] Convert mapping information between supported formats.
 orm <----
 router
  router:match                            Helps debug routes by simulating a path info match

$ bin/console list orm

  [Symfony\Component\Debug\Exception\ContextErrorException]
  Warning: max(): Array must contain at least one element

$ bin/console list generate

Available commands for the "generate" namespace:
  generate:bundle      Generates a bundle
  generate:command     Generates a console command
  generate:controller  Generates a controller
```

After:

```
$ bin/console

 doctrine
  doctrine:mapping:convert                [orm:convert:mapping] Convert mapping information between supported formats.
 router
  router:match                            Helps debug routes by simulating a path info match

$ bin/console list orm

Available commands for the "orm" namespace:
  orm:convert:mapping  Convert mapping information between supported formats.

$ bin/console list generate

Available commands for the "generate" namespace:
  generate:bundle             Generates a bundle
  generate:command            Generates a console command
  generate:controller         Generates a controller
  generate:doctrine:crud      Generates a CRUD based on a Doctrine entity
  generate:doctrine:entities  Generates entity classes and method stubs from your mapping information
  generate:doctrine:entity    Generates a new Doctrine entity inside a bundle
  generate:doctrine:form      Generates a form type class based on a Doctrine entity
```

Overrules #19776 but also includes other fixes related to aliases that popped up when writing tests 👍

Commits
-------

d5a7608 [Console] Exclude empty namespaces in text descriptor
  • Loading branch information
fabpot committed Mar 22, 2017
2 parents 858af71 + d5a7608 commit c97407e
Show file tree
Hide file tree
Showing 11 changed files with 298 additions and 21 deletions.
52 changes: 36 additions & 16 deletions src/Symfony/Component/Console/Descriptor/TextDescriptor.php
Expand Up @@ -191,31 +191,47 @@ protected function describeApplication(Application $application, array $options
$this->writeText("\n");
$this->writeText("\n");

$width = $this->getColumnWidth($description->getCommands());
$commands = $description->getCommands();
$namespaces = $description->getNamespaces();
if ($describedNamespace && $namespaces) {
// make sure all alias commands are included when describing a specific namespace
$describedNamespaceInfo = reset($namespaces);
foreach ($describedNamespaceInfo['commands'] as $name) {
$commands[$name] = $description->getCommand($name);
}
}

// calculate max. width based on available commands per namespace
$width = $this->getColumnWidth(call_user_func_array('array_merge', array_map(function ($namespace) use ($commands) {
return array_intersect($namespace['commands'], array_keys($commands));
}, $namespaces)));

if ($describedNamespace) {
$this->writeText(sprintf('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), $options);
} else {
$this->writeText('<comment>Available commands:</comment>', $options);
}

// add commands by namespace
$commands = $description->getCommands();
foreach ($namespaces as $namespace) {
$namespace['commands'] = array_filter($namespace['commands'], function ($name) use ($commands) {
return isset($commands[$name]);
});

if (!$namespace['commands']) {
continue;
}

foreach ($description->getNamespaces() as $namespace) {
if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
$this->writeText("\n");
$this->writeText(' <comment>'.$namespace['id'].'</comment>', $options);
}

foreach ($namespace['commands'] as $name) {
if (isset($commands[$name])) {
$this->writeText("\n");
$spacingWidth = $width - Helper::strlen($name);
$command = $commands[$name];
$commandAliases = $this->getCommandAliasesText($command);
$this->writeText(sprintf(' <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $commandAliases.$command->getDescription()), $options);
}
$this->writeText("\n");
$spacingWidth = $width - Helper::strlen($name);
$command = $commands[$name];
$commandAliases = $name === $command->getName() ? $this->getCommandAliasesText($command) : '';
$this->writeText(sprintf(' <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $commandAliases.$command->getDescription()), $options);
}
}

Expand Down Expand Up @@ -276,7 +292,7 @@ private function formatDefaultValue($default)
}

/**
* @param Command[] $commands
* @param (Command|string)[] $commands
*
* @return int
*/
Expand All @@ -285,13 +301,17 @@ private function getColumnWidth(array $commands)
$widths = array();

foreach ($commands as $command) {
$widths[] = Helper::strlen($command->getName());
foreach ($command->getAliases() as $alias) {
$widths[] = Helper::strlen($alias);
if ($command instanceof Command) {
$widths[] = Helper::strlen($command->getName());
foreach ($command->getAliases() as $alias) {
$widths[] = Helper::strlen($alias);
}
} else {
$widths[] = Helper::strlen($command);
}
}

return max($widths) + 2;
return $widths ? max($widths) + 2 : 0;
}

/**
Expand Down
Expand Up @@ -98,10 +98,10 @@ protected function getDescriptionTestData(array $objects)
return $data;
}

protected function assertDescription($expectedDescription, $describedObject)
protected function assertDescription($expectedDescription, $describedObject, array $options = array())
{
$output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
$this->getDescriptor()->describe($output, $describedObject, array('raw_output' => true));
$this->getDescriptor()->describe($output, $describedObject, $options + array('raw_output' => true));
$this->assertEquals(trim($expectedDescription), trim(str_replace(PHP_EOL, "\n", $output->fetch())));
}
}
Expand Up @@ -26,10 +26,10 @@ protected function getFormat()
return 'json';
}

protected function assertDescription($expectedDescription, $describedObject)
protected function assertDescription($expectedDescription, $describedObject, array $options = array())
{
$output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
$this->getDescriptor()->describe($output, $describedObject, array('raw_output' => true));
$this->getDescriptor()->describe($output, $describedObject, $options + array('raw_output' => true));
$this->assertEquals(json_decode(trim($expectedDescription), true), json_decode(trim(str_replace(PHP_EOL, "\n", $output->fetch())), true));
}
}
Expand Up @@ -12,6 +12,7 @@
namespace Symfony\Component\Console\Tests\Descriptor;

use Symfony\Component\Console\Descriptor\TextDescriptor;
use Symfony\Component\Console\Tests\Fixtures\DescriptorApplication2;
use Symfony\Component\Console\Tests\Fixtures\DescriptorApplicationMbString;
use Symfony\Component\Console\Tests\Fixtures\DescriptorCommandMbString;

Expand All @@ -33,6 +34,13 @@ public function getDescribeApplicationTestData()
));
}

public function testDescribeApplicationWithFilteredNamespace()
{
$application = new DescriptorApplication2();

$this->assertDescription(file_get_contents(__DIR__.'/../Fixtures/application_filtered_namespace.txt'), $application, array('namespace' => 'command4'));
}

protected function getDescriptor()
{
return new TextDescriptor();
Expand Down
Expand Up @@ -21,5 +21,6 @@ public function __construct()
$this->add(new DescriptorCommand1());
$this->add(new DescriptorCommand2());
$this->add(new DescriptorCommand3());
$this->add(new DescriptorCommand4());
}
}
@@ -0,0 +1,25 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Console\Tests\Fixtures;

use Symfony\Component\Console\Command\Command;

class DescriptorCommand4 extends Command
{
protected function configure()
{
$this
->setName('descriptor:command4')
->setAliases(array('descriptor:alias_command4', 'command4:descriptor'))
;
}
}
89 changes: 88 additions & 1 deletion src/Symfony/Component/Console/Tests/Fixtures/application_2.json
Expand Up @@ -398,6 +398,85 @@
}
}
}
},
{
"name": "descriptor:command4",
"hidden": false,
"usage": [
"descriptor:command4",
"descriptor:alias_command4",
"command4:descriptor"
],
"description": null,
"help": "",
"definition": {
"arguments": {},
"options": {
"help": {
"name": "--help",
"shortcut": "-h",
"accept_value": false,
"is_value_required": false,
"is_multiple": false,
"description": "Display this help message",
"default": false
},
"quiet": {
"name": "--quiet",
"shortcut": "-q",
"accept_value": false,
"is_value_required": false,
"is_multiple": false,
"description": "Do not output any message",
"default": false
},
"verbose": {
"name": "--verbose",
"shortcut": "-v|-vv|-vvv",
"accept_value": false,
"is_value_required": false,
"is_multiple": false,
"description": "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug",
"default": false
},
"version": {
"name": "--version",
"shortcut": "-V",
"accept_value": false,
"is_value_required": false,
"is_multiple": false,
"description": "Display this application version",
"default": false
},
"ansi": {
"name": "--ansi",
"shortcut": "",
"accept_value": false,
"is_value_required": false,
"is_multiple": false,
"description": "Force ANSI output",
"default": false
},
"no-ansi": {
"name": "--no-ansi",
"shortcut": "",
"accept_value": false,
"is_value_required": false,
"is_multiple": false,
"description": "Disable ANSI output",
"default": false
},
"no-interaction": {
"name": "--no-interaction",
"shortcut": "-n",
"accept_value": false,
"is_value_required": false,
"is_multiple": false,
"description": "Do not ask any interactive question",
"default": false
}
}
}
}
],
"namespaces": [
Expand All @@ -410,12 +489,20 @@
"list"
]
},
{
"id": "command4",
"commands": [
"command4:descriptor"
]
},
{
"id": "descriptor",
"commands": [
"descriptor:alias_command4",
"descriptor:command1",
"descriptor:command2",
"descriptor:command3"
"descriptor:command3",
"descriptor:command4"
]
}
]
Expand Down
81 changes: 81 additions & 0 deletions src/Symfony/Component/Console/Tests/Fixtures/application_2.md
Expand Up @@ -6,10 +6,16 @@ My Symfony application v1.0
* [`help`](#help)
* [`list`](#list)

**command4:**

* [`command4:descriptor`](#descriptorcommand4)

**descriptor:**

* [`descriptor:alias_command4`](#descriptorcommand4)
* [`descriptor:command1`](#descriptorcommand1)
* [`descriptor:command2`](#descriptorcommand2)
* [`descriptor:command4`](#descriptorcommand4)

`help`
------
Expand Down Expand Up @@ -348,3 +354,78 @@ Do not ask any interactive question
* Is value required: no
* Is multiple: no
* Default: `false`

`descriptor:command4`
---------------------

### Usage

* `descriptor:command4`
* `descriptor:alias_command4`
* `command4:descriptor`


### Options

#### `--help|-h`

Display this help message

* Accept value: no
* Is value required: no
* Is multiple: no
* Default: `false`

#### `--quiet|-q`

Do not output any message

* Accept value: no
* Is value required: no
* Is multiple: no
* Default: `false`

#### `--verbose|-v|-vv|-vvv`

Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

* Accept value: no
* Is value required: no
* Is multiple: no
* Default: `false`

#### `--version|-V`

Display this application version

* Accept value: no
* Is value required: no
* Is multiple: no
* Default: `false`

#### `--ansi`

Force ANSI output

* Accept value: no
* Is value required: no
* Is multiple: no
* Default: `false`

#### `--no-ansi`

Disable ANSI output

* Accept value: no
* Is value required: no
* Is multiple: no
* Default: `false`

#### `--no-interaction|-n`

Do not ask any interactive question

* Accept value: no
* Is value required: no
* Is multiple: no
* Default: `false`
Expand Up @@ -18,3 +18,4 @@ My Symfony application <info>v1.0</info>
<comment>descriptor</comment>
<info>descriptor:command1</info> [alias1|alias2] command 1 description
<info>descriptor:command2</info> command 2 description
<info>descriptor:command4</info> [descriptor:alias_command4|command4:descriptor]

0 comments on commit c97407e

Please sign in to comment.