4 * This file is part of Psy Shell.
6 * (c) 2012-2018 Justin Hileman
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Psy\Command;
15 use Symfony\Component\Console\Application;
16 use Symfony\Component\Console\Command\Command as BaseCommand;
17 use Symfony\Component\Console\Helper\Table;
18 use Symfony\Component\Console\Helper\TableHelper;
19 use Symfony\Component\Console\Helper\TableStyle;
20 use Symfony\Component\Console\Output\OutputInterface;
23 * The Psy Shell base command.
25 abstract class Command extends BaseCommand
28 * Sets the application instance for this command.
30 * @param Application $application An Application instance
34 public function setApplication(Application $application = null)
36 if ($application !== null && !$application instanceof Shell) {
37 throw new \InvalidArgumentException('PsySH Commands require an instance of Psy\Shell');
40 return parent::setApplication($application);
46 public function asText()
49 '<comment>Usage:</comment>',
50 ' ' . $this->getSynopsis(),
54 if ($this->getAliases()) {
55 $messages[] = $this->aliasesAsText();
58 if ($this->getArguments()) {
59 $messages[] = $this->argumentsAsText();
62 if ($this->getOptions()) {
63 $messages[] = $this->optionsAsText();
66 if ($help = $this->getProcessedHelp()) {
67 $messages[] = '<comment>Help:</comment>';
68 $messages[] = ' ' . str_replace("\n", "\n ", $help) . "\n";
71 return implode("\n", $messages);
77 private function getArguments()
79 $hidden = $this->getHiddenArguments();
81 return array_filter($this->getNativeDefinition()->getArguments(), function ($argument) use ($hidden) {
82 return !in_array($argument->getName(), $hidden);
87 * These arguments will be excluded from help output.
91 protected function getHiddenArguments()
99 private function getOptions()
101 $hidden = $this->getHiddenOptions();
103 return array_filter($this->getNativeDefinition()->getOptions(), function ($option) use ($hidden) {
104 return !in_array($option->getName(), $hidden);
109 * These options will be excluded from help output.
113 protected function getHiddenOptions()
119 * Format command aliases as text..
123 private function aliasesAsText()
125 return '<comment>Aliases:</comment> <info>' . implode(', ', $this->getAliases()) . '</info>' . PHP_EOL;
129 * Format command arguments as text.
133 private function argumentsAsText()
135 $max = $this->getMaxWidth();
138 $arguments = $this->getArguments();
139 if (!empty($arguments)) {
140 $messages[] = '<comment>Arguments:</comment>';
141 foreach ($arguments as $argument) {
142 if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
143 $default = sprintf('<comment> (default: %s)</comment>', $this->formatDefaultValue($argument->getDefault()));
148 $description = str_replace("\n", "\n" . str_pad('', $max + 2, ' '), $argument->getDescription());
150 $messages[] = sprintf(" <info>%-${max}s</info> %s%s", $argument->getName(), $description, $default);
156 return implode(PHP_EOL, $messages);
160 * Format options as text.
164 private function optionsAsText()
166 $max = $this->getMaxWidth();
169 $options = $this->getOptions();
171 $messages[] = '<comment>Options:</comment>';
173 foreach ($options as $option) {
174 if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
175 $default = sprintf('<comment> (default: %s)</comment>', $this->formatDefaultValue($option->getDefault()));
180 $multiple = $option->isArray() ? '<comment> (multiple values allowed)</comment>' : '';
181 $description = str_replace("\n", "\n" . str_pad('', $max + 2, ' '), $option->getDescription());
183 $optionMax = $max - strlen($option->getName()) - 2;
184 $messages[] = sprintf(
185 " <info>%s</info> %-${optionMax}s%s%s%s",
186 '--' . $option->getName(),
187 $option->getShortcut() ? sprintf('(-%s) ', $option->getShortcut()) : '',
197 return implode(PHP_EOL, $messages);
201 * Calculate the maximum padding width for a set of lines.
205 private function getMaxWidth()
209 foreach ($this->getOptions() as $option) {
210 $nameLength = strlen($option->getName()) + 2;
211 if ($option->getShortcut()) {
212 $nameLength += strlen($option->getShortcut()) + 3;
215 $max = max($max, $nameLength);
218 foreach ($this->getArguments() as $argument) {
219 $max = max($max, strlen($argument->getName()));
226 * Format an option default as text.
228 * @param mixed $default
232 private function formatDefaultValue($default)
234 if (is_array($default) && $default === array_values($default)) {
235 return sprintf("array('%s')", implode("', '", $default));
238 return str_replace("\n", '', var_export($default, true));
242 * Get a Table instance.
244 * Falls back to legacy TableHelper.
246 * @return Table|TableHelper
248 protected function getTable(OutputInterface $output)
250 if (!class_exists('Symfony\Component\Console\Helper\Table')) {
251 return $this->getTableHelper();
254 $style = new TableStyle();
256 ->setVerticalBorderChar(' ')
257 ->setHorizontalBorderChar('')
258 ->setCrossingChar('');
260 $table = new Table($output);
268 * Legacy fallback for getTable.
270 * @return TableHelper
272 protected function getTableHelper()
274 $table = $this->getApplication()->getHelperSet()->get('table');
278 ->setLayout(TableHelper::LAYOUT_BORDERLESS)
279 ->setHorizontalBorderChar('')
280 ->setCrossingChar('');