diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php
index 4aec01637f883..0290b5bcd9d9d 100644
--- a/src/Symfony/Component/Console/Application.php
+++ b/src/Symfony/Component/Console/Application.php
@@ -11,6 +11,8 @@
namespace Symfony\Component\Console;
+use Symfony\Component\Console\Descriptor\TextDescriptor;
+use Symfony\Component\Console\Descriptor\XmlDescriptor;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\ArrayInput;
@@ -687,47 +689,14 @@ public static function getAbbreviations($names)
* @param boolean $raw Whether to return raw command list
*
* @return string A string representing the Application
+ *
+ * @deprecated Deprecated since version 2.3, to be removed in 3.0.
*/
public function asText($namespace = null, $raw = false)
{
- $commands = $namespace ? $this->all($this->findNamespace($namespace)) : $this->commands;
-
- $width = 0;
- foreach ($commands as $command) {
- $width = strlen($command->getName()) > $width ? strlen($command->getName()) : $width;
- }
- $width += 2;
-
- if ($raw) {
- $messages = array();
- foreach ($this->sortCommands($commands) as $space => $commands) {
- foreach ($commands as $name => $command) {
- $messages[] = sprintf("%-${width}s %s", $name, $command->getDescription());
- }
- }
-
- return implode(PHP_EOL, $messages);
- }
+ $descriptor = new TextDescriptor();
- $messages = array($this->getHelp(), '');
- if ($namespace) {
- $messages[] = sprintf("Available commands for the \"%s\" namespace:", $namespace);
- } else {
- $messages[] = 'Available commands:';
- }
-
- // add commands by namespace
- foreach ($this->sortCommands($commands) as $space => $commands) {
- if (!$namespace && '_global' !== $space) {
- $messages[] = ''.$space.'';
- }
-
- foreach ($commands as $name => $command) {
- $messages[] = sprintf(" %-${width}s %s", $name, $command->getDescription());
- }
- }
-
- return implode(PHP_EOL, $messages);
+ return $descriptor->describe($this, array('namespace' => $namespace, 'raw_text' => $raw));
}
/**
@@ -736,52 +705,15 @@ public function asText($namespace = null, $raw = false)
* @param string $namespace An optional namespace name
* @param Boolean $asDom Whether to return a DOM or an XML string
*
- * @return string|DOMDocument An XML string representing the Application
+ * @return string|\DOMDocument An XML string representing the Application
+ *
+ * @deprecated Deprecated since version 2.3, to be removed in 3.0.
*/
public function asXml($namespace = null, $asDom = false)
{
- $commands = $namespace ? $this->all($this->findNamespace($namespace)) : $this->commands;
-
- $dom = new \DOMDocument('1.0', 'UTF-8');
- $dom->formatOutput = true;
- $dom->appendChild($xml = $dom->createElement('symfony'));
-
- $xml->appendChild($commandsXML = $dom->createElement('commands'));
-
- if ($namespace) {
- $commandsXML->setAttribute('namespace', $namespace);
- } else {
- $namespacesXML = $dom->createElement('namespaces');
- $xml->appendChild($namespacesXML);
- }
-
- // add commands by namespace
- foreach ($this->sortCommands($commands) as $space => $commands) {
- if (!$namespace) {
- $namespaceArrayXML = $dom->createElement('namespace');
- $namespacesXML->appendChild($namespaceArrayXML);
- $namespaceArrayXML->setAttribute('id', $space);
- }
-
- foreach ($commands as $name => $command) {
- if ($name !== $command->getName()) {
- continue;
- }
-
- if (!$namespace) {
- $commandXML = $dom->createElement('command');
- $namespaceArrayXML->appendChild($commandXML);
- $commandXML->appendChild($dom->createTextNode($name));
- }
-
- $node = $command->asXml(true)->getElementsByTagName('command')->item(0);
- $node = $dom->importNode($node, true);
+ $descriptor = new XmlDescriptor();
- $commandsXML->appendChild($node);
- }
- }
-
- return $asDom ? $dom : $dom->saveXml();
+ return $descriptor->describe($this, array('namespace' => $namespace, 'as_dom' => $asDom));
}
/**
@@ -1066,33 +998,6 @@ private function getConsoleMode()
}
}
- /**
- * Sorts commands in alphabetical order.
- *
- * @param array $commands An associative array of commands to sort
- *
- * @return array A sorted array of commands
- */
- private function sortCommands($commands)
- {
- $namespacedCommands = array();
- foreach ($commands as $name => $command) {
- $key = $this->extractNamespace($name, 1);
- if (!$key) {
- $key = '_global';
- }
-
- $namespacedCommands[$key][$name] = $command;
- }
- ksort($namespacedCommands);
-
- foreach ($namespacedCommands as &$commands) {
- ksort($commands);
- }
-
- return $namespacedCommands;
- }
-
/**
* Returns abbreviated suggestions in string format.
*
@@ -1108,12 +1013,14 @@ private function getAbbreviationSuggestions($abbrevs)
/**
* Returns the namespace part of the command name.
*
+ * This method is not part of public API and should not be used directly.
+ *
* @param string $name The full name of the command
* @param string $limit The maximum number of parts of the namespace
*
* @return string The namespace of the command
*/
- private function extractNamespace($name, $limit = null)
+ public function extractNamespace($name, $limit = null)
{
$parts = explode(':', $name);
array_pop($parts);
diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php
index f475ad53632ab..e59854eda256f 100644
--- a/src/Symfony/Component/Console/Command/Command.php
+++ b/src/Symfony/Component/Console/Command/Command.php
@@ -11,6 +11,8 @@
namespace Symfony\Component\Console\Command;
+use Symfony\Component\Console\Descriptor\TextDescriptor;
+use Symfony\Component\Console\Descriptor\XmlDescriptor;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
@@ -273,9 +275,11 @@ public function setCode($code)
/**
* Merges the application definition with the command definition.
*
+ * This method is not part of public API and should not be used directly.
+ *
* @param Boolean $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments
*/
- private function mergeApplicationDefinition($mergeArgs = true)
+ public function mergeApplicationDefinition($mergeArgs = true)
{
if (null === $this->application || true === $this->applicationDefinitionMerged) {
return;
@@ -332,9 +336,11 @@ public function getDefinition()
* Can be overridden to provide the original command representation when it would otherwise
* be changed by merging with the application InputDefinition.
*
+ * This method is not part of public API and should not be used directly.
+ *
* @return InputDefinition An InputDefinition instance
*/
- protected function getNativeDefinition()
+ public function getNativeDefinition()
{
return $this->getDefinition();
}
@@ -559,32 +565,14 @@ public function getHelper($name)
* Returns a text representation of the command.
*
* @return string A string representing the command
+ *
+ * @deprecated Deprecated since version 2.3, to be removed in 3.0.
*/
public function asText()
{
- if ($this->application && !$this->applicationDefinitionMerged) {
- $this->getSynopsis();
- $this->mergeApplicationDefinition(false);
- }
-
- $messages = array(
- 'Usage:',
- ' '.$this->getSynopsis(),
- '',
- );
-
- if ($this->getAliases()) {
- $messages[] = 'Aliases: '.implode(', ', $this->getAliases()).'';
- }
-
- $messages[] = $this->getNativeDefinition()->asText();
-
- if ($help = $this->getProcessedHelp()) {
- $messages[] = 'Help:';
- $messages[] = ' '.str_replace("\n", "\n ", $help)."\n";
- }
+ $descriptor = new TextDescriptor();
- return implode("\n", $messages);
+ return $descriptor->describe($this);
}
/**
@@ -592,41 +580,15 @@ public function asText()
*
* @param Boolean $asDom Whether to return a DOM or an XML string
*
- * @return string|DOMDocument An XML string representing the command
+ * @return string|\DOMDocument An XML string representing the command
+ *
+ * @deprecated Deprecated since version 2.3, to be removed in 3.0.
*/
public function asXml($asDom = false)
{
- if ($this->application && !$this->applicationDefinitionMerged) {
- $this->getSynopsis();
- $this->mergeApplicationDefinition(false);
- }
-
- $dom = new \DOMDocument('1.0', 'UTF-8');
- $dom->formatOutput = true;
- $dom->appendChild($commandXML = $dom->createElement('command'));
- $commandXML->setAttribute('id', $this->name);
- $commandXML->setAttribute('name', $this->name);
-
- $commandXML->appendChild($usageXML = $dom->createElement('usage'));
- $usageXML->appendChild($dom->createTextNode(sprintf($this->getSynopsis(), '')));
-
- $commandXML->appendChild($descriptionXML = $dom->createElement('description'));
- $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $this->getDescription())));
-
- $commandXML->appendChild($helpXML = $dom->createElement('help'));
- $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $this->getProcessedHelp())));
-
- $commandXML->appendChild($aliasesXML = $dom->createElement('aliases'));
- foreach ($this->getAliases() as $alias) {
- $aliasesXML->appendChild($aliasXML = $dom->createElement('alias'));
- $aliasXML->appendChild($dom->createTextNode($alias));
- }
-
- $definition = $this->getNativeDefinition()->asXml(true);
- $commandXML->appendChild($dom->importNode($definition->getElementsByTagName('arguments')->item(0), true));
- $commandXML->appendChild($dom->importNode($definition->getElementsByTagName('options')->item(0), true));
+ $descriptor = new XmlDescriptor();
- return $asDom ? $dom : $dom->saveXml();
+ return $descriptor->describe($this, array('as_dom' => $asDom));
}
private function validateName($name)
diff --git a/src/Symfony/Component/Console/Command/HelpCommand.php b/src/Symfony/Component/Console/Command/HelpCommand.php
index ac4dd3d54d772..2aa933ea0f7a7 100644
--- a/src/Symfony/Component/Console/Command/HelpCommand.php
+++ b/src/Symfony/Component/Console/Command/HelpCommand.php
@@ -11,11 +11,11 @@
namespace Symfony\Component\Console\Command;
+use Symfony\Component\Console\Helper\DescriptorHelper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
-use Symfony\Component\Console\Command\Command;
/**
* HelpCommand displays the help for a given command.
@@ -38,6 +38,8 @@ protected function configure()
->setDefinition(array(
new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'),
+ new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output help in other formats'),
+ new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
))
->setDescription('Displays help for a command')
->setHelp(<<php %command.full_name% list
-You can also output the help as XML by using the --xml option:
+You can also output the help in other formats by using the --format option:
- php %command.full_name% --xml list
+ php %command.full_name% --format=xml list
To display the list of available commands, please use the list command.
EOF
@@ -75,11 +77,11 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
if ($input->getOption('xml')) {
- $output->writeln($this->command->asXml(), OutputInterface::OUTPUT_RAW);
- } else {
- $output->writeln($this->command->asText());
+ $input->setOption('format', 'xml');
}
+ $helper = new DescriptorHelper();
+ $helper->describe($output, $this->command, $input->getOption('format'), $input->getOption('raw'));
$this->command = null;
}
}
diff --git a/src/Symfony/Component/Console/Command/ListCommand.php b/src/Symfony/Component/Console/Command/ListCommand.php
index ec5ea43e5b40e..bc047a87fd057 100644
--- a/src/Symfony/Component/Console/Command/ListCommand.php
+++ b/src/Symfony/Component/Console/Command/ListCommand.php
@@ -11,11 +11,11 @@
namespace Symfony\Component\Console\Command;
+use Symfony\Component\Console\Helper\DescriptorHelper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
-use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputDefinition;
/**
@@ -43,9 +43,9 @@ protected function configure()
php %command.full_name% test
-You can also output the information as XML by using the --xml option:
+You can also output the information in other formats by using the --format option:
- php %command.full_name% --xml
+ php %command.full_name% --format=xml
It's also possible to get raw list of commands (useful for embedding command runner):
@@ -58,7 +58,7 @@ protected function configure()
/**
* {@inheritdoc}
*/
- protected function getNativeDefinition()
+ public function getNativeDefinition()
{
return $this->createDefinition();
}
@@ -69,18 +69,23 @@ protected function getNativeDefinition()
protected function execute(InputInterface $input, OutputInterface $output)
{
if ($input->getOption('xml')) {
- $output->writeln($this->getApplication()->asXml($input->getArgument('namespace')), OutputInterface::OUTPUT_RAW);
- } else {
- $output->writeln($this->getApplication()->asText($input->getArgument('namespace'), $input->getOption('raw')));
+ $input->setOption('format', 'xml');
}
+
+ $helper = new DescriptorHelper();
+ $helper->describe($output, $this->getApplication(), $input->getOption('format'), $input->getOption('raw'));
}
+ /**
+ * {@inheritdoc}
+ */
private function createDefinition()
{
return new InputDefinition(array(
new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
- new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'),
+ new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'),
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
+ new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output list in other formats'),
));
}
}
diff --git a/src/Symfony/Component/Console/Descriptor/ApplicationDescription.php b/src/Symfony/Component/Console/Descriptor/ApplicationDescription.php
new file mode 100644
index 0000000000000..cdf1493c40217
--- /dev/null
+++ b/src/Symfony/Component/Console/Descriptor/ApplicationDescription.php
@@ -0,0 +1,153 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Descriptor;
+
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Command\Command;
+
+/**
+ * @author Jean-François Simon
+ */
+class ApplicationDescription
+{
+ const GLOBAL_NAMESPACE = '_global';
+
+ /**
+ * @var Application
+ */
+ private $application;
+
+ /**
+ * @var null|string
+ */
+ private $namespace;
+
+ /**
+ * @var array
+ */
+ private $namespaces;
+
+ /**
+ * @var Command[]
+ */
+ private $commands;
+
+ /**
+ * @var Command[]
+ */
+ private $aliases;
+
+ /**
+ * Constructor.
+ *
+ * @param Application $application
+ * @param string|null $namespace
+ */
+ public function __construct(Application $application, $namespace = null)
+ {
+ $this->application = $application;
+ $this->namespace = $namespace;
+ }
+
+ /**
+ * @return array
+ */
+ public function getNamespaces()
+ {
+ if (null === $this->namespaces) {
+ $this->inspectApplication();
+ }
+
+ return $this->namespaces;
+ }
+
+ /**
+ * @return Command[]
+ */
+ public function getCommands()
+ {
+ if (null === $this->commands) {
+ $this->inspectApplication();
+ }
+
+ return $this->commands;
+ }
+
+ /**
+ * @param string $name
+ *
+ * @return Command
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function getCommand($name)
+ {
+ if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) {
+ throw new \InvalidArgumentException(sprintf('Command %s does not exist.', $name));
+ }
+
+ return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name];
+ }
+
+ private function inspectApplication()
+ {
+ $this->commands = array();
+ $this->namespaces = array();
+
+ $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null);
+ foreach ($this->sortCommands($all) as $namespace => $commands) {
+ $names = array();
+
+ /** @var Command $command */
+ foreach ($commands as $name => $command) {
+ if (!$command->getName()) {
+ continue;
+ }
+
+ if ($command->getName() === $name) {
+ $this->commands[$name] = $command;
+ } else {
+ $this->aliases[$name] = $command;
+ }
+
+ $names[] = $name;
+ }
+
+ $this->namespaces[$namespace] = array('id' => $namespace, 'commands' => $names);
+ }
+ }
+
+ /**
+ * @param array $commands
+ *
+ * @return array
+ */
+ private function sortCommands(array $commands)
+ {
+ $namespacedCommands = array();
+ foreach ($commands as $name => $command) {
+ $key = $this->application->extractNamespace($name, 1);
+ if (!$key) {
+ $key = '_global';
+ }
+
+ $namespacedCommands[$key][$name] = $command;
+ }
+ ksort($namespacedCommands);
+
+ foreach ($namespacedCommands as &$commands) {
+ ksort($commands);
+ }
+
+ return $namespacedCommands;
+ }
+}
diff --git a/src/Symfony/Component/Console/Descriptor/Descriptor.php b/src/Symfony/Component/Console/Descriptor/Descriptor.php
new file mode 100644
index 0000000000000..659b8f4cc76ad
--- /dev/null
+++ b/src/Symfony/Component/Console/Descriptor/Descriptor.php
@@ -0,0 +1,92 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Descriptor;
+
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputDefinition;
+use Symfony\Component\Console\Input\InputOption;
+
+/**
+ * @author Jean-François Simon
+ */
+abstract class Descriptor implements DescriptorInterface
+{
+ public function describe($object, array $options = array())
+ {
+ switch (true) {
+ case $object instanceof InputArgument:
+ return $this->describeInputArgument($object, $options);
+ case $object instanceof InputOption:
+ return $this->describeInputOption($object, $options);
+ case $object instanceof InputDefinition:
+ return $this->describeInputDefinition($object, $options);
+ case $object instanceof Command:
+ return $this->describeCommand($object, $options);
+ case $object instanceof Application:
+ return $this->describeApplication($object, $options);
+ }
+
+ throw new \InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object)));
+ }
+
+ /**
+ * Describes an InputArgument instance.
+ *
+ * @param InputArgument $argument
+ * @param array $options
+ *
+ * @return string|mixed
+ */
+ abstract protected function describeInputArgument(InputArgument $argument, array $options = array());
+
+ /**
+ * Describes an InputOption instance.
+ *
+ * @param InputOption $option
+ * @param array $options
+ *
+ * @return string|mixed
+ */
+ abstract protected function describeInputOption(InputOption $option, array $options = array());
+
+ /**
+ * Describes an InputDefinition instance.
+ *
+ * @param InputDefinition $definition
+ * @param array $options
+ *
+ * @return string|mixed
+ */
+ abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array());
+
+ /**
+ * Describes a Command instance.
+ *
+ * @param Command $command
+ * @param array $options
+ *
+ * @return string|mixed
+ */
+ abstract protected function describeCommand(Command $command, array $options = array());
+
+ /**
+ * Describes an Application instance.
+ *
+ * @param Application $application
+ * @param array $options
+ *
+ * @return string|mixed
+ */
+ abstract protected function describeApplication(Application $application, array $options = array());
+}
diff --git a/src/Symfony/Component/Console/Descriptor/DescriptorInterface.php b/src/Symfony/Component/Console/Descriptor/DescriptorInterface.php
new file mode 100644
index 0000000000000..a4e8633e8b50c
--- /dev/null
+++ b/src/Symfony/Component/Console/Descriptor/DescriptorInterface.php
@@ -0,0 +1,30 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Descriptor;
+
+/**
+ * Descriptor interface.
+ *
+ * @author Jean-François Simon
+ */
+interface DescriptorInterface
+{
+ /**
+ * Describes an InputArgument instance.
+ *
+ * @param object $object
+ * @param array $options
+ *
+ * @return string|mixed
+ */
+ public function describe($object, array $options = array());
+}
diff --git a/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php b/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php
new file mode 100644
index 0000000000000..0edef847af4ce
--- /dev/null
+++ b/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php
@@ -0,0 +1,129 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Descriptor;
+
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputDefinition;
+use Symfony\Component\Console\Input\InputOption;
+
+/**
+ * JSON descriptor.
+ *
+ * @author Jean-François Simon
+ */
+class JsonDescriptor extends Descriptor
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputArgument(InputArgument $argument, array $options = array())
+ {
+ return $this->output(array(
+ 'name' => $argument->getName(),
+ 'is_required' => $argument->isRequired(),
+ 'is_array' => $argument->isArray(),
+ 'description' => $argument->getDescription(),
+ 'default' => $argument->getDefault(),
+ ), $options);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputOption(InputOption $option, array $options = array())
+ {
+ return $this->output(array(
+ 'name' => '--'.$option->getName(),
+ 'shortcut' => $option->getShortcut() ? '-'.$option->getShortcut() : '',
+ 'accept_value' => $option->acceptValue(),
+ 'is_value_required' => $option->isValueRequired(),
+ 'is_multiple' => $option->isArray(),
+ 'description' => $option->getDescription(),
+ 'default' => $option->getDefault(),
+ ), $options);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputDefinition(InputDefinition $definition, array $options = array())
+ {
+ $inputArguments = array();
+ foreach ($definition->getArguments() as $name => $argument) {
+ $inputArguments[$name] = $this->describeInputArgument($argument, array('as_array' => true));
+ }
+
+ $inputOptions = array();
+ foreach ($definition->getOptions() as $name => $option) {
+ $inputOptions[$name] = $this->describeInputOption($option, array('as_array' => true));
+ }
+
+ return $this->output(array('arguments' => $inputArguments, 'options' => $inputOptions), $options);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeCommand(Command $command, array $options = array())
+ {
+ $command->getSynopsis();
+ $command->mergeApplicationDefinition(false);
+
+ return $this->output(array(
+ 'name' => $command->getName(),
+ 'usage' => $command->getSynopsis(),
+ 'description' => $command->getDescription(),
+ 'help' => $command->getProcessedHelp(),
+ 'aliases' => $command->getAliases(),
+ 'definition' => $this->describeInputDefinition($command->getNativeDefinition(), array('as_array' => true)),
+ ), $options);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeApplication(Application $application, array $options = array())
+ {
+ $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
+ $description = new ApplicationDescription($application, $describedNamespace);
+ $commands = array();
+
+ foreach ($description->getCommands() as $command) {
+ $commands[] = $this->describeCommand($command, array('as_array' => true));
+ }
+
+ $data = $describedNamespace
+ ? array('commands' => $commands, 'namespace' => $describedNamespace)
+ : array('commands' => $commands, 'namespaces' => array_values($description->getNamespaces()));
+
+ return $this->output($data, $options);
+ }
+
+ /**
+ * Outputs data as array or string according to options.
+ *
+ * @param array $data
+ * @param array $options
+ *
+ * @return array|string
+ */
+ private function output(array $data, array $options)
+ {
+ if (isset($options['as_array']) && $options['as_array']) {
+ return $data;
+ }
+
+ return json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0);
+ }
+}
diff --git a/src/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php b/src/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php
new file mode 100644
index 0000000000000..694c4b1def403
--- /dev/null
+++ b/src/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php
@@ -0,0 +1,129 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Descriptor;
+
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputDefinition;
+use Symfony\Component\Console\Input\InputOption;
+
+/**
+ * Markdown descriptor.
+ *
+ * @author Jean-François Simon
+ */
+class MarkdownDescriptor extends Descriptor
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputArgument(InputArgument $argument, array $options = array())
+ {
+ return '**'.$argument->getName().':**'."\n\n"
+ .'* Name: '.($argument->getName() ?: '')."\n"
+ .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n"
+ .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n"
+ .'* Description: '.($argument->getDescription() ?: '')."\n"
+ .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputOption(InputOption $option, array $options = array())
+ {
+ return '**'.$option->getName().':**'."\n\n"
+ .'* Name: `--'.$option->getName().'`'."\n"
+ .'* Shortcut: '.($option->getShortcut() ? '`-'.$option->getShortcut().'`' : '')."\n"
+ .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n"
+ .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n"
+ .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n"
+ .'* Description: '.($option->getDescription() ?: '')."\n"
+ .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputDefinition(InputDefinition $definition, array $options = array())
+ {
+ $blocks = array();
+
+ if (count($definition->getArguments()) > 0) {
+ $blocks[] = '### Arguments:';
+ foreach ($definition->getArguments() as $argument) {
+ $blocks[] = $this->describeInputArgument($argument);
+ }
+ }
+
+ if (count($definition->getOptions()) > 0) {
+ $blocks[] = '### Options:';
+ foreach ($definition->getOptions() as $option) {
+ $blocks[] = $this->describeInputOption($option);
+ }
+ }
+
+ return implode("\n\n", $blocks);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeCommand(Command $command, array $options = array())
+ {
+ $command->getSynopsis();
+ $command->mergeApplicationDefinition(false);
+
+ $markdown = $command->getName()."\n"
+ .str_repeat('-', strlen($command->getName()))."\n\n"
+ .'* Description: '.($command->getDescription() ?: '')."\n"
+ .'* Usage: `'.$command->getSynopsis().'`'."\n"
+ .'* Aliases: '.(count($command->getAliases()) ? '`'.implode('`, `', $command->getAliases()).'`' : '');
+
+ if ($help = $command->getProcessedHelp()) {
+ $markdown .= "\n\n".$help;
+ }
+
+ if ($definitionMarkdown = $this->describeInputDefinition($command->getNativeDefinition())) {
+ $markdown .= "\n\n".$definitionMarkdown;
+ }
+
+ return $markdown;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeApplication(Application $application, array $options = array())
+ {
+ $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
+ $description = new ApplicationDescription($application, $describedNamespace);
+ $blocks = array($application->getName()."\n".str_repeat('=', strlen($application->getName())));
+
+ foreach ($description->getNamespaces() as $namespace) {
+ if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
+ $blocks[] = '**'.$namespace['id'].':**';
+ }
+
+ $blocks[] = implode("\n", array_map(function ($commandName) {
+ return '* '.$commandName;
+ } , $namespace['commands']));
+ }
+
+ foreach ($description->getCommands() as $command) {
+ $blocks[] = $this->describeCommand($command);
+ }
+
+ return implode("\n\n", $blocks);
+ }
+}
diff --git a/src/Symfony/Component/Console/Descriptor/TextDescriptor.php b/src/Symfony/Component/Console/Descriptor/TextDescriptor.php
new file mode 100644
index 0000000000000..2003237441cef
--- /dev/null
+++ b/src/Symfony/Component/Console/Descriptor/TextDescriptor.php
@@ -0,0 +1,210 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Descriptor;
+
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputDefinition;
+use Symfony\Component\Console\Input\InputOption;
+
+/**
+ * Text descriptor.
+ *
+ * @author Jean-François Simon
+ */
+class TextDescriptor extends Descriptor
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputArgument(InputArgument $argument, array $options = array())
+ {
+ if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
+ $default = sprintf(' (default: %s)', $this->formatDefaultValue($argument->getDefault()));
+ } else {
+ $default = '';
+ }
+
+ $nameWidth = isset($options['name_width']) ? $options['name_width'] : strlen($argument->getName());
+ $output = str_replace("\n", "\n".str_repeat(' ', $nameWidth + 2), $argument->getDescription());
+ $output = sprintf(" %-${nameWidth}s %s%s", $argument->getName(), $output, $default);
+
+ return isset($options['raw_text']) && $options['raw_text'] ? strip_tags($output) : $output;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputOption(InputOption $option, array $options = array())
+ {
+ if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
+ $default = sprintf(' (default: %s)', $this->formatDefaultValue($option->getDefault()));
+ } else {
+ $default = '';
+ }
+
+ $nameWidth = isset($options['name_width']) ? $options['name_width'] : strlen($option->getName());
+ $nameWithShortcutWidth = $nameWidth - strlen($option->getName()) - 2;
+
+ $output = sprintf(" %s %-${nameWithShortcutWidth}s%s%s%s",
+ '--'.$option->getName(),
+ $option->getShortcut() ? sprintf('(-%s) ', $option->getShortcut()) : '',
+ str_replace("\n", "\n".str_repeat(' ', $nameWidth + 2), $option->getDescription()),
+ $default,
+ $option->isArray() ? ' (multiple values allowed)' : ''
+ );
+
+ return isset($options['raw_text']) && $options['raw_text'] ? strip_tags($output) : $output;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputDefinition(InputDefinition $definition, array $options = array())
+ {
+ $nameWidth = 0;
+ foreach ($definition->getOptions() as $option) {
+ $nameLength = strlen($option->getName()) + 2;
+ if ($option->getShortcut()) {
+ $nameLength += strlen($option->getShortcut()) + 3;
+ }
+ $nameWidth = max($nameWidth, $nameLength);
+ }
+ foreach ($definition->getArguments() as $argument) {
+ $nameWidth = max($nameWidth, strlen($argument->getName()));
+ }
+ ++$nameWidth;
+
+ $messages = array();
+
+ if ($definition->getArguments()) {
+ $messages[] = 'Arguments:';
+ foreach ($definition->getArguments() as $argument) {
+ $messages[] = $this->describeInputArgument($argument, array('name_width' => $nameWidth));
+ }
+ $messages[] = '';
+ }
+
+ if ($definition->getOptions()) {
+ $messages[] = 'Options:';
+ foreach ($definition->getOptions() as $option) {
+ $messages[] = $this->describeInputOption($option, array('name_width' => $nameWidth));
+ }
+ $messages[] = '';
+ }
+
+ $output = implode("\n", $messages);
+
+ return isset($options['raw_text']) && $options['raw_text'] ? strip_tags($output) : $output;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeCommand(Command $command, array $options = array())
+ {
+ $command->getSynopsis();
+ $command->mergeApplicationDefinition(false);
+ $messages = array('Usage:', ' '.$command->getSynopsis(), '');
+
+ if ($command->getAliases()) {
+ $messages[] = 'Aliases: '.implode(', ', $command->getAliases()).'';
+ }
+
+ $messages[] = $this->describeInputDefinition($command->getNativeDefinition());
+
+ if ($help = $command->getProcessedHelp()) {
+ $messages[] = 'Help:';
+ $messages[] = ' '.str_replace("\n", "\n ", $help)."\n";
+ }
+
+ $output = implode("\n", $messages);
+
+ return isset($options['raw_text']) && $options['raw_text'] ? strip_tags($output) : $output;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeApplication(Application $application, array $options = array())
+ {
+ $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
+ $description = new ApplicationDescription($application, $describedNamespace);
+ $messages = array();
+
+ if (isset($options['raw_text']) && $options['raw_text']) {
+ $width = $this->getColumnWidth($description->getCommands());
+
+ foreach ($description->getCommands() as $command) {
+ $messages[] = sprintf("%-${width}s %s", $command->getName(), $command->getDescription());
+ }
+ } else {
+ $width = $this->getColumnWidth($description->getCommands());
+
+ $messages[] = $application->getHelp();
+ $messages[] = '';
+
+ if ($describedNamespace) {
+ $messages[] = sprintf("Available commands for the \"%s\" namespace:", $describedNamespace);
+ } else {
+ $messages[] = 'Available commands:';
+ }
+
+ // add commands by namespace
+ foreach ($description->getNamespaces() as $namespace) {
+ if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
+ $messages[] = ''.$namespace['id'].'';
+ }
+
+ foreach ($namespace['commands'] as $name) {
+ $messages[] = sprintf(" %-${width}s %s", $name, $description->getCommand($name)->getDescription());
+ }
+ }
+ }
+
+ $output = implode("\n", $messages);
+
+ return isset($options['raw_text']) && $options['raw_text'] ? strip_tags($output) : $output;
+ }
+
+ /**
+ * Formats input option/argument default value.
+ *
+ * @param mixed $default
+ *
+ * @return string
+ */
+ private function formatDefaultValue($default)
+ {
+ if (version_compare(PHP_VERSION, '5.4', '<')) {
+ return str_replace('\/', '/', json_encode($default));
+ }
+
+ return json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
+ }
+
+ /**
+ * @param Command[] $commands
+ *
+ * @return int
+ */
+ private function getColumnWidth(array $commands)
+ {
+ $width = 0;
+ foreach ($commands as $command) {
+ $width = strlen($command->getName()) > $width ? strlen($command->getName()) : $width;
+ }
+
+ return $width + 2;
+ }
+}
diff --git a/src/Symfony/Component/Console/Descriptor/XmlDescriptor.php b/src/Symfony/Component/Console/Descriptor/XmlDescriptor.php
new file mode 100644
index 0000000000000..5e1f93f4fc96e
--- /dev/null
+++ b/src/Symfony/Component/Console/Descriptor/XmlDescriptor.php
@@ -0,0 +1,206 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Descriptor;
+
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputDefinition;
+use Symfony\Component\Console\Input\InputOption;
+
+/**
+ * XML descriptor.
+ *
+ * @author Jean-François Simon
+ */
+class XmlDescriptor extends Descriptor
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputArgument(InputArgument $argument, array $options = array())
+ {
+ $dom = new \DOMDocument('1.0', 'UTF-8');
+
+ $dom->appendChild($objectXML = $dom->createElement('argument'));
+ $objectXML->setAttribute('name', $argument->getName());
+ $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
+ $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
+ $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
+ $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
+
+ $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
+ $defaults = is_array($argument->getDefault()) ? $argument->getDefault() : (is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array()));
+ foreach ($defaults as $default) {
+ $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
+ $defaultXML->appendChild($dom->createTextNode($default));
+ }
+
+ return $this->output($dom, $options);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputOption(InputOption $option, array $options = array())
+ {
+ $dom = new \DOMDocument('1.0', 'UTF-8');
+
+ $dom->appendChild($objectXML = $dom->createElement('option'));
+ $objectXML->setAttribute('name', '--'.$option->getName());
+ $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
+ $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
+ $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
+ $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
+ $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
+ $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
+
+ if ($option->acceptValue()) {
+ $defaults = is_array($option->getDefault()) ? $option->getDefault() : (is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array()));
+ $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
+
+ if (!empty($defaults)) {
+ foreach ($defaults as $default) {
+ $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
+ $defaultXML->appendChild($dom->createTextNode($default));
+ }
+ }
+ }
+
+ return $this->output($dom, $options);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputDefinition(InputDefinition $definition, array $options = array())
+ {
+ $dom = new \DOMDocument('1.0', 'UTF-8');
+ $dom->appendChild($definitionXML = $dom->createElement('definition'));
+
+ $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
+ foreach ($definition->getArguments() as $argument) {
+ $this->appendDocument($argumentsXML, $this->describeInputArgument($argument, array('as_dom' => true)));
+ }
+
+ $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
+ foreach ($definition->getOptions() as $option) {
+ $this->appendDocument($optionsXML, $this->describeInputOption($option, array('as_dom' => true)));
+ }
+
+ return $this->output($dom, $options);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeCommand(Command $command, array $options = array())
+ {
+ $dom = new \DOMDocument('1.0', 'UTF-8');
+ $dom->appendChild($commandXML = $dom->createElement('command'));
+
+ $command->getSynopsis();
+ $command->mergeApplicationDefinition(false);
+
+ $commandXML->setAttribute('id', $command->getName());
+ $commandXML->setAttribute('name', $command->getName());
+
+ $commandXML->appendChild($usageXML = $dom->createElement('usage'));
+ $usageXML->appendChild($dom->createTextNode(sprintf($command->getSynopsis(), '')));
+
+ $commandXML->appendChild($descriptionXML = $dom->createElement('description'));
+ $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription())));
+
+ $commandXML->appendChild($helpXML = $dom->createElement('help'));
+ $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));
+
+ $commandXML->appendChild($aliasesXML = $dom->createElement('aliases'));
+ foreach ($command->getAliases() as $alias) {
+ $aliasesXML->appendChild($aliasXML = $dom->createElement('alias'));
+ $aliasXML->appendChild($dom->createTextNode($alias));
+ }
+
+ $definitionXML = $this->describeInputDefinition($command->getNativeDefinition(), array('as_dom' => true));
+ $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));
+
+ return $this->output($dom, $options);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeApplication(Application $application, array $options = array())
+ {
+ $dom = new \DOMDocument('1.0', 'UTF-8');
+ $dom->appendChild($rootXml = $dom->createElement('symfony'));
+ $rootXml->appendChild($commandsXML = $dom->createElement('commands'));
+
+ $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
+ $description = new ApplicationDescription($application, $describedNamespace);
+
+ if ($describedNamespace) {
+ $commandsXML->setAttribute('namespace', $describedNamespace);
+ }
+
+ foreach ($description->getCommands() as $command) {
+ $this->appendDocument($commandsXML, $this->describeCommand($command, array('as_dom' => true)));
+ }
+
+ if (!$describedNamespace) {
+ $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces'));
+
+ foreach ($description->getNamespaces() as $namespace) {
+ $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
+ $namespaceArrayXML->setAttribute('id', $namespace['id']);
+
+ foreach ($namespace['commands'] as $name) {
+ $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
+ $commandXML->appendChild($dom->createTextNode($name));
+ }
+ }
+ }
+
+ return $this->output($dom, $options);
+ }
+
+ /**
+ * Appends document children to parent node.
+ *
+ * @param \DOMNode $parentNode
+ * @param \DOMNode $importedParent
+ */
+ private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent)
+ {
+ foreach ($importedParent->childNodes as $childNode) {
+ $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true));
+ }
+ }
+
+ /**
+ * Outputs document as DOMDocument or string according to options.
+ *
+ * @param \DOMDocument $dom
+ * @param array $options
+ *
+ * @return \DOMDocument|string
+ */
+ private function output(\DOMDocument $dom, array $options)
+ {
+ if (isset($options['as_dom']) && $options['as_dom']) {
+ return $dom;
+ }
+
+ $dom->formatOutput = true;
+
+ return $dom->saveXML();
+ }
+}
diff --git a/src/Symfony/Component/Console/Helper/DescriptorHelper.php b/src/Symfony/Component/Console/Helper/DescriptorHelper.php
new file mode 100644
index 0000000000000..a114096562c71
--- /dev/null
+++ b/src/Symfony/Component/Console/Helper/DescriptorHelper.php
@@ -0,0 +1,95 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Helper;
+
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Descriptor\DescriptorInterface;
+use Symfony\Component\Console\Descriptor\JsonDescriptor;
+use Symfony\Component\Console\Descriptor\MarkdownDescriptor;
+use Symfony\Component\Console\Descriptor\TextDescriptor;
+use Symfony\Component\Console\Descriptor\XmlDescriptor;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputDefinition;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+/**
+ * This class adds helper method to describe objects in various formats.
+ *
+ * @author Jean-François Simon
+ */
+class DescriptorHelper extends Helper
+{
+ /**
+ * @var DescriptorInterface[]
+ */
+ private $descriptors = array();
+
+ /**
+ * Constructor.
+ */
+ public function __construct()
+ {
+ $this
+ ->register('txt', new TextDescriptor())
+ ->register('xml', new XmlDescriptor())
+ ->register('json', new JsonDescriptor())
+ ->register('md', new MarkdownDescriptor())
+ ;
+ }
+
+ /**
+ * Describes an object if supported.
+ *
+ * @param OutputInterface $output
+ * @param object $object
+ * @param string $format
+ * @param boolean $raw
+ */
+ public function describe(OutputInterface $output, $object, $format = null, $raw = false)
+ {
+ $options = array('raw_text' => $raw, 'format' => $format ?: 'txt');
+ $type = !$raw && 'txt' === $options['format'] ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW;
+
+ if (!isset($this->descriptors[$options['format']])) {
+ throw new \InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format']));
+ }
+
+ $descriptor = $this->descriptors[$options['format']];
+
+ $output->writeln($descriptor->describe($object, $options), $type);
+ }
+
+ /**
+ * Registers a descriptor.
+ *
+ * @param string $format
+ * @param DescriptorInterface $descriptor
+ *
+ * @return DescriptorHelper
+ */
+ public function register($format, DescriptorInterface $descriptor)
+ {
+ $this->descriptors[$format] = $descriptor;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'descriptor';
+ }
+}
diff --git a/src/Symfony/Component/Console/Input/InputDefinition.php b/src/Symfony/Component/Console/Input/InputDefinition.php
index 69d2f1efe125b..204d293cd0053 100644
--- a/src/Symfony/Component/Console/Input/InputDefinition.php
+++ b/src/Symfony/Component/Console/Input/InputDefinition.php
@@ -11,6 +11,9 @@
namespace Symfony\Component\Console\Input;
+use Symfony\Component\Console\Descriptor\TextDescriptor;
+use Symfony\Component\Console\Descriptor\XmlDescriptor;
+
/**
* A InputDefinition represents a set of valid command line arguments and options.
*
@@ -404,70 +407,14 @@ public function getSynopsis()
* Returns a textual representation of the InputDefinition.
*
* @return string A string representing the InputDefinition
+ *
+ * @deprecated Deprecated since version 2.3, to be removed in 3.0.
*/
public function asText()
{
- // find the largest option or argument name
- $max = 0;
- foreach ($this->getOptions() as $option) {
- $nameLength = strlen($option->getName()) + 2;
- if ($option->getShortcut()) {
- $nameLength += strlen($option->getShortcut()) + 3;
- }
-
- $max = max($max, $nameLength);
- }
- foreach ($this->getArguments() as $argument) {
- $max = max($max, strlen($argument->getName()));
- }
- ++$max;
-
- $text = array();
-
- if ($this->getArguments()) {
- $text[] = 'Arguments:';
- foreach ($this->getArguments() as $argument) {
- if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
- $default = sprintf(' (default: %s)', $this->formatDefaultValue($argument->getDefault()));
- } else {
- $default = '';
- }
-
- $description = str_replace("\n", "\n".str_repeat(' ', $max + 2), $argument->getDescription());
-
- $text[] = sprintf(" %-${max}s %s%s", $argument->getName(), $description, $default);
- }
-
- $text[] = '';
- }
-
- if ($this->getOptions()) {
- $text[] = 'Options:';
-
- foreach ($this->getOptions() as $option) {
- if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
- $default = sprintf(' (default: %s)', $this->formatDefaultValue($option->getDefault()));
- } else {
- $default = '';
- }
-
- $multiple = $option->isArray() ? ' (multiple values allowed)' : '';
- $description = str_replace("\n", "\n".str_repeat(' ', $max + 2), $option->getDescription());
-
- $optionMax = $max - strlen($option->getName()) - 2;
- $text[] = sprintf(" %s %-${optionMax}s%s%s%s",
- '--'.$option->getName(),
- $option->getShortcut() ? sprintf('(-%s) ', $option->getShortcut()) : '',
- $description,
- $default,
- $multiple
- );
- }
+ $descriptor = new TextDescriptor();
- $text[] = '';
- }
-
- return implode("\n", $text);
+ return $descriptor->describe($this);
}
/**
@@ -475,61 +422,14 @@ public function asText()
*
* @param Boolean $asDom Whether to return a DOM or an XML string
*
- * @return string|DOMDocument An XML string representing the InputDefinition
+ * @return string|\DOMDocument An XML string representing the InputDefinition
+ *
+ * @deprecated Deprecated since version 2.3, to be removed in 3.0.
*/
public function asXml($asDom = false)
{
- $dom = new \DOMDocument('1.0', 'UTF-8');
- $dom->formatOutput = true;
- $dom->appendChild($definitionXML = $dom->createElement('definition'));
-
- $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
- foreach ($this->getArguments() as $argument) {
- $argumentsXML->appendChild($argumentXML = $dom->createElement('argument'));
- $argumentXML->setAttribute('name', $argument->getName());
- $argumentXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
- $argumentXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
- $argumentXML->appendChild($descriptionXML = $dom->createElement('description'));
- $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
-
- $argumentXML->appendChild($defaultsXML = $dom->createElement('defaults'));
- $defaults = is_array($argument->getDefault()) ? $argument->getDefault() : (is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array()));
- foreach ($defaults as $default) {
- $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
- $defaultXML->appendChild($dom->createTextNode($default));
- }
- }
-
- $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
- foreach ($this->getOptions() as $option) {
- $optionsXML->appendChild($optionXML = $dom->createElement('option'));
- $optionXML->setAttribute('name', '--'.$option->getName());
- $optionXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
- $optionXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
- $optionXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
- $optionXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
- $optionXML->appendChild($descriptionXML = $dom->createElement('description'));
- $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
-
- if ($option->acceptValue()) {
- $optionXML->appendChild($defaultsXML = $dom->createElement('defaults'));
- $defaults = is_array($option->getDefault()) ? $option->getDefault() : (is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array()));
- foreach ($defaults as $default) {
- $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
- $defaultXML->appendChild($dom->createTextNode($default));
- }
- }
- }
-
- return $asDom ? $dom : $dom->saveXml();
- }
-
- private function formatDefaultValue($default)
- {
- if (version_compare(PHP_VERSION, '5.4', '<')) {
- return str_replace('\/', '/', json_encode($default));
- }
+ $descriptor = new XmlDescriptor();
- return json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
+ return $descriptor->describe($this, array('as_dom' => $asDom));
}
}
diff --git a/src/Symfony/Component/Console/Tests/Command/HelpCommandTest.php b/src/Symfony/Component/Console/Tests/Command/HelpCommandTest.php
index f9b72e6ae385e..d60f3e4a67fae 100644
--- a/src/Symfony/Component/Console/Tests/Command/HelpCommandTest.php
+++ b/src/Symfony/Component/Console/Tests/Command/HelpCommandTest.php
@@ -24,8 +24,7 @@ public function testExecuteForCommandAlias()
$command->setApplication(new Application());
$commandTester = new CommandTester($command);
$commandTester->execute(array('command_name' => 'li'));
-
- $this->assertRegExp('/list \[--xml\] \[--raw\] \[namespace\]/', $commandTester->getDisplay(), '->execute() returns a text help for the given command alias');
+ $this->assertRegExp('/list \[--xml\] \[--raw\] \[--format="\.\.\."\] \[namespace\]/', $commandTester->getDisplay(), '->execute() returns a text help for the given command alias');
}
public function testExecuteForCommand()
@@ -34,8 +33,7 @@ public function testExecuteForCommand()
$commandTester = new CommandTester($command);
$command->setCommand(new ListCommand());
$commandTester->execute(array());
-
- $this->assertRegExp('/list \[--xml\] \[--raw\] \[namespace\]/', $commandTester->getDisplay(), '->execute() returns a text help for the given command');
+ $this->assertRegExp('/list \[--xml\] \[--raw\] \[--format="\.\.\."\] \[namespace\]/', $commandTester->getDisplay(), '->execute() returns a text help for the given command');
}
public function testExecuteForCommandWithXmlOption()
@@ -43,8 +41,7 @@ public function testExecuteForCommandWithXmlOption()
$command = new HelpCommand();
$commandTester = new CommandTester($command);
$command->setCommand(new ListCommand());
- $commandTester->execute(array('--xml' => true));
-
+ $commandTester->execute(array('--format' => 'xml'));
$this->assertRegExp('/getDisplay(), '->execute() returns an XML help text if --xml is passed');
}
@@ -53,16 +50,16 @@ public function testExecuteForApplicationCommand()
$application = new Application();
$commandTester = new CommandTester($application->get('help'));
$commandTester->execute(array('command_name' => 'list'));
-
- $this->assertRegExp('/list \[--xml\] \[--raw\] \[namespace\]/', $commandTester->getDisplay(), '->execute() returns a text help for the given command');
+ $this->assertRegExp('/list \[--xml\] \[--raw\] \[--format="\.\.\."\] \[namespace\]/', $commandTester->getDisplay(), '->execute() returns a text help for the given command');
}
+
public function testExecuteForApplicationCommandWithXmlOption()
{
$application = new Application();
$commandTester = new CommandTester($application->get('help'));
- $commandTester->execute(array('command_name' => 'list', '--xml' => true));
-
- $this->assertRegExp('/getDisplay(), '->execute() returns an XML help text if --xml is passed');
+ $commandTester->execute(array('command_name' => 'list', '--format' => 'xml'));
+ $this->assertRegExp('/list \[--xml\] \[--raw\] \[--format="\.\.\."\] \[namespace\]/', $commandTester->getDisplay(), '->execute() returns a text help for the given command');
+ $this->assertRegExp('/getDisplay(), '->execute() returns an XML help text if --format=xml is passed');
}
}
diff --git a/src/Symfony/Component/Console/Tests/Command/ListCommandTest.php b/src/Symfony/Component/Console/Tests/Command/ListCommandTest.php
index cad313652c0aa..156e21db470d8 100644
--- a/src/Symfony/Component/Console/Tests/Command/ListCommandTest.php
+++ b/src/Symfony/Component/Console/Tests/Command/ListCommandTest.php
@@ -29,8 +29,7 @@ public function testExecuteListsCommandsWithXmlOption()
{
$application = new Application();
$commandTester = new CommandTester($command = $application->get('list'));
- $commandTester->execute(array('command' => $command->getName(), '--xml' => true));
-
+ $commandTester->execute(array('command' => $command->getName(), '--format' => 'xml'));
$this->assertRegExp('//', $commandTester->getDisplay(), '->execute() returns a list of available commands in XML if --xml is passed');
}
diff --git a/src/Symfony/Component/Console/Tests/Descriptor/AbstractDescriptorTest.php b/src/Symfony/Component/Console/Tests/Descriptor/AbstractDescriptorTest.php
new file mode 100644
index 0000000000000..703a72c451855
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Descriptor/AbstractDescriptorTest.php
@@ -0,0 +1,98 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Tests\Descriptor;
+
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Descriptor\DescriptorInterface;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputDefinition;
+use Symfony\Component\Console\Input\InputOption;
+
+abstract class AbstractDescriptorTest extends \PHPUnit_Framework_TestCase
+{
+ /** @dataProvider getDescribeInputArgumentTestData */
+ public function testDescribeInputArgument(DescriptorInterface $descriptor, InputArgument $argument, $expectedDescription)
+ {
+ $this->assertEquals(trim($expectedDescription), trim($descriptor->describe($argument)));
+ }
+
+ /** @dataProvider getDescribeInputOptionTestData */
+ public function testDescribeInputOption(DescriptorInterface $descriptor, InputOption $option, $expectedDescription)
+ {
+ $this->assertEquals(trim($expectedDescription), trim($descriptor->describe($option)));
+ }
+
+ /** @dataProvider getDescribeInputDefinitionTestData */
+ public function testDescribeInputDefinition(DescriptorInterface $descriptor, InputDefinition $definition, $expectedDescription)
+ {
+ $this->assertEquals(trim($expectedDescription), trim($descriptor->describe($definition)));
+ }
+
+ /** @dataProvider getDescribeCommandTestData */
+ public function testDescribeCommand(DescriptorInterface $descriptor, Command $command, $expectedDescription)
+ {
+ $this->assertEquals(trim($expectedDescription), trim($descriptor->describe($command)));
+ }
+
+ /** @dataProvider getDescribeApplicationTestData */
+ public function testDescribeApplication(DescriptorInterface $descriptor, Application $application, $expectedDescription)
+ {
+ // Replaces the dynamic placeholders of the command help text with a static version.
+ // The placeholder %command.full_name% includes the script path that is not predictable
+ // and can not be tested against.
+ foreach ($application->all() as $command) {
+ $command->setHelp(str_replace('%command.full_name%', 'app/console %command.name%', $command->getHelp()));
+ }
+
+ $this->assertEquals(trim($expectedDescription), trim($descriptor->describe($application)));
+ }
+
+ public function getDescribeInputArgumentTestData()
+ {
+ return $this->getDescriptionTestData(ObjectsProvider::getInputArguments());
+ }
+
+ public function getDescribeInputOptionTestData()
+ {
+ return $this->getDescriptionTestData(ObjectsProvider::getInputOptions());
+ }
+
+ public function getDescribeInputDefinitionTestData()
+ {
+ return $this->getDescriptionTestData(ObjectsProvider::getInputDefinitions());
+ }
+
+ public function getDescribeCommandTestData()
+ {
+ return $this->getDescriptionTestData(ObjectsProvider::getCommands());
+ }
+
+ public function getDescribeApplicationTestData()
+ {
+ return $this->getDescriptionTestData(ObjectsProvider::getApplications());
+ }
+
+ abstract protected function getDescriptor();
+ abstract protected function getFormat();
+
+ private function getDescriptionTestData(array $objects)
+ {
+ $data = array();
+ foreach ($objects as $name => $object) {
+ $description = file_get_contents(sprintf('%s/../Fixtures/%s.%s', __DIR__, $name, $this->getFormat()));
+ $data[] = array($this->getDescriptor(), $object, $description);
+ }
+
+ return $data;
+ }
+}
diff --git a/src/Symfony/Component/Console/Tests/Descriptor/JsonDescriptorTest.php b/src/Symfony/Component/Console/Tests/Descriptor/JsonDescriptorTest.php
new file mode 100644
index 0000000000000..943ea2956a6b3
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Descriptor/JsonDescriptorTest.php
@@ -0,0 +1,27 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Tests\Descriptor;
+
+use Symfony\Component\Console\Descriptor\JsonDescriptor;
+
+class JsonDescriptorTest extends AbstractDescriptorTest
+{
+ protected function getDescriptor()
+ {
+ return new JsonDescriptor();
+ }
+
+ protected function getFormat()
+ {
+ return 'json';
+ }
+}
diff --git a/src/Symfony/Component/Console/Tests/Descriptor/MarkdownDescriptorTest.php b/src/Symfony/Component/Console/Tests/Descriptor/MarkdownDescriptorTest.php
new file mode 100644
index 0000000000000..c85e8a594beae
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Descriptor/MarkdownDescriptorTest.php
@@ -0,0 +1,27 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Tests\Descriptor;
+
+use Symfony\Component\Console\Descriptor\MarkdownDescriptor;
+
+class MarkdownDescriptorTest extends AbstractDescriptorTest
+{
+ protected function getDescriptor()
+ {
+ return new MarkdownDescriptor();
+ }
+
+ protected function getFormat()
+ {
+ return 'md';
+ }
+}
diff --git a/src/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.php b/src/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.php
new file mode 100644
index 0000000000000..a36732174691a
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.php
@@ -0,0 +1,75 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Tests\Descriptor;
+
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputDefinition;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Tests\Fixtures\DescriptorApplication1;
+use Symfony\Component\Console\Tests\Fixtures\DescriptorApplication2;
+use Symfony\Component\Console\Tests\Fixtures\DescriptorCommand1;
+use Symfony\Component\Console\Tests\Fixtures\DescriptorCommand2;
+use Symfony\Component\Finder\Shell\Command;
+
+/**
+ * @author Jean-François Simon
+ */
+class ObjectsProvider
+{
+ public static function getInputArguments()
+ {
+ return array(
+ 'input_argument_1' => new InputArgument('argument_name', InputArgument::REQUIRED),
+ 'input_argument_2' => new InputArgument('argument_name', InputArgument::IS_ARRAY, 'argument description'),
+ 'input_argument_3' => new InputArgument('argument_name', InputArgument::OPTIONAL, 'argument description', 'default_value'),
+ );
+ }
+
+ public static function getInputOptions()
+ {
+ return array(
+ 'input_option_1' => new InputOption('option_name', 'o', InputOption::VALUE_NONE),
+ 'input_option_2' => new InputOption('option_name', 'o', InputOption::VALUE_OPTIONAL, 'option description', 'default_value'),
+ 'input_option_3' => new InputOption('option_name', 'o', InputOption::VALUE_REQUIRED, 'option description'),
+ 'input_option_4' => new InputOption('option_name', 'o', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, 'option description', array()),
+ );
+ }
+
+ public static function getInputDefinitions()
+ {
+ return array(
+ 'input_definition_1' => new InputDefinition(),
+ 'input_definition_2' => new InputDefinition(array(new InputArgument('argument_name', InputArgument::REQUIRED))),
+ 'input_definition_3' => new InputDefinition(array(new InputOption('option_name', 'o', InputOption::VALUE_NONE))),
+ 'input_definition_4' => new InputDefinition(array(
+ new InputArgument('argument_name', InputArgument::REQUIRED),
+ new InputOption('option_name', 'o', InputOption::VALUE_NONE),
+ )),
+ );
+ }
+
+ public static function getCommands()
+ {
+ return array(
+ 'command_1' => new DescriptorCommand1(),
+ 'command_2' => new DescriptorCommand2(),
+ );
+ }
+
+ public static function getApplications()
+ {
+ return array(
+ 'application_1' => new DescriptorApplication1(),
+ 'application_2' => new DescriptorApplication2(),
+ );
+ }
+}
diff --git a/src/Symfony/Component/Console/Tests/Descriptor/TextDescriptorTest.php b/src/Symfony/Component/Console/Tests/Descriptor/TextDescriptorTest.php
new file mode 100644
index 0000000000000..350b67950d2b1
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Descriptor/TextDescriptorTest.php
@@ -0,0 +1,27 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Tests\Descriptor;
+
+use Symfony\Component\Console\Descriptor\TextDescriptor;
+
+class TextDescriptorTest extends AbstractDescriptorTest
+{
+ protected function getDescriptor()
+ {
+ return new TextDescriptor();
+ }
+
+ protected function getFormat()
+ {
+ return 'txt';
+ }
+}
diff --git a/src/Symfony/Component/Console/Tests/Descriptor/XmlDescriptorTest.php b/src/Symfony/Component/Console/Tests/Descriptor/XmlDescriptorTest.php
new file mode 100644
index 0000000000000..59a5d1ed8a2a5
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Descriptor/XmlDescriptorTest.php
@@ -0,0 +1,27 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Tests\Descriptor;
+
+use Symfony\Component\Console\Descriptor\XmlDescriptor;
+
+class XmlDescriptorTest extends AbstractDescriptorTest
+{
+ protected function getDescriptor()
+ {
+ return new XmlDescriptor();
+ }
+
+ protected function getFormat()
+ {
+ return 'xml';
+ }
+}
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication1.php b/src/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication1.php
new file mode 100644
index 0000000000000..132b6d57ddaa2
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication1.php
@@ -0,0 +1,18 @@
+
+ *
+ * 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\Application;
+
+class DescriptorApplication1 extends Application
+{
+}
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication2.php b/src/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication2.php
new file mode 100644
index 0000000000000..ff5513580041b
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication2.php
@@ -0,0 +1,24 @@
+
+ *
+ * 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\Application;
+
+class DescriptorApplication2 extends Application
+{
+ public function __construct()
+ {
+ parent::__construct('My Symfony application', 'v1.0');
+ $this->add(new DescriptorCommand1());
+ $this->add(new DescriptorCommand2());
+ }
+}
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand1.php b/src/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand1.php
new file mode 100644
index 0000000000000..ede05d7a73c0f
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand1.php
@@ -0,0 +1,27 @@
+
+ *
+ * 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 DescriptorCommand1 extends Command
+{
+ protected function configure()
+ {
+ $this
+ ->setName('descriptor:command1')
+ ->setAliases(array('alias1', 'alias2'))
+ ->setDescription('command 1 description')
+ ->setHelp('command 1 help')
+ ;
+ }
+}
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand2.php b/src/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand2.php
new file mode 100644
index 0000000000000..bc04ca9141272
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand2.php
@@ -0,0 +1,30 @@
+
+ *
+ * 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;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputOption;
+
+class DescriptorCommand2 extends Command
+{
+ protected function configure()
+ {
+ $this
+ ->setName('descriptor:command2')
+ ->setDescription('command 2 description')
+ ->setHelp('command 2 help')
+ ->addArgument('argument_name', InputArgument::REQUIRED)
+ ->addOption('option_name', 'o', InputOption::VALUE_NONE)
+ ;
+ }
+}
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_1.json b/src/Symfony/Component/Console/Tests/Fixtures/application_1.json
new file mode 100644
index 0000000000000..116e125ecfa98
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/application_1.json
@@ -0,0 +1 @@
+{"commands":[{"name":"help","usage":"help [--xml] [--format=\"...\"] [--raw] [command_name]","description":"Displays help for a command","help":"The help<\/info> command displays help for a given command:\n\n php app\/console help list<\/info>\n\nYou can also output the help in other formats by using the --format<\/comment> option:\n\n php app\/console help --format=xml list<\/info>\n\nTo display the list of available commands, please use the list<\/info> command.","aliases":[],"definition":{"arguments":{"command_name":{"name":"command_name","is_required":false,"is_array":false,"description":"The command name","default":"help"}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output help as XML","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"To output help in other formats","default":null},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command help","default":false},"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","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Increase verbosity of messages.","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}}}},{"name":"list","usage":"list [--xml] [--raw] [--format=\"...\"] [namespace]","description":"Lists commands","help":"The list<\/info> command lists all commands:\n\n php app\/console list<\/info>\n\nYou can also display the commands for a specific namespace:\n\n php app\/console list test<\/info>\n\nYou can also output the information in other formats by using the --format<\/comment> option:\n\n php app\/console list --format=xml<\/info>\n\nIt's also possible to get raw list of commands (useful for embedding command runner):\n\n php app\/console list --raw<\/info>","aliases":[],"definition":{"arguments":{"namespace":{"name":"namespace","is_required":false,"is_array":false,"description":"The namespace name","default":null}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output list as XML","default":false},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command list","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"To output list in other formats","default":null}}}}],"namespaces":[{"id":"_global","commands":["help","list"]}]}
\ No newline at end of file
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_1.md b/src/Symfony/Component/Console/Tests/Fixtures/application_1.md
new file mode 100644
index 0000000000000..ca564e45ca1b2
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/application_1.md
@@ -0,0 +1,199 @@
+UNKNOWN
+=======
+
+* help
+* list
+
+help
+----
+
+* Description: Displays help for a command
+* Usage: `help [--xml] [--format="..."] [--raw] [command_name]`
+* Aliases:
+
+The help command displays help for a given command:
+
+ php app/console help list
+
+You can also output the help in other formats by using the --format option:
+
+ php app/console help --format=xml list
+
+To display the list of available commands, please use the list command.
+
+### Arguments:
+
+**command_name:**
+
+* Name: command_name
+* Is required: no
+* Is array: no
+* Description: The command name
+* Default: `'help'`
+
+### Options:
+
+**xml:**
+
+* Name: `--xml`
+* Shortcut:
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: To output help as XML
+* Default: `false`
+
+**format:**
+
+* Name: `--format`
+* Shortcut:
+* Accept value: yes
+* Is value required: yes
+* Is multiple: no
+* Description: To output help in other formats
+* Default: `NULL`
+
+**raw:**
+
+* Name: `--raw`
+* Shortcut:
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: To output raw command help
+* Default: `false`
+
+**help:**
+
+* Name: `--help`
+* Shortcut: `-h`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Display this help message.
+* Default: `false`
+
+**quiet:**
+
+* Name: `--quiet`
+* Shortcut: `-q`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Do not output any message.
+* Default: `false`
+
+**verbose:**
+
+* Name: `--verbose`
+* Shortcut: `-v`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Increase verbosity of messages.
+* Default: `false`
+
+**version:**
+
+* Name: `--version`
+* Shortcut: `-V`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Display this application version.
+* Default: `false`
+
+**ansi:**
+
+* Name: `--ansi`
+* Shortcut:
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Force ANSI output.
+* Default: `false`
+
+**no-ansi:**
+
+* Name: `--no-ansi`
+* Shortcut:
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Disable ANSI output.
+* Default: `false`
+
+**no-interaction:**
+
+* Name: `--no-interaction`
+* Shortcut: `-n`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Do not ask any interactive question.
+* Default: `false`
+
+list
+----
+
+* Description: Lists commands
+* Usage: `list [--xml] [--raw] [--format="..."] [namespace]`
+* Aliases:
+
+The list command lists all commands:
+
+ php app/console list
+
+You can also display the commands for a specific namespace:
+
+ php app/console list test
+
+You can also output the information in other formats by using the --format option:
+
+ php app/console list --format=xml
+
+It's also possible to get raw list of commands (useful for embedding command runner):
+
+ php app/console list --raw
+
+### Arguments:
+
+**namespace:**
+
+* Name: namespace
+* Is required: no
+* Is array: no
+* Description: The namespace name
+* Default: `NULL`
+
+### Options:
+
+**xml:**
+
+* Name: `--xml`
+* Shortcut:
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: To output list as XML
+* Default: `false`
+
+**raw:**
+
+* Name: `--raw`
+* Shortcut:
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: To output raw command list
+* Default: `false`
+
+**format:**
+
+* Name: `--format`
+* Shortcut:
+* Accept value: yes
+* Is value required: yes
+* Is multiple: no
+* Description: To output list in other formats
+* Default: `NULL`
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_1.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_1.txt
new file mode 100644
index 0000000000000..5488ae7873827
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/application_1.txt
@@ -0,0 +1,17 @@
+Console Tool
+
+Usage:
+ [options] command [arguments]
+
+Options:
+ --help -h Display this help message.
+ --quiet -q Do not output any message.
+ --verbose -v Increase verbosity of messages.
+ --version -V Display this application version.
+ --ansi Force ANSI output.
+ --no-ansi Disable ANSI output.
+ --no-interaction -n Do not ask any interactive question.
+
+Available commands:
+ help Displays help for a command
+ list Lists commands
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_1.xml b/src/Symfony/Component/Console/Tests/Fixtures/application_1.xml
new file mode 100644
index 0000000000000..ba5decadfe781
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/application_1.xml
@@ -0,0 +1,104 @@
+
+
+
+
+ help [--xml] [--format="..."] [--raw] [command_name]
+ Displays help for a command
+ The <info>help</info> command displays help for a given command:
+
+ <info>php app/console help list</info>
+
+ You can also output the help in other formats by using the <comment>--format</comment> option:
+
+ <info>php app/console help --format=xml list</info>
+
+ To display the list of available commands, please use the <info>list</info> command.
+
+
+
+ The command name
+
+ help
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ list [--xml] [--raw] [--format="..."] [namespace]
+ Lists commands
+ The <info>list</info> command lists all commands:
+
+ <info>php app/console list</info>
+
+ You can also display the commands for a specific namespace:
+
+ <info>php app/console list test</info>
+
+ You can also output the information in other formats by using the <comment>--format</comment> option:
+
+ <info>php app/console list --format=xml</info>
+
+ It's also possible to get raw list of commands (useful for embedding command runner):
+
+ <info>php app/console list --raw</info>
+
+
+
+ The namespace name
+
+
+
+
+
+
+
+
+
+
+
+
+ help
+ list
+
+
+
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_2.json b/src/Symfony/Component/Console/Tests/Fixtures/application_2.json
new file mode 100644
index 0000000000000..c45e58943fea7
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/application_2.json
@@ -0,0 +1 @@
+{"commands":[{"name":"help","usage":"help [--xml] [--format=\"...\"] [--raw] [command_name]","description":"Displays help for a command","help":"The help<\/info> command displays help for a given command:\n\n php app\/console help list<\/info>\n\nYou can also output the help in other formats by using the --format<\/comment> option:\n\n php app\/console help --format=xml list<\/info>\n\nTo display the list of available commands, please use the list<\/info> command.","aliases":[],"definition":{"arguments":{"command_name":{"name":"command_name","is_required":false,"is_array":false,"description":"The command name","default":"help"}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output help as XML","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"To output help in other formats","default":null},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command help","default":false},"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","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Increase verbosity of messages.","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}}}},{"name":"list","usage":"list [--xml] [--raw] [--format=\"...\"] [namespace]","description":"Lists commands","help":"The list<\/info> command lists all commands:\n\n php app\/console list<\/info>\n\nYou can also display the commands for a specific namespace:\n\n php app\/console list test<\/info>\n\nYou can also output the information in other formats by using the --format<\/comment> option:\n\n php app\/console list --format=xml<\/info>\n\nIt's also possible to get raw list of commands (useful for embedding command runner):\n\n php app\/console list --raw<\/info>","aliases":[],"definition":{"arguments":{"namespace":{"name":"namespace","is_required":false,"is_array":false,"description":"The namespace name","default":null}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output list as XML","default":false},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command list","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"To output list in other formats","default":null}}}},{"name":"descriptor:command1","usage":"descriptor:command1","description":"command 1 description","help":"command 1 help","aliases":["alias1","alias2"],"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","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Increase verbosity of messages.","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}}}},{"name":"descriptor:command2","usage":"descriptor:command2 [-o|--option_name] argument_name","description":"command 2 description","help":"command 2 help","aliases":[],"definition":{"arguments":{"argument_name":{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}},"options":{"option_name":{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false},"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","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Increase verbosity of messages.","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":[{"id":"_global","commands":["alias1","alias2","help","list"]},{"id":"descriptor","commands":["descriptor:command1","descriptor:command2"]}]}
\ No newline at end of file
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_2.md b/src/Symfony/Component/Console/Tests/Fixtures/application_2.md
new file mode 100644
index 0000000000000..f8225ae2531e4
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/application_2.md
@@ -0,0 +1,388 @@
+My Symfony application
+======================
+
+* alias1
+* alias2
+* help
+* list
+
+**descriptor:**
+
+* descriptor:command1
+* descriptor:command2
+
+help
+----
+
+* Description: Displays help for a command
+* Usage: `help [--xml] [--format="..."] [--raw] [command_name]`
+* Aliases:
+
+The help command displays help for a given command:
+
+ php app/console help list
+
+You can also output the help in other formats by using the --format option:
+
+ php app/console help --format=xml list
+
+To display the list of available commands, please use the list command.
+
+### Arguments:
+
+**command_name:**
+
+* Name: command_name
+* Is required: no
+* Is array: no
+* Description: The command name
+* Default: `'help'`
+
+### Options:
+
+**xml:**
+
+* Name: `--xml`
+* Shortcut:
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: To output help as XML
+* Default: `false`
+
+**format:**
+
+* Name: `--format`
+* Shortcut:
+* Accept value: yes
+* Is value required: yes
+* Is multiple: no
+* Description: To output help in other formats
+* Default: `NULL`
+
+**raw:**
+
+* Name: `--raw`
+* Shortcut:
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: To output raw command help
+* Default: `false`
+
+**help:**
+
+* Name: `--help`
+* Shortcut: `-h`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Display this help message.
+* Default: `false`
+
+**quiet:**
+
+* Name: `--quiet`
+* Shortcut: `-q`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Do not output any message.
+* Default: `false`
+
+**verbose:**
+
+* Name: `--verbose`
+* Shortcut: `-v`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Increase verbosity of messages.
+* Default: `false`
+
+**version:**
+
+* Name: `--version`
+* Shortcut: `-V`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Display this application version.
+* Default: `false`
+
+**ansi:**
+
+* Name: `--ansi`
+* Shortcut:
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Force ANSI output.
+* Default: `false`
+
+**no-ansi:**
+
+* Name: `--no-ansi`
+* Shortcut:
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Disable ANSI output.
+* Default: `false`
+
+**no-interaction:**
+
+* Name: `--no-interaction`
+* Shortcut: `-n`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Do not ask any interactive question.
+* Default: `false`
+
+list
+----
+
+* Description: Lists commands
+* Usage: `list [--xml] [--raw] [--format="..."] [namespace]`
+* Aliases:
+
+The list command lists all commands:
+
+ php app/console list
+
+You can also display the commands for a specific namespace:
+
+ php app/console list test
+
+You can also output the information in other formats by using the --format option:
+
+ php app/console list --format=xml
+
+It's also possible to get raw list of commands (useful for embedding command runner):
+
+ php app/console list --raw
+
+### Arguments:
+
+**namespace:**
+
+* Name: namespace
+* Is required: no
+* Is array: no
+* Description: The namespace name
+* Default: `NULL`
+
+### Options:
+
+**xml:**
+
+* Name: `--xml`
+* Shortcut:
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: To output list as XML
+* Default: `false`
+
+**raw:**
+
+* Name: `--raw`
+* Shortcut:
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: To output raw command list
+* Default: `false`
+
+**format:**
+
+* Name: `--format`
+* Shortcut:
+* Accept value: yes
+* Is value required: yes
+* Is multiple: no
+* Description: To output list in other formats
+* Default: `NULL`
+
+descriptor:command1
+-------------------
+
+* Description: command 1 description
+* Usage: `descriptor:command1`
+* Aliases: `alias1`, `alias2`
+
+command 1 help
+
+### Options:
+
+**help:**
+
+* Name: `--help`
+* Shortcut: `-h`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Display this help message.
+* Default: `false`
+
+**quiet:**
+
+* Name: `--quiet`
+* Shortcut: `-q`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Do not output any message.
+* Default: `false`
+
+**verbose:**
+
+* Name: `--verbose`
+* Shortcut: `-v`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Increase verbosity of messages.
+* Default: `false`
+
+**version:**
+
+* Name: `--version`
+* Shortcut: `-V`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Display this application version.
+* Default: `false`
+
+**ansi:**
+
+* Name: `--ansi`
+* Shortcut:
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Force ANSI output.
+* Default: `false`
+
+**no-ansi:**
+
+* Name: `--no-ansi`
+* Shortcut:
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Disable ANSI output.
+* Default: `false`
+
+**no-interaction:**
+
+* Name: `--no-interaction`
+* Shortcut: `-n`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Do not ask any interactive question.
+* Default: `false`
+
+descriptor:command2
+-------------------
+
+* Description: command 2 description
+* Usage: `descriptor:command2 [-o|--option_name] argument_name`
+* Aliases:
+
+command 2 help
+
+### Arguments:
+
+**argument_name:**
+
+* Name: argument_name
+* Is required: yes
+* Is array: no
+* Description:
+* Default: `NULL`
+
+### Options:
+
+**option_name:**
+
+* Name: `--option_name`
+* Shortcut: `-o`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description:
+* Default: `false`
+
+**help:**
+
+* Name: `--help`
+* Shortcut: `-h`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Display this help message.
+* Default: `false`
+
+**quiet:**
+
+* Name: `--quiet`
+* Shortcut: `-q`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Do not output any message.
+* Default: `false`
+
+**verbose:**
+
+* Name: `--verbose`
+* Shortcut: `-v`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Increase verbosity of messages.
+* Default: `false`
+
+**version:**
+
+* Name: `--version`
+* Shortcut: `-V`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Display this application version.
+* Default: `false`
+
+**ansi:**
+
+* Name: `--ansi`
+* Shortcut:
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Force ANSI output.
+* Default: `false`
+
+**no-ansi:**
+
+* Name: `--no-ansi`
+* Shortcut:
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Disable ANSI output.
+* Default: `false`
+
+**no-interaction:**
+
+* Name: `--no-interaction`
+* Shortcut: `-n`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description: Do not ask any interactive question.
+* Default: `false`
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_2.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_2.txt
new file mode 100644
index 0000000000000..a677c3fda9d13
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/application_2.txt
@@ -0,0 +1,22 @@
+My Symfony application version v1.0
+
+Usage:
+ [options] command [arguments]
+
+Options:
+ --help -h Display this help message.
+ --quiet -q Do not output any message.
+ --verbose -v Increase verbosity of messages.
+ --version -V Display this application version.
+ --ansi Force ANSI output.
+ --no-ansi Disable ANSI output.
+ --no-interaction -n Do not ask any interactive question.
+
+Available commands:
+ alias1 command 1 description
+ alias2 command 1 description
+ help Displays help for a command
+ list Lists commands
+descriptor
+ descriptor:command1 command 1 description
+ descriptor:command2 command 2 description
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_2.xml b/src/Symfony/Component/Console/Tests/Fixtures/application_2.xml
new file mode 100644
index 0000000000000..b48546849209e
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/application_2.xml
@@ -0,0 +1,181 @@
+
+
+
+
+ help [--xml] [--format="..."] [--raw] [command_name]
+ Displays help for a command
+ The <info>help</info> command displays help for a given command:
+
+ <info>php app/console help list</info>
+
+ You can also output the help in other formats by using the <comment>--format</comment> option:
+
+ <info>php app/console help --format=xml list</info>
+
+ To display the list of available commands, please use the <info>list</info> command.
+
+
+
+ The command name
+
+ help
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ list [--xml] [--raw] [--format="..."] [namespace]
+ Lists commands
+ The <info>list</info> command lists all commands:
+
+ <info>php app/console list</info>
+
+ You can also display the commands for a specific namespace:
+
+ <info>php app/console list test</info>
+
+ You can also output the information in other formats by using the <comment>--format</comment> option:
+
+ <info>php app/console list --format=xml</info>
+
+ It's also possible to get raw list of commands (useful for embedding command runner):
+
+ <info>php app/console list --raw</info>
+
+
+
+ The namespace name
+
+
+
+
+
+
+
+
+
+
+ descriptor:command1
+ command 1 description
+ command 1 help
+
+ alias1
+ alias2
+
+
+
+
+
+
+
+
+
+
+
+
+
+ descriptor:command2 [-o|--option_name] argument_name
+ command 2 description
+ command 2 help
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ alias1
+ alias2
+ help
+ list
+
+
+ descriptor:command1
+ descriptor:command2
+
+
+
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_asxml1.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_asxml1.txt
index ed168f25cbcda..965bc704f2372 100644
--- a/src/Symfony/Component/Console/Tests/Fixtures/application_asxml1.txt
+++ b/src/Symfony/Component/Console/Tests/Fixtures/application_asxml1.txt
@@ -2,15 +2,15 @@
- help [--xml] [command_name]
+ help [--xml] [--format="..."] [--raw] [command_name]
Displays help for a command
The <info>help</info> command displays help for a given command:
<info>php app/console help list</info>
- You can also output the help as XML by using the <comment>--xml</comment> option:
+ You can also output the help in other formats by using the <comment>--format</comment> option:
- <info>php app/console help --xml list</info>
+ <info>php app/console help --format=xml list</info>
To display the list of available commands, please use the <info>list</info> command.
@@ -26,6 +26,13 @@
+
+
@@ -50,7 +57,7 @@
- list [--xml] [--raw] [namespace]
+ list [--xml] [--raw] [--format="..."] [namespace]
Lists commands
The <info>list</info> command lists all commands:
@@ -60,9 +67,9 @@
<info>php app/console list test</info>
- You can also output the information as XML by using the <comment>--xml</comment> option:
+ You can also output the information in other formats by using the <comment>--format</comment> option:
- <info>php app/console list --xml</info>
+ <info>php app/console list --format=xml</info>
It's also possible to get raw list of commands (useful for embedding command runner):
@@ -76,11 +83,15 @@
+
@@ -118,6 +129,7 @@
+ afoobar
help
list
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txt
index 56dd52ecbe8f3..c758129bee967 100644
--- a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txt
+++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txt
@@ -6,6 +6,6 @@
-list [--xml] [--raw] [namespace]
+list [--xml] [--raw] [--format="..."] [namespace]
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_run2.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_run2.txt
index 6831afdd128c1..627d9ba69b486 100644
--- a/src/Symfony/Component/Console/Tests/Fixtures/application_run2.txt
+++ b/src/Symfony/Component/Console/Tests/Fixtures/application_run2.txt
@@ -1,5 +1,5 @@
Usage:
- help [--xml] [command_name]
+ help [--xml] [--format="..."] [--raw] [command_name]
Arguments:
command The command to execute
@@ -7,6 +7,8 @@ Arguments:
Options:
--xml To output help as XML
+ --format To output help in other formats
+ --raw To output raw command help
--help (-h) Display this help message.
--quiet (-q) Do not output any message.
--verbose (-v) Increase verbosity of messages.
@@ -20,9 +22,9 @@ Help:
php app/console help list
- You can also output the help as XML by using the --xml option:
+ You can also output the help in other formats by using the --format option:
- php app/console help --xml list
+ php app/console help --format=xml list
To display the list of available commands, please use the list command.
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_run3.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_run3.txt
index 441db5485752c..68bf516ded16a 100644
--- a/src/Symfony/Component/Console/Tests/Fixtures/application_run3.txt
+++ b/src/Symfony/Component/Console/Tests/Fixtures/application_run3.txt
@@ -1,12 +1,13 @@
Usage:
- list [--xml] [--raw] [namespace]
+ list [--xml] [--raw] [--format="..."] [namespace]
Arguments:
namespace The namespace name
Options:
- --xml To output help as XML
+ --xml To output list as XML
--raw To output raw command list
+ --format To output list in other formats
Help:
The list command lists all commands:
@@ -17,9 +18,9 @@ Help:
php app/console list test
- You can also output the information as XML by using the --xml option:
+ You can also output the information in other formats by using the --format option:
- php app/console list --xml
+ php app/console list --format=xml
It's also possible to get raw list of commands (useful for embedding command runner):
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/command_1.json b/src/Symfony/Component/Console/Tests/Fixtures/command_1.json
new file mode 100644
index 0000000000000..0c1675dbcef42
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/command_1.json
@@ -0,0 +1 @@
+{"name":"descriptor:command1","usage":"descriptor:command1","description":"command 1 description","help":"command 1 help","aliases":["alias1","alias2"],"definition":{"arguments":[],"options":[]}}
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/command_1.md b/src/Symfony/Component/Console/Tests/Fixtures/command_1.md
new file mode 100644
index 0000000000000..2cef9a2d781ed
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/command_1.md
@@ -0,0 +1,8 @@
+descriptor:command1
+-------------------
+
+* Description: command 1 description
+* Usage: `descriptor:command1`
+* Aliases: `alias1`, `alias2`
+
+command 1 help
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/command_1.txt b/src/Symfony/Component/Console/Tests/Fixtures/command_1.txt
new file mode 100644
index 0000000000000..2375ac0e63d8d
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/command_1.txt
@@ -0,0 +1,7 @@
+Usage:
+ descriptor:command1
+
+Aliases: alias1, alias2
+
+Help:
+ command 1 help
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/command_1.xml b/src/Symfony/Component/Console/Tests/Fixtures/command_1.xml
new file mode 100644
index 0000000000000..dcfa6fa5044e7
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/command_1.xml
@@ -0,0 +1,12 @@
+
+
+ descriptor:command1
+ command 1 description
+ command 1 help
+
+ alias1
+ alias2
+
+
+
+
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/command_2.json b/src/Symfony/Component/Console/Tests/Fixtures/command_2.json
new file mode 100644
index 0000000000000..493b584669ef9
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/command_2.json
@@ -0,0 +1 @@
+{"name":"descriptor:command2","usage":"descriptor:command2 [-o|--option_name] argument_name","description":"command 2 description","help":"command 2 help","aliases":[],"definition":{"arguments":{"argument_name":{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}},"options":{"option_name":{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false}}}}
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/command_2.md b/src/Symfony/Component/Console/Tests/Fixtures/command_2.md
new file mode 100644
index 0000000000000..5257c0d3f2cfc
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/command_2.md
@@ -0,0 +1,30 @@
+descriptor:command2
+-------------------
+
+* Description: command 2 description
+* Usage: `descriptor:command2 [-o|--option_name] argument_name`
+* Aliases:
+
+command 2 help
+
+### Arguments:
+
+**argument_name:**
+
+* Name: argument_name
+* Is required: yes
+* Is array: no
+* Description:
+* Default: `NULL`
+
+### Options:
+
+**option_name:**
+
+* Name: `--option_name`
+* Shortcut: `-o`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description:
+* Default: `false`
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/command_2.txt b/src/Symfony/Component/Console/Tests/Fixtures/command_2.txt
new file mode 100644
index 0000000000000..1da9f3d29fa05
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/command_2.txt
@@ -0,0 +1,11 @@
+Usage:
+ descriptor:command2 [-o|--option_name] argument_name
+
+Arguments:
+ argument_name
+
+Options:
+ --option_name (-o)
+
+Help:
+ command 2 help
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/command_2.xml b/src/Symfony/Component/Console/Tests/Fixtures/command_2.xml
new file mode 100644
index 0000000000000..c411c36c3d285
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/command_2.xml
@@ -0,0 +1,18 @@
+
+
+ descriptor:command2 [-o|--option_name] argument_name
+ command 2 description
+ command 2 help
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_1.json b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_1.json
new file mode 100644
index 0000000000000..b8173b6b3fca9
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_1.json
@@ -0,0 +1 @@
+{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_1.md b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_1.md
new file mode 100644
index 0000000000000..88f311ab534b1
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_1.md
@@ -0,0 +1,7 @@
+**argument_name:**
+
+* Name: argument_name
+* Is required: yes
+* Is array: no
+* Description:
+* Default: `NULL`
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_1.txt b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_1.txt
new file mode 100644
index 0000000000000..111e5157f892d
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_1.txt
@@ -0,0 +1 @@
+ argument_name
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_1.xml b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_1.xml
new file mode 100644
index 0000000000000..cb37f812c5ec4
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_1.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_2.json b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_2.json
new file mode 100644
index 0000000000000..ef06b09a7550f
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_2.json
@@ -0,0 +1 @@
+{"name":"argument_name","is_required":false,"is_array":true,"description":"argument description","default":[]}
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_2.md b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_2.md
new file mode 100644
index 0000000000000..3cdb00cc81867
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_2.md
@@ -0,0 +1,7 @@
+**argument_name:**
+
+* Name: argument_name
+* Is required: no
+* Is array: yes
+* Description: argument description
+* Default: `array ()`
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_2.txt b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_2.txt
new file mode 100644
index 0000000000000..9497b1ce01a96
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_2.txt
@@ -0,0 +1 @@
+ argument_name argument description
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_2.xml b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_2.xml
new file mode 100644
index 0000000000000..629da5a98a3b5
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_2.xml
@@ -0,0 +1,5 @@
+
+
+ argument description
+
+
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_3.json b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_3.json
new file mode 100644
index 0000000000000..de8484e6a72ce
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_3.json
@@ -0,0 +1 @@
+{"name":"argument_name","is_required":false,"is_array":false,"description":"argument description","default":"default_value"}
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_3.md b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_3.md
new file mode 100644
index 0000000000000..be1c443ae0dcf
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_3.md
@@ -0,0 +1,7 @@
+**argument_name:**
+
+* Name: argument_name
+* Is required: no
+* Is array: no
+* Description: argument description
+* Default: `'default_value'`
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_3.txt b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_3.txt
new file mode 100644
index 0000000000000..c421fc9117cad
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_3.txt
@@ -0,0 +1 @@
+ argument_name argument description (default: "default_value")
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_3.xml b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_3.xml
new file mode 100644
index 0000000000000..399a5c864d5dd
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_3.xml
@@ -0,0 +1,7 @@
+
+
+ argument description
+
+ default_value
+
+
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_1.json b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_1.json
new file mode 100644
index 0000000000000..c7a7d838fd5ae
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_1.json
@@ -0,0 +1 @@
+{"arguments":[],"options":[]}
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_1.md b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_1.md
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_1.txt b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_1.txt
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_1.xml b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_1.xml
new file mode 100644
index 0000000000000..b5481ce1276a2
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_1.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_2.json b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_2.json
new file mode 100644
index 0000000000000..9964a55ae31ec
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_2.json
@@ -0,0 +1 @@
+{"arguments":{"argument_name":{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}},"options":[]}
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_2.md b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_2.md
new file mode 100644
index 0000000000000..923191cdcf9f2
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_2.md
@@ -0,0 +1,9 @@
+### Arguments:
+
+**argument_name:**
+
+* Name: argument_name
+* Is required: yes
+* Is array: no
+* Description:
+* Default: `NULL`
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_2.txt b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_2.txt
new file mode 100644
index 0000000000000..0db9f66263a71
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_2.txt
@@ -0,0 +1,2 @@
+Arguments:
+ argument_name
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_2.xml b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_2.xml
new file mode 100644
index 0000000000000..102efc1486381
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_2.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_3.json b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_3.json
new file mode 100644
index 0000000000000..6a86056029784
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_3.json
@@ -0,0 +1 @@
+{"arguments":[],"options":{"option_name":{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false}}}
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_3.md b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_3.md
new file mode 100644
index 0000000000000..40fd7b0a973cb
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_3.md
@@ -0,0 +1,11 @@
+### Options:
+
+**option_name:**
+
+* Name: `--option_name`
+* Shortcut: `-o`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description:
+* Default: `false`
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_3.txt b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_3.txt
new file mode 100644
index 0000000000000..c6fb2ccc7b5b1
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_3.txt
@@ -0,0 +1,2 @@
+Options:
+ --option_name (-o)
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_3.xml b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_3.xml
new file mode 100644
index 0000000000000..bc95151548ada
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_3.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_4.json b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_4.json
new file mode 100644
index 0000000000000..c5a0019fe2a1f
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_4.json
@@ -0,0 +1 @@
+{"arguments":{"argument_name":{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}},"options":{"option_name":{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false}}}
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_4.md b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_4.md
new file mode 100644
index 0000000000000..a31feea477cd9
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_4.md
@@ -0,0 +1,21 @@
+### Arguments:
+
+**argument_name:**
+
+* Name: argument_name
+* Is required: yes
+* Is array: no
+* Description:
+* Default: `NULL`
+
+### Options:
+
+**option_name:**
+
+* Name: `--option_name`
+* Shortcut: `-o`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description:
+* Default: `false`
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_4.txt b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_4.txt
new file mode 100644
index 0000000000000..e17c61c3adf4b
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_4.txt
@@ -0,0 +1,5 @@
+Arguments:
+ argument_name
+
+Options:
+ --option_name (-o)
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_4.xml b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_4.xml
new file mode 100644
index 0000000000000..cffceecef14c7
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_4.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_1.json b/src/Symfony/Component/Console/Tests/Fixtures/input_option_1.json
new file mode 100644
index 0000000000000..60c5b56cb44ea
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_1.json
@@ -0,0 +1 @@
+{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false}
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_1.md b/src/Symfony/Component/Console/Tests/Fixtures/input_option_1.md
new file mode 100644
index 0000000000000..6f9e9a7e074c6
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_1.md
@@ -0,0 +1,9 @@
+**option_name:**
+
+* Name: `--option_name`
+* Shortcut: `-o`
+* Accept value: no
+* Is value required: no
+* Is multiple: no
+* Description:
+* Default: `false`
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_1.txt b/src/Symfony/Component/Console/Tests/Fixtures/input_option_1.txt
new file mode 100644
index 0000000000000..daf83d07ea748
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_1.txt
@@ -0,0 +1 @@
+ --option_name (-o)
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_1.xml b/src/Symfony/Component/Console/Tests/Fixtures/input_option_1.xml
new file mode 100644
index 0000000000000..8a64ea65296e6
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_1.xml
@@ -0,0 +1,4 @@
+
+
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_2.json b/src/Symfony/Component/Console/Tests/Fixtures/input_option_2.json
new file mode 100644
index 0000000000000..04e4228ec3164
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_2.json
@@ -0,0 +1 @@
+{"name":"--option_name","shortcut":"-o","accept_value":true,"is_value_required":false,"is_multiple":false,"description":"option description","default":"default_value"}
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_2.md b/src/Symfony/Component/Console/Tests/Fixtures/input_option_2.md
new file mode 100644
index 0000000000000..634ac0b03c02c
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_2.md
@@ -0,0 +1,9 @@
+**option_name:**
+
+* Name: `--option_name`
+* Shortcut: `-o`
+* Accept value: yes
+* Is value required: no
+* Is multiple: no
+* Description: option description
+* Default: `'default_value'`
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_2.txt b/src/Symfony/Component/Console/Tests/Fixtures/input_option_2.txt
new file mode 100644
index 0000000000000..627e3c1ce5db8
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_2.txt
@@ -0,0 +1 @@
+ --option_name (-o) option description (default: "default_value")
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_2.xml b/src/Symfony/Component/Console/Tests/Fixtures/input_option_2.xml
new file mode 100644
index 0000000000000..4afac5b04e10d
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_2.xml
@@ -0,0 +1,7 @@
+
+
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_3.json b/src/Symfony/Component/Console/Tests/Fixtures/input_option_3.json
new file mode 100644
index 0000000000000..c1ea120c7a24a
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_3.json
@@ -0,0 +1 @@
+{"name":"--option_name","shortcut":"-o","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"option description","default":null}
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_3.md b/src/Symfony/Component/Console/Tests/Fixtures/input_option_3.md
new file mode 100644
index 0000000000000..34282896ba39a
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_3.md
@@ -0,0 +1,9 @@
+**option_name:**
+
+* Name: `--option_name`
+* Shortcut: `-o`
+* Accept value: yes
+* Is value required: yes
+* Is multiple: no
+* Description: option description
+* Default: `NULL`
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_3.txt b/src/Symfony/Component/Console/Tests/Fixtures/input_option_3.txt
new file mode 100644
index 0000000000000..b88b12d2b3e70
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_3.txt
@@ -0,0 +1 @@
+ --option_name (-o) option description
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_3.xml b/src/Symfony/Component/Console/Tests/Fixtures/input_option_3.xml
new file mode 100644
index 0000000000000..dcc0631cf4e6f
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_3.xml
@@ -0,0 +1,5 @@
+
+
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_4.json b/src/Symfony/Component/Console/Tests/Fixtures/input_option_4.json
new file mode 100644
index 0000000000000..1b671d80651ef
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_4.json
@@ -0,0 +1 @@
+{"name":"--option_name","shortcut":"-o","accept_value":true,"is_value_required":false,"is_multiple":true,"description":"option description","default":[]}
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_4.md b/src/Symfony/Component/Console/Tests/Fixtures/input_option_4.md
new file mode 100644
index 0000000000000..8ffba56e73265
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_4.md
@@ -0,0 +1,9 @@
+**option_name:**
+
+* Name: `--option_name`
+* Shortcut: `-o`
+* Accept value: yes
+* Is value required: no
+* Is multiple: yes
+* Description: option description
+* Default: `array ()`
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_4.txt b/src/Symfony/Component/Console/Tests/Fixtures/input_option_4.txt
new file mode 100644
index 0000000000000..5dba5e6e87422
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_4.txt
@@ -0,0 +1 @@
+ --option_name (-o) option description (multiple values allowed)
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_4.xml b/src/Symfony/Component/Console/Tests/Fixtures/input_option_4.xml
new file mode 100644
index 0000000000000..5e2418b14ade3
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_4.xml
@@ -0,0 +1,5 @@
+
+