update v1.0.3.3
This commit is contained in:
77
vendor/psy/psysh/src/Psy/Command/BufferCommand.php
vendored
Normal file
77
vendor/psy/psysh/src/Psy/Command/BufferCommand.php
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command;
|
||||
|
||||
use Psy\Output\ShellOutput;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Interact with the current code buffer.
|
||||
*
|
||||
* Shows and clears the buffer for the current multi-line expression.
|
||||
*/
|
||||
class BufferCommand extends Command
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('buffer')
|
||||
->setAliases(array('buf'))
|
||||
->setDefinition(array(
|
||||
new InputOption('clear', '', InputOption::VALUE_NONE, 'Clear the current buffer.'),
|
||||
))
|
||||
->setDescription('Show (or clear) the contents of the code input buffer.')
|
||||
->setHelp(
|
||||
<<<HELP
|
||||
Show the contents of the code buffer for the current multi-line expression.
|
||||
|
||||
Optionally, clear the buffer by passing the <info>--clear</info> option.
|
||||
HELP
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$buf = $this->getApplication()->getCodeBuffer();
|
||||
if ($input->getOption('clear')) {
|
||||
$this->getApplication()->resetCodeBuffer();
|
||||
$output->writeln($this->formatLines($buf, 'urgent'), ShellOutput::NUMBER_LINES);
|
||||
} else {
|
||||
$output->writeln($this->formatLines($buf), ShellOutput::NUMBER_LINES);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper method for wrapping buffer lines in `<urgent>` and `<return>` formatter strings.
|
||||
*
|
||||
* @param array $lines
|
||||
* @param string $type (default: 'return')
|
||||
*
|
||||
* @return array Formatted strings
|
||||
*/
|
||||
protected function formatLines(array $lines, $type = 'return')
|
||||
{
|
||||
$template = sprintf('<%s>%%s</%s>', $type, $type);
|
||||
|
||||
return array_map(function ($line) use ($template) {
|
||||
return sprintf($template, $line);
|
||||
}, $lines);
|
||||
}
|
||||
}
|
||||
49
vendor/psy/psysh/src/Psy/Command/ClearCommand.php
vendored
Normal file
49
vendor/psy/psysh/src/Psy/Command/ClearCommand.php
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command;
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Clear the Psy Shell.
|
||||
*
|
||||
* Just what it says on the tin.
|
||||
*/
|
||||
class ClearCommand extends Command
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('clear')
|
||||
->setDefinition(array())
|
||||
->setDescription('Clear the Psy Shell screen.')
|
||||
->setHelp(
|
||||
<<<HELP
|
||||
Clear the Psy Shell screen.
|
||||
|
||||
Pro Tip: If your PHP has readline support, you should be able to use ctrl+l too!
|
||||
HELP
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$output->write(sprintf('%c[2J%c[0;0f', 27, 27));
|
||||
}
|
||||
}
|
||||
282
vendor/psy/psysh/src/Psy/Command/Command.php
vendored
Normal file
282
vendor/psy/psysh/src/Psy/Command/Command.php
vendored
Normal file
@@ -0,0 +1,282 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command;
|
||||
|
||||
use Psy\Shell;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Command\Command as BaseCommand;
|
||||
use Symfony\Component\Console\Helper\Table;
|
||||
use Symfony\Component\Console\Helper\TableHelper;
|
||||
use Symfony\Component\Console\Helper\TableStyle;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* The Psy Shell base command.
|
||||
*/
|
||||
abstract class Command extends BaseCommand
|
||||
{
|
||||
/**
|
||||
* Sets the application instance for this command.
|
||||
*
|
||||
* @param Application $application An Application instance
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setApplication(Application $application = null)
|
||||
{
|
||||
if ($application !== null && !$application instanceof Shell) {
|
||||
throw new \InvalidArgumentException('PsySH Commands require an instance of Psy\Shell.');
|
||||
}
|
||||
|
||||
return parent::setApplication($application);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function asText()
|
||||
{
|
||||
$messages = array(
|
||||
'<comment>Usage:</comment>',
|
||||
' ' . $this->getSynopsis(),
|
||||
'',
|
||||
);
|
||||
|
||||
if ($this->getAliases()) {
|
||||
$messages[] = $this->aliasesAsText();
|
||||
}
|
||||
|
||||
if ($this->getArguments()) {
|
||||
$messages[] = $this->argumentsAsText();
|
||||
}
|
||||
|
||||
if ($this->getOptions()) {
|
||||
$messages[] = $this->optionsAsText();
|
||||
}
|
||||
|
||||
if ($help = $this->getProcessedHelp()) {
|
||||
$messages[] = '<comment>Help:</comment>';
|
||||
$messages[] = ' ' . str_replace("\n", "\n ", $help) . "\n";
|
||||
}
|
||||
|
||||
return implode("\n", $messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
private function getArguments()
|
||||
{
|
||||
$hidden = $this->getHiddenArguments();
|
||||
|
||||
return array_filter($this->getNativeDefinition()->getArguments(), function ($argument) use ($hidden) {
|
||||
return !in_array($argument->getName(), $hidden);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* These arguments will be excluded from help output.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getHiddenArguments()
|
||||
{
|
||||
return array('command');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
private function getOptions()
|
||||
{
|
||||
$hidden = $this->getHiddenOptions();
|
||||
|
||||
return array_filter($this->getNativeDefinition()->getOptions(), function ($option) use ($hidden) {
|
||||
return !in_array($option->getName(), $hidden);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* These options will be excluded from help output.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getHiddenOptions()
|
||||
{
|
||||
return array('verbose');
|
||||
}
|
||||
|
||||
/**
|
||||
* Format command aliases as text..
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function aliasesAsText()
|
||||
{
|
||||
return '<comment>Aliases:</comment> <info>' . implode(', ', $this->getAliases()) . '</info>' . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format command arguments as text.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function argumentsAsText()
|
||||
{
|
||||
$max = $this->getMaxWidth();
|
||||
$messages = array();
|
||||
|
||||
$arguments = $this->getArguments();
|
||||
if (!empty($arguments)) {
|
||||
$messages[] = '<comment>Arguments:</comment>';
|
||||
foreach ($arguments as $argument) {
|
||||
if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
|
||||
$default = sprintf('<comment> (default: %s)</comment>', $this->formatDefaultValue($argument->getDefault()));
|
||||
} else {
|
||||
$default = '';
|
||||
}
|
||||
|
||||
$description = str_replace("\n", "\n" . str_pad('', $max + 2, ' '), $argument->getDescription());
|
||||
|
||||
$messages[] = sprintf(" <info>%-${max}s</info> %s%s", $argument->getName(), $description, $default);
|
||||
}
|
||||
|
||||
$messages[] = '';
|
||||
}
|
||||
|
||||
return implode(PHP_EOL, $messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format options as text.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function optionsAsText()
|
||||
{
|
||||
$max = $this->getMaxWidth();
|
||||
$messages = array();
|
||||
|
||||
$options = $this->getOptions();
|
||||
if ($options) {
|
||||
$messages[] = '<comment>Options:</comment>';
|
||||
|
||||
foreach ($options as $option) {
|
||||
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 = '';
|
||||
}
|
||||
|
||||
$multiple = $option->isArray() ? '<comment> (multiple values allowed)</comment>' : '';
|
||||
$description = str_replace("\n", "\n" . str_pad('', $max + 2, ' '), $option->getDescription());
|
||||
|
||||
$optionMax = $max - strlen($option->getName()) - 2;
|
||||
$messages[] = sprintf(
|
||||
" <info>%s</info> %-${optionMax}s%s%s%s",
|
||||
'--' . $option->getName(),
|
||||
$option->getShortcut() ? sprintf('(-%s) ', $option->getShortcut()) : '',
|
||||
$description,
|
||||
$default,
|
||||
$multiple
|
||||
);
|
||||
}
|
||||
|
||||
$messages[] = '';
|
||||
}
|
||||
|
||||
return implode(PHP_EOL, $messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the maximum padding width for a set of lines.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function getMaxWidth()
|
||||
{
|
||||
$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()));
|
||||
}
|
||||
|
||||
return ++$max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format an option default as text.
|
||||
*
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function formatDefaultValue($default)
|
||||
{
|
||||
if (is_array($default) && $default === array_values($default)) {
|
||||
return sprintf("array('%s')", implode("', '", $default));
|
||||
}
|
||||
|
||||
return str_replace("\n", '', var_export($default, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Table instance.
|
||||
*
|
||||
* Falls back to legacy TableHelper.
|
||||
*
|
||||
* @return Table|TableHelper
|
||||
*/
|
||||
protected function getTable(OutputInterface $output)
|
||||
{
|
||||
if (!class_exists('Symfony\Component\Console\Helper\Table')) {
|
||||
return $this->getTableHelper();
|
||||
}
|
||||
|
||||
$style = new TableStyle();
|
||||
$style
|
||||
->setVerticalBorderChar(' ')
|
||||
->setHorizontalBorderChar('')
|
||||
->setCrossingChar('');
|
||||
|
||||
$table = new Table($output);
|
||||
|
||||
return $table
|
||||
->setRows(array())
|
||||
->setStyle($style);
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy fallback for getTable.
|
||||
*
|
||||
* @return TableHelper
|
||||
*/
|
||||
protected function getTableHelper()
|
||||
{
|
||||
$table = $this->getApplication()->getHelperSet()->get('table');
|
||||
|
||||
return $table
|
||||
->setRows(array())
|
||||
->setLayout(TableHelper::LAYOUT_BORDERLESS)
|
||||
->setHorizontalBorderChar('')
|
||||
->setCrossingChar('');
|
||||
}
|
||||
}
|
||||
98
vendor/psy/psysh/src/Psy/Command/DocCommand.php
vendored
Normal file
98
vendor/psy/psysh/src/Psy/Command/DocCommand.php
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command;
|
||||
|
||||
use Psy\Formatter\DocblockFormatter;
|
||||
use Psy\Formatter\SignatureFormatter;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Read the documentation for an object, class, constant, method or property.
|
||||
*/
|
||||
class DocCommand extends ReflectingCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('doc')
|
||||
->setAliases(array('rtfm', 'man'))
|
||||
->setDefinition(array(
|
||||
new InputArgument('value', InputArgument::REQUIRED, 'Function, class, instance, constant, method or property to document.'),
|
||||
))
|
||||
->setDescription('Read the documentation for an object, class, constant, method or property.')
|
||||
->setHelp(
|
||||
<<<HELP
|
||||
Read the documentation for an object, class, constant, method or property.
|
||||
|
||||
It's awesome for well-documented code, not quite as awesome for poorly documented code.
|
||||
|
||||
e.g.
|
||||
<return>>>> doc preg_replace</return>
|
||||
<return>>>> doc Psy\Shell</return>
|
||||
<return>>>> doc Psy\Shell::debug</return>
|
||||
<return>>>> \$s = new Psy\Shell</return>
|
||||
<return>>>> doc \$s->run</return>
|
||||
HELP
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
list($value, $reflector) = $this->getTargetAndReflector($input->getArgument('value'));
|
||||
|
||||
$doc = $this->getManualDoc($reflector) ?: DocblockFormatter::format($reflector);
|
||||
$db = $this->getApplication()->getManualDb();
|
||||
|
||||
$output->page(function ($output) use ($reflector, $doc, $db) {
|
||||
$output->writeln(SignatureFormatter::format($reflector));
|
||||
if (empty($doc) && !$db) {
|
||||
$output->writeln('');
|
||||
$output->writeln('<warning>PHP manual not found</warning>');
|
||||
$output->writeln(' To document core PHP functionality, download the PHP reference manual:');
|
||||
$output->writeln(' https://github.com/bobthecow/psysh#downloading-the-manual');
|
||||
} else {
|
||||
$output->writeln('');
|
||||
$output->writeln($doc);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private function getManualDoc($reflector)
|
||||
{
|
||||
switch (get_class($reflector)) {
|
||||
case 'ReflectionFunction':
|
||||
$id = $reflector->name;
|
||||
break;
|
||||
|
||||
case 'ReflectionMethod':
|
||||
$id = $reflector->class . '::' . $reflector->name;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($db = $this->getApplication()->getManualDb()) {
|
||||
return $db
|
||||
->query(sprintf('SELECT doc FROM php_manual WHERE id = %s', $db->quote($id)))
|
||||
->fetchColumn(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
96
vendor/psy/psysh/src/Psy/Command/DumpCommand.php
vendored
Normal file
96
vendor/psy/psysh/src/Psy/Command/DumpCommand.php
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command;
|
||||
|
||||
use Psy\Exception\RuntimeException;
|
||||
use Psy\Presenter\Presenter;
|
||||
use Psy\Presenter\PresenterManager;
|
||||
use Psy\Presenter\PresenterManagerAware;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Dump an object or primitive.
|
||||
*
|
||||
* This is like var_dump but *way* awesomer.
|
||||
*/
|
||||
class DumpCommand extends ReflectingCommand implements PresenterManagerAware
|
||||
{
|
||||
private $presenterManager;
|
||||
|
||||
/**
|
||||
* PresenterManagerAware interface.
|
||||
*
|
||||
* @param PresenterManager $manager
|
||||
*/
|
||||
public function setPresenterManager(PresenterManager $manager)
|
||||
{
|
||||
$this->presenterManager = $manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('dump')
|
||||
->setDefinition(array(
|
||||
new InputArgument('target', InputArgument::REQUIRED, 'A target object or primitive to dump.', null),
|
||||
new InputOption('depth', '', InputOption::VALUE_REQUIRED, 'Depth to parse', 10),
|
||||
new InputOption('all', 'a', InputOption::VALUE_NONE, 'Include private and protected methods and properties.'),
|
||||
))
|
||||
->setDescription('Dump an object or primitive.')
|
||||
->setHelp(
|
||||
<<<HELP
|
||||
Dump an object or primitive.
|
||||
|
||||
This is like var_dump but <strong>way</strong> awesomer.
|
||||
|
||||
e.g.
|
||||
<return>>>> dump \$_</return>
|
||||
<return>>>> dump \$someVar</return>
|
||||
HELP
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$depth = $input->getOption('depth');
|
||||
$target = $this->resolveTarget($input->getArgument('target'));
|
||||
$output->page($this->presenterManager->present($target, $depth, $input->getOption('all') ? Presenter::VERBOSE : 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve dump target name.
|
||||
*
|
||||
* @throws RuntimeException if target name does not exist in the current scope.
|
||||
*
|
||||
* @param string $target
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function resolveTarget($target)
|
||||
{
|
||||
$matches = array();
|
||||
if (preg_match(self::INSTANCE, $target, $matches)) {
|
||||
return $this->getScopeVariable($matches[1]);
|
||||
} else {
|
||||
throw new RuntimeException('Unknown target: ' . $target);
|
||||
}
|
||||
}
|
||||
}
|
||||
52
vendor/psy/psysh/src/Psy/Command/ExitCommand.php
vendored
Normal file
52
vendor/psy/psysh/src/Psy/Command/ExitCommand.php
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command;
|
||||
|
||||
use Psy\Exception\BreakException;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Exit the Psy Shell.
|
||||
*
|
||||
* Just what it says on the tin.
|
||||
*/
|
||||
class ExitCommand extends Command
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('exit')
|
||||
->setAliases(array('quit', 'q'))
|
||||
->setDefinition(array())
|
||||
->setDescription('End the current session and return to caller.')
|
||||
->setHelp(
|
||||
<<<HELP
|
||||
End the current session and return to caller.
|
||||
|
||||
e.g.
|
||||
<return>>>> exit</return>
|
||||
HELP
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
throw new BreakException('Goodbye.');
|
||||
}
|
||||
}
|
||||
98
vendor/psy/psysh/src/Psy/Command/HelpCommand.php
vendored
Normal file
98
vendor/psy/psysh/src/Psy/Command/HelpCommand.php
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command;
|
||||
|
||||
use Symfony\Component\Console\Helper\TableHelper;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Help command.
|
||||
*
|
||||
* Lists available commands, and gives command-specific help when asked nicely.
|
||||
*/
|
||||
class HelpCommand extends Command
|
||||
{
|
||||
private $command;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('help')
|
||||
->setAliases(array('?'))
|
||||
->setDefinition(array(
|
||||
new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', null),
|
||||
))
|
||||
->setDescription('Show a list of commands. Type `help [foo]` for information about [foo].')
|
||||
->setHelp('My. How meta.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for setting a subcommand to retrieve help for.
|
||||
*
|
||||
* @param Command $command
|
||||
*/
|
||||
public function setCommand($command)
|
||||
{
|
||||
$this->command = $command;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
if ($this->command !== null) {
|
||||
// help for an individual command
|
||||
$output->page($this->command->asText());
|
||||
$this->command = null;
|
||||
} elseif ($name = $input->getArgument('command_name')) {
|
||||
// help for an individual command
|
||||
$output->page($this->getApplication()->get($name)->asText());
|
||||
} else {
|
||||
// list available commands
|
||||
$commands = $this->getApplication()->all();
|
||||
|
||||
$table = $this->getTable($output);
|
||||
|
||||
foreach ($commands as $name => $command) {
|
||||
if ($name !== $command->getName()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($command->getAliases()) {
|
||||
$aliases = sprintf('<comment>Aliases:</comment> %s', implode(', ', $command->getAliases()));
|
||||
} else {
|
||||
$aliases = '';
|
||||
}
|
||||
|
||||
$table->addRow(array(
|
||||
sprintf('<info>%s</info>', $name),
|
||||
$command->getDescription(),
|
||||
$aliases,
|
||||
));
|
||||
}
|
||||
|
||||
$output->startPaging();
|
||||
if ($table instanceof TableHelper) {
|
||||
$table->render($output);
|
||||
} else {
|
||||
$table->render();
|
||||
}
|
||||
$output->stopPaging();
|
||||
}
|
||||
}
|
||||
}
|
||||
260
vendor/psy/psysh/src/Psy/Command/HistoryCommand.php
vendored
Normal file
260
vendor/psy/psysh/src/Psy/Command/HistoryCommand.php
vendored
Normal file
@@ -0,0 +1,260 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command;
|
||||
|
||||
use Psy\Output\ShellOutput;
|
||||
use Psy\Readline\Readline;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatter;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Psy Shell history command.
|
||||
*
|
||||
* Shows, searches and replays readline history. Not too shabby.
|
||||
*/
|
||||
class HistoryCommand extends Command
|
||||
{
|
||||
/**
|
||||
* Set the Shell's Readline service.
|
||||
*
|
||||
* @param Readline $readline
|
||||
*/
|
||||
public function setReadline(Readline $readline)
|
||||
{
|
||||
$this->readline = $readline;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('history')
|
||||
->setAliases(array('hist'))
|
||||
->setDefinition(array(
|
||||
new InputOption('show', 's', InputOption::VALUE_REQUIRED, 'Show the given range of lines'),
|
||||
new InputOption('head', 'H', InputOption::VALUE_REQUIRED, 'Display the first N items.'),
|
||||
new InputOption('tail', 'T', InputOption::VALUE_REQUIRED, 'Display the last N items.'),
|
||||
|
||||
new InputOption('grep', 'G', InputOption::VALUE_REQUIRED, 'Show lines matching the given pattern (string or regex).'),
|
||||
new InputOption('insensitive', 'i', InputOption::VALUE_NONE, 'Case insensitive search (requires --grep).'),
|
||||
new InputOption('invert', 'v', InputOption::VALUE_NONE, 'Inverted search (requires --grep).'),
|
||||
|
||||
new InputOption('no-numbers', 'N', InputOption::VALUE_NONE, 'Omit line numbers.'),
|
||||
|
||||
new InputOption('save', '', InputOption::VALUE_REQUIRED, 'Save history to a file.'),
|
||||
new InputOption('replay', '', InputOption::VALUE_NONE, 'Replay'),
|
||||
new InputOption('clear', '', InputOption::VALUE_NONE, 'Clear the history.'),
|
||||
))
|
||||
->setDescription('Show the Psy Shell history.')
|
||||
->setHelp(
|
||||
<<<HELP
|
||||
Show, search, save or replay the Psy Shell history.
|
||||
|
||||
e.g.
|
||||
<return>>>> history --grep /[bB]acon/</return>
|
||||
<return>>>> history --show 0..10 --replay</return>
|
||||
<return>>>> history --clear</return>
|
||||
<return>>>> history --tail 1000 --save somefile.txt</return>
|
||||
HELP
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$this->validateOnlyOne($input, array('show', 'head', 'tail'));
|
||||
$this->validateOnlyOne($input, array('save', 'replay', 'clear'));
|
||||
|
||||
$history = $this->getHistorySlice(
|
||||
$input->getOption('show'),
|
||||
$input->getOption('head'),
|
||||
$input->getOption('tail')
|
||||
);
|
||||
$highlighted = false;
|
||||
|
||||
$invert = $input->getOption('invert');
|
||||
$insensitive = $input->getOption('insensitive');
|
||||
if ($pattern = $input->getOption('grep')) {
|
||||
if (substr($pattern, 0, 1) !== '/' || substr($pattern, -1) !== '/' || strlen($pattern) < 3) {
|
||||
$pattern = '/' . preg_quote($pattern, '/') . '/';
|
||||
}
|
||||
|
||||
if ($insensitive) {
|
||||
$pattern .= 'i';
|
||||
}
|
||||
|
||||
$this->validateRegex($pattern);
|
||||
|
||||
$matches = array();
|
||||
$highlighted = array();
|
||||
foreach ($history as $i => $line) {
|
||||
if (preg_match($pattern, $line, $matches) xor $invert) {
|
||||
if (!$invert) {
|
||||
$chunks = explode($matches[0], $history[$i]);
|
||||
$chunks = array_map(array(__CLASS__, 'escape'), $chunks);
|
||||
$glue = sprintf('<urgent>%s</urgent>', self::escape($matches[0]));
|
||||
|
||||
$highlighted[$i] = implode($glue, $chunks);
|
||||
}
|
||||
} else {
|
||||
unset($history[$i]);
|
||||
}
|
||||
}
|
||||
} elseif ($invert) {
|
||||
throw new \InvalidArgumentException('Cannot use -v without --grep.');
|
||||
} elseif ($insensitive) {
|
||||
throw new \InvalidArgumentException('Cannot use -i without --grep.');
|
||||
}
|
||||
|
||||
if ($save = $input->getOption('save')) {
|
||||
$output->writeln(sprintf('Saving history in %s...', $save));
|
||||
file_put_contents($save, implode(PHP_EOL, $history) . PHP_EOL);
|
||||
$output->writeln('<info>History saved.</info>');
|
||||
} elseif ($input->getOption('replay')) {
|
||||
if (!($input->getOption('show') || $input->getOption('head') || $input->getOption('tail'))) {
|
||||
throw new \InvalidArgumentException('You must limit history via --head, --tail or --show before replaying.');
|
||||
}
|
||||
|
||||
$count = count($history);
|
||||
$output->writeln(sprintf('Replaying %d line%s of history', $count, ($count !== 1) ? 's' : ''));
|
||||
$this->getApplication()->addInput($history);
|
||||
} elseif ($input->getOption('clear')) {
|
||||
$this->clearHistory();
|
||||
$output->writeln('<info>History cleared.</info>');
|
||||
} else {
|
||||
$type = $input->getOption('no-numbers') ? 0 : ShellOutput::NUMBER_LINES;
|
||||
if (!$highlighted) {
|
||||
$type = $type | ShellOutput::OUTPUT_RAW;
|
||||
}
|
||||
|
||||
$output->page($highlighted ?: $history, $type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a range from a string.
|
||||
*
|
||||
* @param string $range
|
||||
*
|
||||
* @return array [ start, end ]
|
||||
*/
|
||||
private function extractRange($range)
|
||||
{
|
||||
if (preg_match('/^\d+$/', $range)) {
|
||||
return array($range, $range + 1);
|
||||
}
|
||||
|
||||
$matches = array();
|
||||
if ($range !== '..' && preg_match('/^(\d*)\.\.(\d*)$/', $range, $matches)) {
|
||||
$start = $matches[1] ? intval($matches[1]) : 0;
|
||||
$end = $matches[2] ? intval($matches[2]) + 1 : PHP_INT_MAX;
|
||||
|
||||
return array($start, $end);
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException('Unexpected range: ' . $range);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a slice of the readline history.
|
||||
*
|
||||
* @param string $show
|
||||
* @param string $head
|
||||
* @param string $tail
|
||||
*
|
||||
* @return array A slilce of history.
|
||||
*/
|
||||
private function getHistorySlice($show, $head, $tail)
|
||||
{
|
||||
$history = $this->readline->listHistory();
|
||||
|
||||
if ($show) {
|
||||
list($start, $end) = $this->extractRange($show);
|
||||
$length = $end - $start;
|
||||
} elseif ($head) {
|
||||
if (!preg_match('/^\d+$/', $head)) {
|
||||
throw new \InvalidArgumentException('Please specify an integer argument for --head.');
|
||||
}
|
||||
|
||||
$start = 0;
|
||||
$length = intval($head);
|
||||
} elseif ($tail) {
|
||||
if (!preg_match('/^\d+$/', $tail)) {
|
||||
throw new \InvalidArgumentException('Please specify an integer argument for --tail.');
|
||||
}
|
||||
|
||||
$start = count($history) - $tail;
|
||||
$length = intval($tail) + 1;
|
||||
} else {
|
||||
return $history;
|
||||
}
|
||||
|
||||
return array_slice($history, $start, $length, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that $pattern is a valid regular expression.
|
||||
*
|
||||
* @param string $pattern
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function validateRegex($pattern)
|
||||
{
|
||||
set_error_handler(array('Psy\Exception\ErrorException', 'throwException'));
|
||||
try {
|
||||
preg_match($pattern, '');
|
||||
} catch (ErrorException $e) {
|
||||
throw new RuntimeException(str_replace('preg_match(): ', 'Invalid regular expression: ', $e->getRawMessage()));
|
||||
}
|
||||
restore_error_handler();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that only one of the given $options is set.
|
||||
*
|
||||
* @param InputInterface $input
|
||||
* @param array $options
|
||||
*/
|
||||
private function validateOnlyOne(InputInterface $input, array $options)
|
||||
{
|
||||
$count = 0;
|
||||
foreach ($options as $opt) {
|
||||
if ($input->getOption($opt)) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($count > 1) {
|
||||
throw new \InvalidArgumentException('Please specify only one of --' . implode(', --', $options));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the readline history.
|
||||
*/
|
||||
private function clearHistory()
|
||||
{
|
||||
$this->readline->clearHistory();
|
||||
}
|
||||
|
||||
public static function escape($string)
|
||||
{
|
||||
return OutputFormatter::escape($string);
|
||||
}
|
||||
}
|
||||
278
vendor/psy/psysh/src/Psy/Command/ListCommand.php
vendored
Normal file
278
vendor/psy/psysh/src/Psy/Command/ListCommand.php
vendored
Normal file
@@ -0,0 +1,278 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command;
|
||||
|
||||
use Psy\Command\ListCommand\ClassConstantEnumerator;
|
||||
use Psy\Command\ListCommand\ClassEnumerator;
|
||||
use Psy\Command\ListCommand\ConstantEnumerator;
|
||||
use Psy\Command\ListCommand\FunctionEnumerator;
|
||||
use Psy\Command\ListCommand\GlobalVariableEnumerator;
|
||||
use Psy\Command\ListCommand\InterfaceEnumerator;
|
||||
use Psy\Command\ListCommand\MethodEnumerator;
|
||||
use Psy\Command\ListCommand\PropertyEnumerator;
|
||||
use Psy\Command\ListCommand\TraitEnumerator;
|
||||
use Psy\Command\ListCommand\VariableEnumerator;
|
||||
use Psy\Exception\RuntimeException;
|
||||
use Psy\Presenter\PresenterManager;
|
||||
use Psy\Presenter\PresenterManagerAware;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatter;
|
||||
use Symfony\Component\Console\Helper\TableHelper;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* List available local variables, object properties, etc.
|
||||
*/
|
||||
class ListCommand extends ReflectingCommand implements PresenterManagerAware
|
||||
{
|
||||
protected $presenterManager;
|
||||
protected $enumerators;
|
||||
|
||||
/**
|
||||
* PresenterManagerAware interface.
|
||||
*
|
||||
* @param PresenterManager $manager
|
||||
*/
|
||||
public function setPresenterManager(PresenterManager $manager)
|
||||
{
|
||||
$this->presenterManager = $manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('ls')
|
||||
->setAliases(array('list', 'dir'))
|
||||
->setDefinition(array(
|
||||
new InputArgument('target', InputArgument::OPTIONAL, 'A target class or object to list.', null),
|
||||
|
||||
new InputOption('vars', '', InputOption::VALUE_NONE, 'Display variables.'),
|
||||
new InputOption('constants', 'c', InputOption::VALUE_NONE, 'Display defined constants.'),
|
||||
new InputOption('functions', 'f', InputOption::VALUE_NONE, 'Display defined functions.'),
|
||||
new InputOption('classes', 'k', InputOption::VALUE_NONE, 'Display declared classes.'),
|
||||
new InputOption('interfaces', 'I', InputOption::VALUE_NONE, 'Display declared interfaces.'),
|
||||
new InputOption('traits', 't', InputOption::VALUE_NONE, 'Display declared traits.'),
|
||||
|
||||
new InputOption('properties', 'p', InputOption::VALUE_NONE, 'Display class or object properties (public properties by default).'),
|
||||
new InputOption('methods', 'm', InputOption::VALUE_NONE, 'Display class or object methods (public methods by default).'),
|
||||
|
||||
new InputOption('grep', 'G', InputOption::VALUE_REQUIRED, 'Limit to items matching the given pattern (string or regex).'),
|
||||
new InputOption('insensitive', 'i', InputOption::VALUE_NONE, 'Case-insensitive search (requires --grep).'),
|
||||
new InputOption('invert', 'v', InputOption::VALUE_NONE, 'Inverted search (requires --grep).'),
|
||||
|
||||
new InputOption('globals', 'g', InputOption::VALUE_NONE, 'Include global variables.'),
|
||||
new InputOption('internal', 'n', InputOption::VALUE_NONE, 'Limit to internal functions and classes.'),
|
||||
new InputOption('user', 'u', InputOption::VALUE_NONE, 'Limit to user-defined constants, functions and classes.'),
|
||||
new InputOption('category', 'C', InputOption::VALUE_REQUIRED, 'Limit to constants in a specific category (e.g. "date").'),
|
||||
|
||||
new InputOption('all', 'a', InputOption::VALUE_NONE, 'Include private and protected methods and properties.'),
|
||||
new InputOption('long', 'l', InputOption::VALUE_NONE, 'List in long format: includes class names and method signatures.'),
|
||||
))
|
||||
->setDescription('List local, instance or class variables, methods and constants.')
|
||||
->setHelp(
|
||||
<<<HELP
|
||||
List variables, constants, classes, interfaces, traits, functions, methods,
|
||||
and properties.
|
||||
|
||||
Called without options, this will return a list of variables currently in scope.
|
||||
|
||||
If a target object is provided, list properties, constants and methods of that
|
||||
target. If a class, interface or trait name is passed instead, list constants
|
||||
and methods on that class.
|
||||
|
||||
e.g.
|
||||
<return>>>> ls</return>
|
||||
<return>>>> ls \$foo</return>
|
||||
<return>>>> ls -k --grep mongo -i</return>
|
||||
<return>>>> ls -al ReflectionClass</return>
|
||||
<return>>>> ls --constants --category date</return>
|
||||
<return>>>> ls -l --functions --grep /^array_.*/</return>
|
||||
HELP
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$this->validateInput($input);
|
||||
$this->initEnumerators();
|
||||
|
||||
$method = $input->getOption('long') ? 'writeLong' : 'write';
|
||||
|
||||
if ($target = $input->getArgument('target')) {
|
||||
list($target, $reflector) = $this->getTargetAndReflector($target, true);
|
||||
} else {
|
||||
$reflector = null;
|
||||
}
|
||||
|
||||
// TODO: something cleaner than this :-/
|
||||
if ($input->getOption('long')) {
|
||||
$output->startPaging();
|
||||
}
|
||||
|
||||
foreach ($this->enumerators as $enumerator) {
|
||||
$this->$method($output, $enumerator->enumerate($input, $reflector, $target));
|
||||
}
|
||||
|
||||
if ($input->getOption('long')) {
|
||||
$output->stopPaging();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Enumerators.
|
||||
*/
|
||||
protected function initEnumerators()
|
||||
{
|
||||
if (!isset($this->enumerators)) {
|
||||
$mgr = $this->presenterManager;
|
||||
|
||||
$this->enumerators = array(
|
||||
new ClassConstantEnumerator($mgr),
|
||||
new ClassEnumerator($mgr),
|
||||
new ConstantEnumerator($mgr),
|
||||
new FunctionEnumerator($mgr),
|
||||
new GlobalVariableEnumerator($mgr),
|
||||
new InterfaceEnumerator($mgr),
|
||||
new PropertyEnumerator($mgr),
|
||||
new MethodEnumerator($mgr),
|
||||
new TraitEnumerator($mgr),
|
||||
new VariableEnumerator($mgr, $this->context),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the list items to $output.
|
||||
*
|
||||
* @param OutputInterface $output
|
||||
* @param null|array $result List of enumerated items.
|
||||
*/
|
||||
protected function write(OutputInterface $output, array $result = null)
|
||||
{
|
||||
if ($result === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($result as $label => $items) {
|
||||
$names = array_map(array($this, 'formatItemName'), $items);
|
||||
$output->writeln(sprintf('<strong>%s</strong>: %s', $label, implode(', ', $names)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the list items to $output.
|
||||
*
|
||||
* Items are listed one per line, and include the item signature.
|
||||
*
|
||||
* @param OutputInterface $output
|
||||
* @param null|array $result List of enumerated items.
|
||||
*/
|
||||
protected function writeLong(OutputInterface $output, array $result = null)
|
||||
{
|
||||
if ($result === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$table = $this->getTable($output);
|
||||
|
||||
foreach ($result as $label => $items) {
|
||||
$output->writeln('');
|
||||
$output->writeln(sprintf('<strong>%s:</strong>', $label));
|
||||
|
||||
$table->setRows(array());
|
||||
foreach ($items as $item) {
|
||||
$table->addRow(array($this->formatItemName($item), $item['value']));
|
||||
}
|
||||
|
||||
if ($table instanceof TableHelper) {
|
||||
$table->render($output);
|
||||
} else {
|
||||
$table->render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format an item name given its visibility.
|
||||
*
|
||||
* @param array $item
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function formatItemName($item)
|
||||
{
|
||||
return sprintf('<%s>%s</%s>', $item['style'], OutputFormatter::escape($item['name']), $item['style']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that input options make sense, provide defaults when called without options.
|
||||
*
|
||||
* @throws RuntimeException if options are inconsistent.
|
||||
*
|
||||
* @param InputInterface $input
|
||||
*/
|
||||
private function validateInput(InputInterface $input)
|
||||
{
|
||||
// grep, invert and insensitive
|
||||
if (!$input->getOption('grep')) {
|
||||
foreach (array('invert', 'insensitive') as $option) {
|
||||
if ($input->getOption($option)) {
|
||||
throw new RuntimeException('--' . $option . ' does not make sense without --grep');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$input->getArgument('target')) {
|
||||
// if no target is passed, there can be no properties or methods
|
||||
foreach (array('properties', 'methods') as $option) {
|
||||
if ($input->getOption($option)) {
|
||||
throw new RuntimeException('--' . $option . ' does not make sense without a specified target.');
|
||||
}
|
||||
}
|
||||
|
||||
foreach (array('globals', 'vars', 'constants', 'functions', 'classes', 'interfaces', 'traits') as $option) {
|
||||
if ($input->getOption($option)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// default to --vars if no other options are passed
|
||||
$input->setOption('vars', true);
|
||||
} else {
|
||||
// if a target is passed, classes, functions, etc don't make sense
|
||||
foreach (array('vars', 'globals', 'functions', 'classes', 'interfaces', 'traits') as $option) {
|
||||
if ($input->getOption($option)) {
|
||||
throw new RuntimeException('--' . $option . ' does not make sense with a specified target.');
|
||||
}
|
||||
}
|
||||
|
||||
foreach (array('constants', 'properties', 'methods') as $option) {
|
||||
if ($input->getOption($option)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// default to --constants --properties --methods if no other options are passed
|
||||
$input->setOption('constants', true);
|
||||
$input->setOption('properties', true);
|
||||
$input->setOption('methods', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
118
vendor/psy/psysh/src/Psy/Command/ListCommand/ClassConstantEnumerator.php
vendored
Normal file
118
vendor/psy/psysh/src/Psy/Command/ListCommand/ClassConstantEnumerator.php
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command\ListCommand;
|
||||
|
||||
use Psy\Reflection\ReflectionConstant;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
|
||||
/**
|
||||
* Class Constant Enumerator class.
|
||||
*/
|
||||
class ClassConstantEnumerator extends Enumerator
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function listItems(InputInterface $input, \Reflector $reflector = null, $target = null)
|
||||
{
|
||||
// only list constants when a Reflector is present.
|
||||
|
||||
if ($reflector === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We can only list constants on actual class (or object) reflectors.
|
||||
if (!$reflector instanceof \ReflectionClass) {
|
||||
// TODO: handle ReflectionExtension as well
|
||||
return;
|
||||
}
|
||||
|
||||
// only list constants if we are specifically asked
|
||||
if (!$input->getOption('constants')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$constants = $this->prepareConstants($this->getConstants($reflector));
|
||||
|
||||
if (empty($constants)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ret = array();
|
||||
$ret[$this->getKindLabel($reflector)] = $constants;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get defined constants for the given class or object Reflector.
|
||||
*
|
||||
* @param \Reflector $reflector
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getConstants(\Reflector $reflector)
|
||||
{
|
||||
$constants = array();
|
||||
foreach ($reflector->getConstants() as $name => $constant) {
|
||||
$constants[$name] = new ReflectionConstant($reflector, $name);
|
||||
}
|
||||
|
||||
// TODO: this should be natcasesort
|
||||
ksort($constants);
|
||||
|
||||
return $constants;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare formatted constant array.
|
||||
*
|
||||
* @param array $constants
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function prepareConstants(array $constants)
|
||||
{
|
||||
// My kingdom for a generator.
|
||||
$ret = array();
|
||||
|
||||
foreach ($constants as $name => $constant) {
|
||||
if ($this->showItem($name)) {
|
||||
$ret[$name] = array(
|
||||
'name' => $name,
|
||||
'style' => self::IS_CONSTANT,
|
||||
'value' => $this->presentRef($constant->getValue()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a label for the particular kind of "class" represented.
|
||||
*
|
||||
* @param \ReflectionClass $reflector
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getKindLabel(\ReflectionClass $reflector)
|
||||
{
|
||||
if ($reflector->isInterface()) {
|
||||
return 'Interface Constants';
|
||||
} elseif (method_exists($reflector, 'isTrait') && $reflector->isTrait()) {
|
||||
return 'Trait Constants';
|
||||
} else {
|
||||
return 'Class Constants';
|
||||
}
|
||||
}
|
||||
}
|
||||
80
vendor/psy/psysh/src/Psy/Command/ListCommand/ClassEnumerator.php
vendored
Normal file
80
vendor/psy/psysh/src/Psy/Command/ListCommand/ClassEnumerator.php
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command\ListCommand;
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
|
||||
/**
|
||||
* Class Enumerator class.
|
||||
*/
|
||||
class ClassEnumerator extends Enumerator
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function listItems(InputInterface $input, \Reflector $reflector = null, $target = null)
|
||||
{
|
||||
// only list classes when no Reflector is present.
|
||||
//
|
||||
// TODO: make a NamespaceReflector and pass that in for commands like:
|
||||
//
|
||||
// ls --classes Foo
|
||||
//
|
||||
// ... for listing classes in the Foo namespace
|
||||
|
||||
if ($reflector !== null || $target !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// only list classes if we are specifically asked
|
||||
if (!$input->getOption('classes')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$classes = $this->prepareClasses(get_declared_classes());
|
||||
|
||||
if (empty($classes)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return array(
|
||||
'Classes' => $classes,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare formatted class array.
|
||||
*
|
||||
* @param array $class
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function prepareClasses(array $classes)
|
||||
{
|
||||
natcasesort($classes);
|
||||
|
||||
// My kingdom for a generator.
|
||||
$ret = array();
|
||||
|
||||
foreach ($classes as $name) {
|
||||
if ($this->showItem($name)) {
|
||||
$ret[$name] = array(
|
||||
'name' => $name,
|
||||
'style' => self::IS_CLASS,
|
||||
'value' => $this->presentSignature($name),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
103
vendor/psy/psysh/src/Psy/Command/ListCommand/ConstantEnumerator.php
vendored
Normal file
103
vendor/psy/psysh/src/Psy/Command/ListCommand/ConstantEnumerator.php
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command\ListCommand;
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
|
||||
/**
|
||||
* Constant Enumerator class.
|
||||
*/
|
||||
class ConstantEnumerator extends Enumerator
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function listItems(InputInterface $input, \Reflector $reflector = null, $target = null)
|
||||
{
|
||||
// only list constants when no Reflector is present.
|
||||
//
|
||||
// TODO: make a NamespaceReflector and pass that in for commands like:
|
||||
//
|
||||
// ls --constants Foo
|
||||
//
|
||||
// ... for listing constants in the Foo namespace
|
||||
if ($reflector !== null || $target !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// only list constants if we are specifically asked
|
||||
if (!$input->getOption('constants')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$category = $input->getOption('user') ? 'user' : $input->getOption('category');
|
||||
$label = $category ? ucfirst($category) . ' Constants' : 'Constants';
|
||||
$constants = $this->prepareConstants($this->getConstants($category));
|
||||
|
||||
if (empty($constants)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ret = array();
|
||||
$ret[$label] = $constants;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get defined constants.
|
||||
*
|
||||
* Optionally restrict constants to a given category, e.g. "date".
|
||||
*
|
||||
* @param string $category
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getConstants($category = null)
|
||||
{
|
||||
if (!$category) {
|
||||
return get_defined_constants();
|
||||
}
|
||||
|
||||
$consts = get_defined_constants(true);
|
||||
|
||||
return isset($consts[$category]) ? $consts[$category] : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare formatted constant array.
|
||||
*
|
||||
* @param array $constants
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function prepareConstants(array $constants)
|
||||
{
|
||||
// My kingdom for a generator.
|
||||
$ret = array();
|
||||
|
||||
$names = array_keys($constants);
|
||||
natcasesort($names);
|
||||
|
||||
foreach ($names as $name) {
|
||||
if ($this->showItem($name)) {
|
||||
$ret[$name] = array(
|
||||
'name' => $name,
|
||||
'style' => self::IS_CONSTANT,
|
||||
'value' => $this->presentRef($constants[$name]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
146
vendor/psy/psysh/src/Psy/Command/ListCommand/Enumerator.php
vendored
Normal file
146
vendor/psy/psysh/src/Psy/Command/ListCommand/Enumerator.php
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command\ListCommand;
|
||||
|
||||
use Psy\Formatter\SignatureFormatter;
|
||||
use Psy\Presenter\PresenterManager;
|
||||
use Psy\Util\Mirror;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
|
||||
/**
|
||||
* Abstract Enumerator class.
|
||||
*/
|
||||
abstract class Enumerator
|
||||
{
|
||||
// Output styles
|
||||
const IS_PUBLIC = 'public';
|
||||
const IS_PROTECTED = 'protected';
|
||||
const IS_PRIVATE = 'private';
|
||||
const IS_GLOBAL = 'global';
|
||||
const IS_CONSTANT = 'const';
|
||||
const IS_CLASS = 'class';
|
||||
const IS_FUNCTION = 'function';
|
||||
|
||||
private $presenterManager;
|
||||
|
||||
private $filter = false;
|
||||
private $invertFilter = false;
|
||||
private $pattern;
|
||||
|
||||
/**
|
||||
* Enumerator constructor.
|
||||
*
|
||||
* @param PresenterManager $presenterManager
|
||||
*/
|
||||
public function __construct(PresenterManager $presenterManager)
|
||||
{
|
||||
$this->presenterManager = $presenterManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of categorized things with the given input options and target.
|
||||
*
|
||||
* @param InputInterface $input
|
||||
* @param Reflector $reflector
|
||||
* @param mixed $target
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function enumerate(InputInterface $input, \Reflector $reflector = null, $target = null)
|
||||
{
|
||||
$this->setFilter($input);
|
||||
|
||||
return $this->listItems($input, $reflector, $target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumerate specific items with the given input options and target.
|
||||
*
|
||||
* Implementing classes should return an array of arrays:
|
||||
*
|
||||
* [
|
||||
* 'Constants' => [
|
||||
* 'FOO' => [
|
||||
* 'name' => 'FOO',
|
||||
* 'style' => 'public',
|
||||
* 'value' => '123',
|
||||
* ],
|
||||
* ],
|
||||
* ]
|
||||
*
|
||||
* @param InputInterface $input
|
||||
* @param Reflector $reflector
|
||||
* @param mixed $target
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract protected function listItems(InputInterface $input, \Reflector $reflector = null, $target = null);
|
||||
|
||||
protected function presentRef($value)
|
||||
{
|
||||
return $this->presenterManager->presentRef($value);
|
||||
}
|
||||
|
||||
protected function showItem($name)
|
||||
{
|
||||
return $this->filter === false || (preg_match($this->pattern, $name) xor $this->invertFilter);
|
||||
}
|
||||
|
||||
private function setFilter(InputInterface $input)
|
||||
{
|
||||
if ($pattern = $input->getOption('grep')) {
|
||||
if (substr($pattern, 0, 1) !== '/' || substr($pattern, -1) !== '/' || strlen($pattern) < 3) {
|
||||
$pattern = '/' . preg_quote($pattern, '/') . '/';
|
||||
}
|
||||
|
||||
if ($input->getOption('insensitive')) {
|
||||
$pattern .= 'i';
|
||||
}
|
||||
|
||||
$this->validateRegex($pattern);
|
||||
|
||||
$this->filter = true;
|
||||
$this->pattern = $pattern;
|
||||
$this->invertFilter = $input->getOption('invert');
|
||||
} else {
|
||||
$this->filter = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that $pattern is a valid regular expression.
|
||||
*
|
||||
* @param string $pattern
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function validateRegex($pattern)
|
||||
{
|
||||
set_error_handler(array('Psy\Exception\ErrorException', 'throwException'));
|
||||
try {
|
||||
preg_match($pattern, '');
|
||||
} catch (ErrorException $e) {
|
||||
throw new RuntimeException(str_replace('preg_match(): ', 'Invalid regular expression: ', $e->getRawMessage()));
|
||||
}
|
||||
restore_error_handler();
|
||||
}
|
||||
|
||||
protected function presentSignature($target)
|
||||
{
|
||||
// This might get weird if the signature is actually for a reflector. Hrm.
|
||||
if (!$target instanceof \Reflector) {
|
||||
$target = Mirror::get($target);
|
||||
}
|
||||
|
||||
return SignatureFormatter::format($target);
|
||||
}
|
||||
}
|
||||
112
vendor/psy/psysh/src/Psy/Command/ListCommand/FunctionEnumerator.php
vendored
Normal file
112
vendor/psy/psysh/src/Psy/Command/ListCommand/FunctionEnumerator.php
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command\ListCommand;
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
|
||||
/**
|
||||
* Function Enumerator class.
|
||||
*/
|
||||
class FunctionEnumerator extends Enumerator
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function listItems(InputInterface $input, \Reflector $reflector = null, $target = null)
|
||||
{
|
||||
// only list functions when no Reflector is present.
|
||||
//
|
||||
// TODO: make a NamespaceReflector and pass that in for commands like:
|
||||
//
|
||||
// ls --functions Foo
|
||||
//
|
||||
// ... for listing functions in the Foo namespace
|
||||
|
||||
if ($reflector !== null || $target !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// only list functions if we are specifically asked
|
||||
if (!$input->getOption('functions')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($input->getOption('user')) {
|
||||
$label = 'User Functions';
|
||||
$functions = $this->getFunctions('user');
|
||||
} elseif ($input->getOption('internal')) {
|
||||
$label = 'Internal Functions';
|
||||
$functions = $this->getFunctions('internal');
|
||||
} else {
|
||||
$label = 'Functions';
|
||||
$functions = $this->getFunctions();
|
||||
}
|
||||
|
||||
$functions = $this->prepareFunctions($functions);
|
||||
|
||||
if (empty($functions)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ret = array();
|
||||
$ret[$label] = $functions;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get defined functions.
|
||||
*
|
||||
* Optionally limit functions to "user" or "internal" functions.
|
||||
*
|
||||
* @param null|string $type "user" or "internal" (default: both)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getFunctions($type = null)
|
||||
{
|
||||
$funcs = get_defined_functions();
|
||||
|
||||
if ($type) {
|
||||
return $funcs[$type];
|
||||
} else {
|
||||
return array_merge($funcs['internal'], $funcs['user']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare formatted function array.
|
||||
*
|
||||
* @param array $functions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function prepareFunctions(array $functions)
|
||||
{
|
||||
natcasesort($functions);
|
||||
|
||||
// My kingdom for a generator.
|
||||
$ret = array();
|
||||
|
||||
foreach ($functions as $name) {
|
||||
if ($this->showItem($name)) {
|
||||
$ret[$name] = array(
|
||||
'name' => $name,
|
||||
'style' => self::IS_FUNCTION,
|
||||
'value' => $this->presentSignature($name),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
92
vendor/psy/psysh/src/Psy/Command/ListCommand/GlobalVariableEnumerator.php
vendored
Normal file
92
vendor/psy/psysh/src/Psy/Command/ListCommand/GlobalVariableEnumerator.php
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command\ListCommand;
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
|
||||
/**
|
||||
* Global Variable Enumerator class.
|
||||
*/
|
||||
class GlobalVariableEnumerator extends Enumerator
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function listItems(InputInterface $input, \Reflector $reflector = null, $target = null)
|
||||
{
|
||||
// only list globals when no Reflector is present.
|
||||
if ($reflector !== null || $target !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// only list globals if we are specifically asked
|
||||
if (!$input->getOption('globals')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$globals = $this->prepareGlobals($this->getGlobals());
|
||||
|
||||
if (empty($globals)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return array(
|
||||
'Global Variables' => $globals,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get defined global variables.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getGlobals()
|
||||
{
|
||||
global $GLOBALS;
|
||||
|
||||
$names = array_keys($GLOBALS);
|
||||
natcasesort($names);
|
||||
|
||||
$ret = array();
|
||||
foreach ($names as $name) {
|
||||
$ret[$name] = $GLOBALS[$name];
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare formatted global variable array.
|
||||
*
|
||||
* @param array $globals
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function prepareGlobals($globals)
|
||||
{
|
||||
// My kingdom for a generator.
|
||||
$ret = array();
|
||||
|
||||
foreach ($globals as $name => $value) {
|
||||
if ($this->showItem($name)) {
|
||||
$fname = '$' . $name;
|
||||
$ret[$fname] = array(
|
||||
'name' => $fname,
|
||||
'style' => self::IS_GLOBAL,
|
||||
'value' => $this->presentRef($value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
80
vendor/psy/psysh/src/Psy/Command/ListCommand/InterfaceEnumerator.php
vendored
Normal file
80
vendor/psy/psysh/src/Psy/Command/ListCommand/InterfaceEnumerator.php
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command\ListCommand;
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
|
||||
/**
|
||||
* Interface Enumerator class.
|
||||
*/
|
||||
class InterfaceEnumerator extends Enumerator
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function listItems(InputInterface $input, \Reflector $reflector = null, $target = null)
|
||||
{
|
||||
// only list interfaces when no Reflector is present.
|
||||
//
|
||||
// TODO: make a NamespaceReflector and pass that in for commands like:
|
||||
//
|
||||
// ls --interfaces Foo
|
||||
//
|
||||
// ... for listing interfaces in the Foo namespace
|
||||
|
||||
if ($reflector !== null || $target !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// only list interfaces if we are specifically asked
|
||||
if (!$input->getOption('interfaces')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$interfaces = $this->prepareInterfaces(get_declared_interfaces());
|
||||
|
||||
if (empty($interfaces)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return array(
|
||||
'Interfaces' => $interfaces,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare formatted interface array.
|
||||
*
|
||||
* @param array $interfaces
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function prepareInterfaces(array $interfaces)
|
||||
{
|
||||
natcasesort($interfaces);
|
||||
|
||||
// My kingdom for a generator.
|
||||
$ret = array();
|
||||
|
||||
foreach ($interfaces as $name) {
|
||||
if ($this->showItem($name)) {
|
||||
$ret[$name] = array(
|
||||
'name' => $name,
|
||||
'style' => self::IS_CLASS,
|
||||
'value' => $this->presentSignature($name),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
138
vendor/psy/psysh/src/Psy/Command/ListCommand/MethodEnumerator.php
vendored
Normal file
138
vendor/psy/psysh/src/Psy/Command/ListCommand/MethodEnumerator.php
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command\ListCommand;
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
|
||||
/**
|
||||
* Method Enumerator class.
|
||||
*/
|
||||
class MethodEnumerator extends Enumerator
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function listItems(InputInterface $input, \Reflector $reflector = null, $target = null)
|
||||
{
|
||||
// only list methods when a Reflector is present.
|
||||
|
||||
if ($reflector === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We can only list methods on actual class (or object) reflectors.
|
||||
if (!$reflector instanceof \ReflectionClass) {
|
||||
return;
|
||||
}
|
||||
|
||||
// only list methods if we are specifically asked
|
||||
if (!$input->getOption('methods')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$showAll = $input->getOption('all');
|
||||
$methods = $this->prepareMethods($this->getMethods($showAll, $reflector));
|
||||
|
||||
if (empty($methods)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ret = array();
|
||||
$ret[$this->getKindLabel($reflector)] = $methods;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get defined methods for the given class or object Reflector.
|
||||
*
|
||||
* @param boolean $showAll Include private and protected methods.
|
||||
* @param \Reflector $reflector
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getMethods($showAll, \Reflector $reflector)
|
||||
{
|
||||
$methods = array();
|
||||
foreach ($reflector->getMethods() as $name => $method) {
|
||||
if ($showAll || $method->isPublic()) {
|
||||
$methods[$method->getName()] = $method;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: this should be natcasesort
|
||||
ksort($methods);
|
||||
|
||||
return $methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare formatted method array.
|
||||
*
|
||||
* @param array $methods
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function prepareMethods(array $methods)
|
||||
{
|
||||
// My kingdom for a generator.
|
||||
$ret = array();
|
||||
|
||||
foreach ($methods as $name => $method) {
|
||||
if ($this->showItem($name)) {
|
||||
$ret[$name] = array(
|
||||
'name' => $name,
|
||||
'style' => $this->getVisibilityStyle($method),
|
||||
'value' => $this->presentSignature($method),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a label for the particular kind of "class" represented.
|
||||
*
|
||||
* @param \ReflectionClass $reflector
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getKindLabel(\ReflectionClass $reflector)
|
||||
{
|
||||
if ($reflector->isInterface()) {
|
||||
return 'Interface Methods';
|
||||
} elseif (method_exists($reflector, 'isTrait') && $reflector->isTrait()) {
|
||||
return 'Trait Methods';
|
||||
} else {
|
||||
return 'Class Methods';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get output style for the given method's visibility.
|
||||
*
|
||||
* @param \ReflectionMethod $method
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getVisibilityStyle(\ReflectionMethod $method)
|
||||
{
|
||||
if ($method->isPublic()) {
|
||||
return self::IS_PUBLIC;
|
||||
} elseif ($method->isProtected()) {
|
||||
return self::IS_PROTECTED;
|
||||
} else {
|
||||
return self::IS_PRIVATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
161
vendor/psy/psysh/src/Psy/Command/ListCommand/PropertyEnumerator.php
vendored
Normal file
161
vendor/psy/psysh/src/Psy/Command/ListCommand/PropertyEnumerator.php
vendored
Normal file
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command\ListCommand;
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
|
||||
/**
|
||||
* Property Enumerator class.
|
||||
*/
|
||||
class PropertyEnumerator extends Enumerator
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function listItems(InputInterface $input, \Reflector $reflector = null, $target = null)
|
||||
{
|
||||
// only list properties when a Reflector is present.
|
||||
|
||||
if ($reflector === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We can only list properties on actual class (or object) reflectors.
|
||||
if (!$reflector instanceof \ReflectionClass) {
|
||||
return;
|
||||
}
|
||||
|
||||
// only list properties if we are specifically asked
|
||||
if (!$input->getOption('properties')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$showAll = $input->getOption('all');
|
||||
$properties = $this->prepareProperties($this->getProperties($showAll, $reflector), $target);
|
||||
|
||||
if (empty($properties)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ret = array();
|
||||
$ret[$this->getKindLabel($reflector)] = $properties;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get defined properties for the given class or object Reflector.
|
||||
*
|
||||
* @param boolean $showAll Include private and protected properties.
|
||||
* @param \Reflector $reflector
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getProperties($showAll, \Reflector $reflector)
|
||||
{
|
||||
$properties = array();
|
||||
foreach ($reflector->getProperties() as $property) {
|
||||
if ($showAll || $property->isPublic()) {
|
||||
$properties[$property->getName()] = $property;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: this should be natcasesort
|
||||
ksort($properties);
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare formatted property array.
|
||||
*
|
||||
* @param array $properties
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function prepareProperties(array $properties, $target = null)
|
||||
{
|
||||
// My kingdom for a generator.
|
||||
$ret = array();
|
||||
|
||||
foreach ($properties as $name => $property) {
|
||||
if ($this->showItem($name)) {
|
||||
$fname = '$' . $name;
|
||||
$ret[$fname] = array(
|
||||
'name' => $fname,
|
||||
'style' => $this->getVisibilityStyle($property),
|
||||
'value' => $this->presentValue($property, $target),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a label for the particular kind of "class" represented.
|
||||
*
|
||||
* @param \ReflectionClass $reflector
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getKindLabel(\ReflectionClass $reflector)
|
||||
{
|
||||
if ($reflector->isInterface()) {
|
||||
return 'Interface Properties';
|
||||
} elseif (method_exists($reflector, 'isTrait') && $reflector->isTrait()) {
|
||||
return 'Trait Properties';
|
||||
} else {
|
||||
return 'Class Properties';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get output style for the given property's visibility.
|
||||
*
|
||||
* @param \ReflectionProperty $property
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getVisibilityStyle(\ReflectionProperty $property)
|
||||
{
|
||||
if ($property->isPublic()) {
|
||||
return self::IS_PUBLIC;
|
||||
} elseif ($property->isProtected()) {
|
||||
return self::IS_PROTECTED;
|
||||
} else {
|
||||
return self::IS_PRIVATE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Present the $target's current value for a reflection property.
|
||||
*
|
||||
* @param \ReflectionProperty $property
|
||||
* @param mixed $target
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function presentValue(\ReflectionProperty $property, $target)
|
||||
{
|
||||
if (!is_object($target)) {
|
||||
// TODO: figure out if there's a way to return defaults when target
|
||||
// is a class/interface/trait rather than an object.
|
||||
return '';
|
||||
}
|
||||
|
||||
$property->setAccessible(true);
|
||||
$value = $property->getValue($target);
|
||||
|
||||
return $this->presentRef($value);
|
||||
}
|
||||
}
|
||||
85
vendor/psy/psysh/src/Psy/Command/ListCommand/TraitEnumerator.php
vendored
Normal file
85
vendor/psy/psysh/src/Psy/Command/ListCommand/TraitEnumerator.php
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command\ListCommand;
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
|
||||
/**
|
||||
* Trait Enumerator class.
|
||||
*/
|
||||
class TraitEnumerator extends Enumerator
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function listItems(InputInterface $input, \Reflector $reflector = null, $target = null)
|
||||
{
|
||||
// bail early if current PHP doesn't know about traits.
|
||||
if (!function_exists('trait_exists')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// only list traits when no Reflector is present.
|
||||
//
|
||||
// TODO: make a NamespaceReflector and pass that in for commands like:
|
||||
//
|
||||
// ls --traits Foo
|
||||
//
|
||||
// ... for listing traits in the Foo namespace
|
||||
|
||||
if ($reflector !== null || $target !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// only list traits if we are specifically asked
|
||||
if (!$input->getOption('traits')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$traits = $this->prepareTraits(get_declared_traits());
|
||||
|
||||
if (empty($traits)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return array(
|
||||
'Traits' => $traits,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare formatted trait array.
|
||||
*
|
||||
* @param array $traits
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function prepareTraits(array $traits)
|
||||
{
|
||||
natcasesort($traits);
|
||||
|
||||
// My kingdom for a generator.
|
||||
$ret = array();
|
||||
|
||||
foreach ($traits as $name) {
|
||||
if ($this->showItem($name)) {
|
||||
$ret[$name] = array(
|
||||
'name' => $name,
|
||||
'style' => self::IS_CLASS,
|
||||
'value' => $this->presentSignature($name),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
129
vendor/psy/psysh/src/Psy/Command/ListCommand/VariableEnumerator.php
vendored
Normal file
129
vendor/psy/psysh/src/Psy/Command/ListCommand/VariableEnumerator.php
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command\ListCommand;
|
||||
|
||||
use Psy\Context;
|
||||
use Psy\Presenter\PresenterManager;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
|
||||
/**
|
||||
* Variable Enumerator class.
|
||||
*/
|
||||
class VariableEnumerator extends Enumerator
|
||||
{
|
||||
private static $specialVars = array('_', '_e');
|
||||
private $context;
|
||||
|
||||
/**
|
||||
* Variable Enumerator constructor.
|
||||
*
|
||||
* Unlike most other enumerators, the Variable Enumerator needs access to
|
||||
* the current scope variables, so we need to pass it a Context instance.
|
||||
*
|
||||
* @param PresenterManager $presenterManager
|
||||
* @param Context $context
|
||||
*/
|
||||
public function __construct(PresenterManager $presenterManager, Context $context)
|
||||
{
|
||||
$this->context = $context;
|
||||
parent::__construct($presenterManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function listItems(InputInterface $input, \Reflector $reflector = null, $target = null)
|
||||
{
|
||||
// only list variables when no Reflector is present.
|
||||
if ($reflector !== null || $target !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// only list variables if we are specifically asked
|
||||
if (!$input->getOption('vars')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$showAll = $input->getOption('all');
|
||||
$variables = $this->prepareVariables($this->getVariables($showAll));
|
||||
|
||||
if (empty($variables)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return array(
|
||||
'Variables' => $variables,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get scope variables.
|
||||
*
|
||||
* @param boolean $showAll Include special variables (e.g. $_).
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getVariables($showAll)
|
||||
{
|
||||
$scopeVars = $this->context->getAll();
|
||||
uksort($scopeVars, function ($a, $b) {
|
||||
if ($a === '_e') {
|
||||
return 1;
|
||||
} elseif ($b === '_e') {
|
||||
return -1;
|
||||
} elseif ($a === '_') {
|
||||
return 1;
|
||||
} elseif ($b === '_') {
|
||||
return -1;
|
||||
} else {
|
||||
// TODO: this should be natcasesort
|
||||
return strcasecmp($a, $b);
|
||||
}
|
||||
});
|
||||
|
||||
$ret = array();
|
||||
foreach ($scopeVars as $name => $val) {
|
||||
if (!$showAll && in_array($name, self::$specialVars)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ret[$name] = $val;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare formatted variable array.
|
||||
*
|
||||
* @param array $variables
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function prepareVariables(array $variables)
|
||||
{
|
||||
// My kingdom for a generator.
|
||||
$ret = array();
|
||||
foreach ($variables as $name => $val) {
|
||||
if ($this->showItem($name)) {
|
||||
$fname = '$' . $name;
|
||||
$ret[$fname] = array(
|
||||
'name' => $fname,
|
||||
'style' => in_array($name, self::$specialVars) ? self::IS_PRIVATE : self::IS_PUBLIC,
|
||||
'value' => $this->presentRef($val), // TODO: add types to variable signatures
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
125
vendor/psy/psysh/src/Psy/Command/ParseCommand.php
vendored
Normal file
125
vendor/psy/psysh/src/Psy/Command/ParseCommand.php
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command;
|
||||
|
||||
use PhpParser\Lexer;
|
||||
use PhpParser\Parser;
|
||||
use Psy\Presenter\PHPParserPresenter;
|
||||
use Psy\Presenter\PresenterManager;
|
||||
use Psy\Presenter\PresenterManagerAware;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Parse PHP code and show the abstract syntax tree.
|
||||
*/
|
||||
class ParseCommand extends Command implements PresenterManagerAware
|
||||
{
|
||||
private $presenterManager;
|
||||
private $parser;
|
||||
|
||||
/**
|
||||
* PresenterManagerAware interface.
|
||||
*
|
||||
* @param PresenterManager $manager
|
||||
*/
|
||||
public function setPresenterManager(PresenterManager $manager)
|
||||
{
|
||||
$this->presenterManager = new PresenterManager();
|
||||
|
||||
foreach ($manager as $presenter) {
|
||||
$this->presenterManager->addPresenter($presenter);
|
||||
}
|
||||
|
||||
$this->presenterManager->addPresenter(new PHPParserPresenter());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('parse')
|
||||
->setDefinition(array(
|
||||
new InputArgument('code', InputArgument::REQUIRED, 'PHP code to parse.'),
|
||||
new InputOption('depth', '', InputOption::VALUE_REQUIRED, 'Depth to parse', 10),
|
||||
))
|
||||
->setDescription('Parse PHP code and show the abstract syntax tree.')
|
||||
->setHelp(
|
||||
<<<HELP
|
||||
Parse PHP code and show the abstract syntax tree.
|
||||
|
||||
This command is used in the development of PsySH. Given a string of PHP code,
|
||||
it pretty-prints the PHP Parser parse tree.
|
||||
|
||||
See https://github.com/nikic/PHP-Parser
|
||||
|
||||
It prolly won't be super useful for most of you, but it's here if you want to play.
|
||||
HELP
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$code = $input->getArgument('code');
|
||||
if (strpos('<?', $code) === false) {
|
||||
$code = '<?php ' . $code;
|
||||
}
|
||||
|
||||
$depth = $input->getOption('depth');
|
||||
$nodes = $this->parse($code);
|
||||
$output->page($this->presenterManager->present($nodes, $depth));
|
||||
}
|
||||
|
||||
/**
|
||||
* Lex and parse a string of code into statements.
|
||||
*
|
||||
* @param string $code
|
||||
*
|
||||
* @return array Statements
|
||||
*/
|
||||
private function parse($code)
|
||||
{
|
||||
$parser = $this->getParser();
|
||||
|
||||
try {
|
||||
return $parser->parse($code);
|
||||
} catch (\PhpParser\Error $e) {
|
||||
if (strpos($e->getMessage(), 'unexpected EOF') === false) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
// If we got an unexpected EOF, let's try it again with a semicolon.
|
||||
return $parser->parse($code . ';');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get (or create) the Parser instance.
|
||||
*
|
||||
* @return Parser
|
||||
*/
|
||||
private function getParser()
|
||||
{
|
||||
if (!isset($this->parser)) {
|
||||
$this->parser = new Parser(new Lexer());
|
||||
}
|
||||
|
||||
return $this->parser;
|
||||
}
|
||||
}
|
||||
41
vendor/psy/psysh/src/Psy/Command/PsyVersionCommand.php
vendored
Normal file
41
vendor/psy/psysh/src/Psy/Command/PsyVersionCommand.php
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command;
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* A dumb little command for printing out the current Psy Shell version.
|
||||
*/
|
||||
class PsyVersionCommand extends Command
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('version')
|
||||
->setDefinition(array())
|
||||
->setDescription('Show Psy Shell version.')
|
||||
->setHelp('Show Psy Shell version.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$output->writeln($this->getApplication()->getVersion());
|
||||
}
|
||||
}
|
||||
172
vendor/psy/psysh/src/Psy/Command/ReflectingCommand.php
vendored
Normal file
172
vendor/psy/psysh/src/Psy/Command/ReflectingCommand.php
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command;
|
||||
|
||||
use Psy\Context;
|
||||
use Psy\ContextAware;
|
||||
use Psy\Exception\RuntimeException;
|
||||
use Psy\Util\Mirror;
|
||||
|
||||
/**
|
||||
* An abstract command with helpers for inspecting the current context.
|
||||
*/
|
||||
abstract class ReflectingCommand extends Command implements ContextAware
|
||||
{
|
||||
const CLASS_OR_FUNC = '/^[\\\\\w]+$/';
|
||||
const INSTANCE = '/^\$(\w+)$/';
|
||||
const CLASS_MEMBER = '/^([\\\\\w]+)::(\w+)$/';
|
||||
const CLASS_STATIC = '/^([\\\\\w]+)::\$(\w+)$/';
|
||||
const INSTANCE_MEMBER = '/^\$(\w+)(::|->)(\w+)$/';
|
||||
const INSTANCE_STATIC = '/^\$(\w+)::\$(\w+)$/';
|
||||
|
||||
/**
|
||||
* Context instance (for ContextAware interface).
|
||||
*
|
||||
* @var Context
|
||||
*/
|
||||
protected $context;
|
||||
|
||||
/**
|
||||
* ContextAware interface.
|
||||
*
|
||||
* @param Context $context
|
||||
*/
|
||||
public function setContext(Context $context)
|
||||
{
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the target for a value.
|
||||
*
|
||||
* @throws \InvalidArgumentException when the value specified can't be resolved.
|
||||
*
|
||||
* @param string $valueName Function, class, variable, constant, method or property name.
|
||||
* @param boolean $classOnly True if the name should only refer to a class, function or instance
|
||||
*
|
||||
* @return array (class or instance name, member name, kind)
|
||||
*/
|
||||
protected function getTarget($valueName, $classOnly = false)
|
||||
{
|
||||
$valueName = trim($valueName);
|
||||
$matches = array();
|
||||
switch (true) {
|
||||
case preg_match(self::CLASS_OR_FUNC, $valueName, $matches):
|
||||
return array($this->resolveName($matches[0], true), null, 0);
|
||||
|
||||
case preg_match(self::INSTANCE, $valueName, $matches):
|
||||
return array($this->resolveInstance($matches[1]), null, 0);
|
||||
|
||||
case (!$classOnly && preg_match(self::CLASS_MEMBER, $valueName, $matches)):
|
||||
return array($this->resolveName($matches[1]), $matches[2], Mirror::CONSTANT | Mirror::METHOD);
|
||||
|
||||
case (!$classOnly && preg_match(self::CLASS_STATIC, $valueName, $matches)):
|
||||
return array($this->resolveName($matches[1]), $matches[2], Mirror::STATIC_PROPERTY | Mirror::PROPERTY);
|
||||
|
||||
case (!$classOnly && preg_match(self::INSTANCE_MEMBER, $valueName, $matches)):
|
||||
if ($matches[2] === '->') {
|
||||
$kind = Mirror::METHOD | Mirror::PROPERTY;
|
||||
} else {
|
||||
$kind = Mirror::CONSTANT | Mirror::METHOD;
|
||||
}
|
||||
|
||||
return array($this->resolveInstance($matches[1]), $matches[3], $kind);
|
||||
|
||||
case (!$classOnly && preg_match(self::INSTANCE_STATIC, $valueName, $matches)):
|
||||
return array($this->resolveInstance($matches[1]), $matches[2], Mirror::STATIC_PROPERTY);
|
||||
|
||||
default:
|
||||
throw new RuntimeException('Unknown target: ' . $valueName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a class or function name (with the current shell namespace).
|
||||
*
|
||||
* @param string $name
|
||||
* @param bool $includeFunctions (default: false)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function resolveName($name, $includeFunctions = false)
|
||||
{
|
||||
if (substr($name, 0, 1) === '\\') {
|
||||
return $name;
|
||||
}
|
||||
|
||||
if ($namespace = $this->getApplication()->getNamespace()) {
|
||||
$fullName = $namespace . '\\' . $name;
|
||||
|
||||
if (class_exists($fullName) || interface_exists($fullName) || ($includeFunctions && function_exists($fullName))) {
|
||||
return $fullName;
|
||||
}
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Reflector and documentation for a function, class or instance, constant, method or property.
|
||||
*
|
||||
* @param string $valueName Function, class, variable, constant, method or property name.
|
||||
* @param boolean $classOnly True if the name should only refer to a class, function or instance
|
||||
*
|
||||
* @return array (value, Reflector)
|
||||
*/
|
||||
protected function getTargetAndReflector($valueName, $classOnly = false)
|
||||
{
|
||||
list($value, $member, $kind) = $this->getTarget($valueName, $classOnly);
|
||||
|
||||
return array($value, Mirror::get($value, $member, $kind));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a variable instance from the current scope.
|
||||
*
|
||||
* @throws \InvalidArgumentException when the requested variable does not exist in the current scope.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return mixed Variable instance.
|
||||
*/
|
||||
protected function resolveInstance($name)
|
||||
{
|
||||
$value = $this->getScopeVariable($name);
|
||||
if (!is_object($value)) {
|
||||
throw new RuntimeException('Unable to inspect a non-object');
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a variable from the current shell scope.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getScopeVariable($name)
|
||||
{
|
||||
return $this->context->get($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all scope variables from the current shell scope.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getScopeVariables()
|
||||
{
|
||||
return $this->context->getAll();
|
||||
}
|
||||
}
|
||||
63
vendor/psy/psysh/src/Psy/Command/ShowCommand.php
vendored
Normal file
63
vendor/psy/psysh/src/Psy/Command/ShowCommand.php
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command;
|
||||
|
||||
use Psy\Exception\RuntimeException;
|
||||
use Psy\Formatter\CodeFormatter;
|
||||
use Psy\Formatter\SignatureFormatter;
|
||||
use Psy\Output\ShellOutput;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Show the code for an object, class, constant, method or property.
|
||||
*/
|
||||
class ShowCommand extends ReflectingCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('show')
|
||||
->setDefinition(array(
|
||||
new InputArgument('value', InputArgument::REQUIRED, 'Function, class, instance, constant, method or property to show.'),
|
||||
))
|
||||
->setDescription('Show the code for an object, class, constant, method or property.')
|
||||
->setHelp(
|
||||
<<<HELP
|
||||
Show the code for an object, class, constant, method or property.
|
||||
|
||||
e.g.
|
||||
<return>>>> show \$myObject</return>
|
||||
<return>>>> show Psy\Shell::debug</return>
|
||||
HELP
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
list($value, $reflector) = $this->getTargetAndReflector($input->getArgument('value'));
|
||||
|
||||
try {
|
||||
$output->page(CodeFormatter::format($reflector), ShellOutput::OUTPUT_RAW);
|
||||
} catch (RuntimeException $e) {
|
||||
$output->writeln(SignatureFormatter::format($reflector));
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
87
vendor/psy/psysh/src/Psy/Command/ThrowUpCommand.php
vendored
Normal file
87
vendor/psy/psysh/src/Psy/Command/ThrowUpCommand.php
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command;
|
||||
|
||||
use Psy\Context;
|
||||
use Psy\ContextAware;
|
||||
use Psy\Exception\ThrowUpException;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Throw an exception out of the Psy Shell.
|
||||
*/
|
||||
class ThrowUpCommand extends Command implements ContextAware
|
||||
{
|
||||
/**
|
||||
* Context instance (for ContextAware interface).
|
||||
*
|
||||
* @var Context
|
||||
*/
|
||||
protected $context;
|
||||
|
||||
/**
|
||||
* ContextAware interface.
|
||||
*
|
||||
* @param Context $context
|
||||
*/
|
||||
public function setContext(Context $context)
|
||||
{
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('throw-up')
|
||||
->setDefinition(array(
|
||||
new InputArgument('exception', InputArgument::OPTIONAL, 'Exception to throw'),
|
||||
))
|
||||
->setDescription('Throw an exception out of the Psy Shell.')
|
||||
->setHelp(
|
||||
<<<HELP
|
||||
Throws an exception out of the current the Psy Shell instance.
|
||||
|
||||
By default it throws the most recent exception.
|
||||
|
||||
e.g.
|
||||
<return>>>> throw-up</return>
|
||||
<return>>>> throw-up \$e</return>
|
||||
HELP
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws InvalidArgumentException if there is no exception to throw.
|
||||
* @throws ThrowUpException because what else do you expect it to do?
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
if ($name = $input->getArgument('exception')) {
|
||||
$orig = $this->context->get(preg_replace('/^\$/', '', $name));
|
||||
} else {
|
||||
$orig = $this->context->getLastException();
|
||||
}
|
||||
|
||||
if (!$orig instanceof \Exception) {
|
||||
throw new \InvalidArgumentException('throw-up can only throw Exceptions');
|
||||
}
|
||||
|
||||
throw new ThrowUpException($orig);
|
||||
}
|
||||
}
|
||||
137
vendor/psy/psysh/src/Psy/Command/TraceCommand.php
vendored
Normal file
137
vendor/psy/psysh/src/Psy/Command/TraceCommand.php
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command;
|
||||
|
||||
use Psy\Output\ShellOutput;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatter;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Show the current stack trace.
|
||||
*/
|
||||
class TraceCommand extends Command
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('trace')
|
||||
->setDefinition(array(
|
||||
new InputOption('include-psy', 'p', InputOption::VALUE_NONE, 'Include Psy in the call stack.'),
|
||||
new InputOption('num', 'n', InputOption::VALUE_REQUIRED, 'Only include NUM lines.'),
|
||||
))
|
||||
->setDescription('Show the current call stack.')
|
||||
->setHelp(
|
||||
<<<HELP
|
||||
Show the current call stack.
|
||||
|
||||
Optionally, include PsySH in the call stack by passing the <info>--include-psy</info> option.
|
||||
|
||||
e.g.
|
||||
<return>> trace -n10</return>
|
||||
<return>> trace --include-psy</return>
|
||||
HELP
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$trace = $this->getBacktrace(new \Exception(), $input->getOption('num'), $input->getOption('include-psy'));
|
||||
$output->page($trace, ShellOutput::NUMBER_LINES | ShellOutput::OUTPUT_RAW);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a backtrace for an exception.
|
||||
*
|
||||
* Optionally limit the number of rows to include with $count, and exclude
|
||||
* Psy from the trace.
|
||||
*
|
||||
* @param \Exception $e The exception with a backtrace.
|
||||
* @param int $count (default: PHP_INT_MAX)
|
||||
* @param bool $includePsy (default: true)
|
||||
*
|
||||
* @return array Formatted stacktrace lines.
|
||||
*/
|
||||
protected function getBacktrace(\Exception $e, $count = null, $includePsy = true)
|
||||
{
|
||||
if ($cwd = getcwd()) {
|
||||
$cwd = rtrim($cwd, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
if ($count === null) {
|
||||
$count = PHP_INT_MAX;
|
||||
}
|
||||
|
||||
$lines = array();
|
||||
|
||||
$trace = $e->getTrace();
|
||||
array_unshift($trace, array(
|
||||
'function' => '',
|
||||
'file' => $e->getFile() !== null ? $e->getFile() : 'n/a',
|
||||
'line' => $e->getLine() !== null ? $e->getLine() : 'n/a',
|
||||
'args' => array(),
|
||||
));
|
||||
|
||||
if (!$includePsy) {
|
||||
for ($i = count($trace) - 1; $i >= 0; $i--) {
|
||||
$thing = isset($trace[$i]['class']) ? $trace[$i]['class'] : $trace[$i]['function'];
|
||||
if (preg_match('/\\\\?Psy\\\\/', $thing)) {
|
||||
$trace = array_slice($trace, $i + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ($i = 0, $count = min($count, count($trace)); $i < $count; $i++) {
|
||||
$class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
|
||||
$type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
|
||||
$function = $trace[$i]['function'];
|
||||
$file = isset($trace[$i]['file']) ? $this->replaceCwd($cwd, $trace[$i]['file']) : 'n/a';
|
||||
$line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';
|
||||
|
||||
$lines[] = sprintf(
|
||||
' %s%s%s() at <info>%s:%s</info>',
|
||||
OutputFormatter::escape($class),
|
||||
OutputFormatter::escape($type),
|
||||
OutputFormatter::escape($function),
|
||||
OutputFormatter::escape($file),
|
||||
OutputFormatter::escape($line)
|
||||
);
|
||||
}
|
||||
|
||||
return $lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the given directory from the start of a filepath.
|
||||
*
|
||||
* @param string $cwd
|
||||
* @param string $file
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function replaceCwd($cwd, $file)
|
||||
{
|
||||
if ($cwd === false) {
|
||||
return $file;
|
||||
} else {
|
||||
return preg_replace('/^' . preg_quote($cwd, '/') . '/', '', $file);
|
||||
}
|
||||
}
|
||||
}
|
||||
115
vendor/psy/psysh/src/Psy/Command/WhereamiCommand.php
vendored
Normal file
115
vendor/psy/psysh/src/Psy/Command/WhereamiCommand.php
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command;
|
||||
|
||||
use JakubOnderka\PhpConsoleColor\ConsoleColor;
|
||||
use JakubOnderka\PhpConsoleHighlighter\Highlighter;
|
||||
use Psy\Output\ShellOutput;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Show the context of where you opened the debugger.
|
||||
*/
|
||||
class WhereamiCommand extends Command
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.3.6', '>=')) {
|
||||
$this->backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
|
||||
} else {
|
||||
$this->backtrace = debug_backtrace();
|
||||
}
|
||||
|
||||
return parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('whereami')
|
||||
->setDefinition(array(
|
||||
new InputOption('num', 'n', InputOption::VALUE_OPTIONAL, 'Number of lines before and after.', '5'),
|
||||
))
|
||||
->setDescription('Show where you are in the code.')
|
||||
->setHelp(
|
||||
<<<HELP
|
||||
Show where you are in the code.
|
||||
|
||||
Optionally, include how many lines before and after you want to display.
|
||||
|
||||
e.g.
|
||||
<return>> whereami </return>
|
||||
<return>> whereami -n10</return>
|
||||
HELP
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the correct trace in the full backtrace.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function trace()
|
||||
{
|
||||
foreach ($this->backtrace as $i => $backtrace) {
|
||||
if (!isset($backtrace['class'], $backtrace['function'])) {
|
||||
continue;
|
||||
}
|
||||
$correctClass = $backtrace['class'] === 'Psy\Shell';
|
||||
$correctFunction = $backtrace['function'] === 'debug';
|
||||
if ($correctClass && $correctFunction) {
|
||||
return $backtrace;
|
||||
}
|
||||
}
|
||||
|
||||
return end($this->backtrace);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the file and line based on the specific backtrace.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function fileInfo()
|
||||
{
|
||||
$backtrace = $this->trace();
|
||||
if (preg_match('/eval\(/', $backtrace['file'])) {
|
||||
preg_match_all('/([^\(]+)\((\d+)/', $backtrace['file'], $matches);
|
||||
$file = $matches[1][0];
|
||||
$line = (int) $matches[2][0];
|
||||
} else {
|
||||
$file = $backtrace['file'];
|
||||
$line = $backtrace['line'];
|
||||
}
|
||||
|
||||
return compact('file', 'line');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$info = $this->fileInfo();
|
||||
$num = $input->getOption('num');
|
||||
$colors = new ConsoleColor();
|
||||
$colors->addTheme('line_number', array('blue'));
|
||||
$highlighter = new Highlighter($colors);
|
||||
$contents = file_get_contents($info['file']);
|
||||
$output->page($highlighter->getCodeSnippet($contents, $info['line'], $num, $num), ShellOutput::OUTPUT_RAW);
|
||||
}
|
||||
}
|
||||
111
vendor/psy/psysh/src/Psy/Command/WtfCommand.php
vendored
Normal file
111
vendor/psy/psysh/src/Psy/Command/WtfCommand.php
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell
|
||||
*
|
||||
* (c) 2012-2014 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Command;
|
||||
|
||||
use Psy\Context;
|
||||
use Psy\ContextAware;
|
||||
use Psy\Output\ShellOutput;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Show the last uncaught exception.
|
||||
*/
|
||||
class WtfCommand extends TraceCommand implements ContextAware
|
||||
{
|
||||
/**
|
||||
* Context instance (for ContextAware interface).
|
||||
*
|
||||
* @var Context
|
||||
*/
|
||||
protected $context;
|
||||
|
||||
/**
|
||||
* ContextAware interface.
|
||||
*
|
||||
* @param Context $context
|
||||
*/
|
||||
public function setContext(Context $context)
|
||||
{
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('wtf')
|
||||
->setAliases(array('last-exception', 'wtf?'))
|
||||
->setDefinition(array(
|
||||
new InputArgument('incredulity', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, 'Number of lines to show'),
|
||||
new InputOption('verbose', 'v', InputOption::VALUE_NONE, 'Show entire backtrace.'),
|
||||
))
|
||||
->setDescription('Show the backtrace of the most recent exception.')
|
||||
->setHelp(
|
||||
<<<HELP
|
||||
Shows a few lines of the backtrace of the most recent exception.
|
||||
|
||||
If you want to see more lines, add more question marks or exclamation marks:
|
||||
|
||||
e.g.
|
||||
<return>>>> wtf ?</return>
|
||||
<return>>>> wtf ?!???!?!?</return>
|
||||
|
||||
To see the entire backtrace, pass the -v/--verbose flag:
|
||||
|
||||
e.g.
|
||||
<return>>>> wtf -v</return>
|
||||
HELP
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* --verbose is not hidden for this option :)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getHiddenOptions()
|
||||
{
|
||||
$options = parent::getHiddenOptions();
|
||||
unset($options[array_search('verbose', $options)]);
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$incredulity = implode('', $input->getArgument('incredulity'));
|
||||
if (strlen(preg_replace('/[\\?!]/', '', $incredulity))) {
|
||||
throw new \InvalidArgumentException('Incredulity must include only "?" and "!".');
|
||||
}
|
||||
|
||||
$exception = $this->context->getLastException();
|
||||
$count = $input->getOption('verbose') ? PHP_INT_MAX : pow(2, max(0, (strlen($incredulity) - 1)));
|
||||
$trace = $this->getBacktrace($exception, $count);
|
||||
|
||||
$shell = $this->getApplication();
|
||||
$output->page(function ($output) use ($exception, $trace, $shell) {
|
||||
$shell->renderException($exception, $output);
|
||||
$output->writeln('--');
|
||||
$output->write($trace, true, ShellOutput::NUMBER_LINES);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user