diff --git a/src/Symfony/Component/Console/Completion/Output/BashCompletionOutput.php b/src/Symfony/Component/Console/Completion/Output/BashCompletionOutput.php index 1328cb99a8e50..ba5c0b8ab5936 100644 --- a/src/Symfony/Component/Console/Completion/Output/BashCompletionOutput.php +++ b/src/Symfony/Component/Console/Completion/Output/BashCompletionOutput.php @@ -27,6 +27,24 @@ public function write(CompletionSuggestions $suggestions, OutputInterface $outpu } $output->write(implode(' ', $options)); - $output->writeln(implode(' ', $suggestions->getValueSuggestions())); + $output->writeln($this->normalizeSuggestions($suggestions->getValueSuggestions())); + } + + /** + * Escapes special chars (e.g. backslash or space) and puts quotes around + * the suggestions whenever escaping was needed. + */ + private function normalizeSuggestions(array $suggestions): string + { + $includesUnsafeChars = false; + $suggestions = array_map(function ($value) use (&$includesUnsafeChars) { + $newValue = str_replace('\\', '\\\\', $value); + $newValue = str_replace(' ', '\ ', $value); + $includesUnsafeChars = $includesUnsafeChars || $newValue !== $value; + + return $newValue; + }, $suggestions); + + return $includesUnsafeChars ? "\\'".implode("\\' \\'", $suggestions)."\\'" : implode(' ', $suggestions); } } diff --git a/src/Symfony/Component/Console/Resources/completion.bash b/src/Symfony/Component/Console/Resources/completion.bash index e3614b0322db9..5cf01e78e5f9f 100644 --- a/src/Symfony/Component/Console/Resources/completion.bash +++ b/src/Symfony/Component/Console/Resources/completion.bash @@ -21,7 +21,9 @@ _sf_{{ COMMAND_NAME }}() { local sfcomplete if sfcomplete=$(${completecmd[@]} 2>&1); then - COMPREPLY=($(compgen -W "$sfcomplete" -- "$cur")) + # $sfcomplete is escaped already, escape the input as well + local escapedcur=${cur//\\/\\\\} + COMPREPLY=($(compgen -W "${sfcomplete}" -- "${escapedcur//\'/\\\'}")) __ltrim_colon_completions "$cur" else if [[ "$sfcomplete" != *"Command \"_complete\" is not defined."* ]]; then