Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[Console] Support binary / negatable options #26292

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
[WIP] Implements #24314: Support binary / negatable options, e.g. --f…
…oo and --no-foo.
  • Loading branch information
greg-1-anderson committed Feb 24, 2018
commit a8ad2be59f79a84c1f69855775dfba35e2d73d67
3 changes: 1 addition & 2 deletions 3 src/Symfony/Component/Console/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -949,8 +949,7 @@ protected function getDefaultInputDefinition()
new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'),
new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'),
new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'),
new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'),
new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'),
new InputOption('--ansi', '', InputOption::VALUE_BINARY, 'Force ANSI output', null),
new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'),
));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ private function getInputOptionData(InputOption $option)
'accept_value' => $option->acceptValue(),
'is_value_required' => $option->isValueRequired(),
'is_multiple' => $option->isArray(),
'is_negatable' => $option->isNegatable(),
'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()),
'default' => INF === $option->getDefault() ? 'INF' : $option->getDefault(),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ protected function describeInputArgument(InputArgument $argument, array $options
*/
protected function describeInputOption(InputOption $option, array $options = array())
{
$name = '--'.$option->getName();
$negatable = $option->isNegatable() ? '[no-]' : '';
$name = '--'.$negatable.$option->getName();
if ($option->getShortcut()) {
$name .= '|-'.implode('|-', explode('|', $option->getShortcut())).'';
}
Expand All @@ -79,6 +80,7 @@ protected function describeInputOption(InputOption $option, array $options = arr
.'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n"
.'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n"
.'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n"
.'* Is negatable: '.($option->isNegatable() ? 'yes' : 'no')."\n"
.'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`'
);
}
Expand Down
9 changes: 6 additions & 3 deletions 9 src/Symfony/Component/Console/Descriptor/TextDescriptor.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,12 @@ protected function describeInputArgument(InputArgument $argument, array $options
*/
protected function describeInputOption(InputOption $option, array $options = array())
{
$default = '';
if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
$default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($option->getDefault()));
} else {
$default = '';
} elseif ($option->isNegatable() && (null !== $option->getDefault())) {
$negative_default = $option->getDefault() ? '' : 'no-';
$default = sprintf('<comment> [default: --%s%s]</comment>', $negative_default, $option->getName());
}

$value = '';
Expand All @@ -72,9 +74,10 @@ protected function describeInputOption(InputOption $option, array $options = arr
}

$totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions(array($option));
$negatable = $option->isNegatable() ? '[no-]' : '';
$synopsis = sprintf('%s%s',
$option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : ' ',
sprintf('--%s%s', $option->getName(), $value)
sprintf('--%s%s%s', $negatable, $option->getName(), $value)
);

$spacingWidth = $totalWidth - Helper::strlen($synopsis);
Expand Down
1 change: 1 addition & 0 deletions 1 src/Symfony/Component/Console/Descriptor/XmlDescriptor.php
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ private function getInputOptionDocument(InputOption $option): \DOMDocument
$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->setAttribute('is_negatable', $option->isNegatable() ? 1 : 0);
$objectXML->appendChild($descriptionXML = $dom->createElement('description'));
$descriptionXML->appendChild($dom->createTextNode($option->getDescription()));

Expand Down
33 changes: 33 additions & 0 deletions 33 src/Symfony/Component/Console/Input/ArgvInput.php
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,9 @@ private function addShortOption($shortcut, $value)
private function addLongOption($name, $value)
{
if (!$this->definition->hasOption($name)) {
if ($this->addNegativeBinaryLongOption($name, $value)) {
return;
}
throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name));
}

Expand Down Expand Up @@ -251,6 +254,36 @@ private function addLongOption($name, $value)
}
}

/**
* Adds a long option value.
*
* @param string $name The long option key
* @param mixed $value The value for the option
*
* @return boolean if negative option was found and added
*/
private function addNegativeBinaryLongOption($name, $value)
{
// Negative binary options always start with 'no-'.
if ('no-' != substr($name, 0, 3)) {
return false;
}
$binary_option_name = substr($name, 3);
if (!$this->definition->hasOption($binary_option_name)) {
return false;
}

$option = $this->definition->getOption($binary_option_name);
if (!$option->isNegatable()) {
return false;
}
if (null !== $value && !$option->acceptValue()) {
throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name));
}
$this->options[$binary_option_name] = false;
return true;
}

/**
* {@inheritdoc}
*/
Expand Down
31 changes: 28 additions & 3 deletions 31 src/Symfony/Component/Console/Input/InputOption.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class InputOption
const VALUE_REQUIRED = 2;
const VALUE_OPTIONAL = 4;
const VALUE_IS_ARRAY = 8;
const VALUE_NEGATABLE = 16;
const VALUE_BINARY = (self::VALUE_NONE | self::VALUE_NEGATABLE);

private $name;
private $shortcut;
Expand Down Expand Up @@ -70,7 +72,7 @@ public function __construct(string $name, $shortcut = null, int $mode = null, st

if (null === $mode) {
$mode = self::VALUE_NONE;
} elseif ($mode > 15 || $mode < 1) {
} elseif ($mode > 31 || $mode < 1) {
throw new InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
}

Expand Down Expand Up @@ -146,6 +148,28 @@ public function isArray()
return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
}

/**
* Returns true if the option is negatable (option --foo can be forced
* to 'false' via the --no-foo option).
*
* @return bool true if mode is self::VALUE_NEGATABLE, false otherwise
*/
public function isNegatable()
{
return self::VALUE_NEGATABLE === (self::VALUE_NEGATABLE & $this->mode);
}

/**
* Returns true if the option is binary (can be --foo or --no-foo, and
* nothing else).
*
* @return bool true if negatable and does not have a value.
*/
public function isBinary()
{
return $this->isNegatable() && !$this->acceptValue();
}

/**
* Sets the default value.
*
Expand All @@ -155,7 +179,7 @@ public function isArray()
*/
public function setDefault($default = null)
{
if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) {
if (self::VALUE_NONE === ((self::VALUE_NONE | self::VALUE_NEGATABLE) & $this->mode) && null !== $default) {
throw new LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.');
}

Expand All @@ -167,7 +191,7 @@ public function setDefault($default = null)
}
}

$this->default = $this->acceptValue() ? $default : false;
$this->default = ($this->acceptValue() || $this->isNegatable()) ? $default : false;
}

/**
Expand Down Expand Up @@ -200,6 +224,7 @@ public function equals(InputOption $option)
return $option->getName() === $this->getName()
&& $option->getShortcut() === $this->getShortcut()
&& $option->getDefault() === $this->getDefault()
&& $option->isBinary() === $this->isBinary()
&& $option->isArray() === $this->isArray()
&& $option->isValueRequired() === $this->isValueRequired()
&& $option->isValueOptional() === $this->isValueOptional()
Expand Down
Morty Proxy This is a proxified and sanitized view of the page, visit original site.