X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs-website;a=blobdiff_plain;f=vendor%2Fpsy%2Fpsysh%2Fsrc%2FPsy%2FShell.php;fp=vendor%2Fpsy%2Fpsysh%2Fsrc%2FPsy%2FShell.php;h=0000000000000000000000000000000000000000;hp=e002bee1166f3035add699c48e6fbaa486effe99;hb=af6d1fb995500ae68849458ee10d66abbdcfb252;hpb=680c79a86e3ed402f263faeac92e89fb6d9edcc0 diff --git a/vendor/psy/psysh/src/Psy/Shell.php b/vendor/psy/psysh/src/Psy/Shell.php deleted file mode 100644 index e002bee11..000000000 --- a/vendor/psy/psysh/src/Psy/Shell.php +++ /dev/null @@ -1,1033 +0,0 @@ -run(); - * - * @author Justin Hileman - */ -class Shell extends Application -{ - const VERSION = 'v0.8.17'; - - const PROMPT = '>>> '; - const BUFF_PROMPT = '... '; - const REPLAY = '--> '; - const RETVAL = '=> '; - - private $config; - private $cleaner; - private $output; - private $readline; - private $inputBuffer; - private $code; - private $codeBuffer; - private $codeBufferOpen; - private $context; - private $includes; - private $loop; - private $outputWantsNewline = false; - private $completion; - private $tabCompletionMatchers = array(); - private $stdoutBuffer; - private $prompt; - - /** - * Create a new Psy Shell. - * - * @param Configuration $config (default: null) - */ - public function __construct(Configuration $config = null) - { - $this->config = $config ?: new Configuration(); - $this->cleaner = $this->config->getCodeCleaner(); - $this->loop = $this->config->getLoop(); - $this->context = new Context(); - $this->includes = array(); - $this->readline = $this->config->getReadline(); - $this->inputBuffer = array(); - $this->stdoutBuffer = ''; - - parent::__construct('Psy Shell', self::VERSION); - - $this->config->setShell($this); - - // Register the current shell session's config with \Psy\info - \Psy\info($this->config); - } - - /** - * Check whether the first thing in a backtrace is an include call. - * - * This is used by the psysh bin to decide whether to start a shell on boot, - * or to simply autoload the library. - */ - public static function isIncluded(array $trace) - { - return isset($trace[0]['function']) && - in_array($trace[0]['function'], array('require', 'include', 'require_once', 'include_once')); - } - - /** - * Invoke a Psy Shell from the current context. - * - * @see Psy\debug - * @deprecated will be removed in 1.0. Use \Psy\debug instead - * - * @param array $vars Scope variables from the calling context (default: array()) - * @param object $boundObject Bound object ($this) value for the shell - * - * @return array Scope variables from the debugger session - */ - public static function debug(array $vars = array(), $boundObject = null) - { - return \Psy\debug($vars, $boundObject); - } - - /** - * Adds a command object. - * - * {@inheritdoc} - * - * @param BaseCommand $command A Symfony Console Command object - * - * @return BaseCommand The registered command - */ - public function add(BaseCommand $command) - { - if ($ret = parent::add($command)) { - if ($ret instanceof ContextAware) { - $ret->setContext($this->context); - } - - if ($ret instanceof PresenterAware) { - $ret->setPresenter($this->config->getPresenter()); - } - } - - return $ret; - } - - /** - * Gets the default input definition. - * - * @return InputDefinition An InputDefinition instance - */ - protected function getDefaultInputDefinition() - { - return new InputDefinition(array( - new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'), - new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message.'), - )); - } - - /** - * Gets the default commands that should always be available. - * - * @return array An array of default Command instances - */ - protected function getDefaultCommands() - { - $sudo = new Command\SudoCommand(); - $sudo->setReadline($this->readline); - - $hist = new Command\HistoryCommand(); - $hist->setReadline($this->readline); - - return array( - new Command\HelpCommand(), - new Command\ListCommand(), - new Command\DumpCommand(), - new Command\DocCommand(), - new Command\ShowCommand($this->config->colorMode()), - new Command\WtfCommand($this->config->colorMode()), - new Command\WhereamiCommand($this->config->colorMode()), - new Command\ThrowUpCommand(), - new Command\TraceCommand(), - new Command\BufferCommand(), - new Command\ClearCommand(), - new Command\EditCommand($this->config->getRuntimeDir()), - // new Command\PsyVersionCommand(), - $sudo, - $hist, - new Command\ExitCommand(), - ); - } - - /** - * @return array - */ - protected function getTabCompletionMatchers() - { - if (empty($this->tabCompletionMatchers)) { - $this->tabCompletionMatchers = array( - new Matcher\CommandsMatcher($this->all()), - new Matcher\KeywordsMatcher(), - new Matcher\VariablesMatcher(), - new Matcher\ConstantsMatcher(), - new Matcher\FunctionsMatcher(), - new Matcher\ClassNamesMatcher(), - new Matcher\ClassMethodsMatcher(), - new Matcher\ClassAttributesMatcher(), - new Matcher\ObjectMethodsMatcher(), - new Matcher\ObjectAttributesMatcher(), - new Matcher\ClassMethodDefaultParametersMatcher(), - new Matcher\ObjectMethodDefaultParametersMatcher(), - new Matcher\FunctionDefaultParametersMatcher(), - ); - } - - return $this->tabCompletionMatchers; - } - - /** - * @param array $matchers - */ - public function addTabCompletionMatchers(array $matchers) - { - $this->tabCompletionMatchers = array_merge($matchers, $this->getTabCompletionMatchers()); - } - - /** - * Set the Shell output. - * - * @param OutputInterface $output - */ - public function setOutput(OutputInterface $output) - { - $this->output = $output; - } - - /** - * Runs the current application. - * - * @param InputInterface $input An Input instance - * @param OutputInterface $output An Output instance - * - * @return int 0 if everything went fine, or an error code - */ - public function run(InputInterface $input = null, OutputInterface $output = null) - { - $this->initializeTabCompletion(); - - if ($input === null && !isset($_SERVER['argv'])) { - $input = new ArgvInput(array()); - } - - if ($output === null) { - $output = $this->config->getOutput(); - } - - try { - return parent::run($input, $output); - } catch (\Exception $e) { - $this->writeException($e); - } - } - - /** - * Runs the current application. - * - * @throws Exception if thrown via the `throw-up` command - * - * @param InputInterface $input An Input instance - * @param OutputInterface $output An Output instance - * - * @return int 0 if everything went fine, or an error code - */ - public function doRun(InputInterface $input, OutputInterface $output) - { - $this->setOutput($output); - - $this->resetCodeBuffer(); - - $this->setAutoExit(false); - $this->setCatchExceptions(false); - - $this->readline->readHistory(); - - // if ($this->config->useReadline()) { - // readline_completion_function(array($this, 'autocomplete')); - // } - - $this->output->writeln($this->getHeader()); - $this->writeVersionInfo(); - $this->writeStartupMessage(); - - try { - $this->loop->run($this); - } catch (ThrowUpException $e) { - throw $e->getPrevious(); - } - } - - /** - * Read user input. - * - * This will continue fetching user input until the code buffer contains - * valid code. - * - * @throws BreakException if user hits Ctrl+D - */ - public function getInput() - { - $this->codeBufferOpen = false; - - do { - // reset output verbosity (in case it was altered by a subcommand) - $this->output->setVerbosity(ShellOutput::VERBOSITY_VERBOSE); - - $input = $this->readline(); - - /* - * Handle Ctrl+D. It behaves differently in different cases: - * - * 1) In an expression, like a function or "if" block, clear the input buffer - * 2) At top-level session, behave like the exit command - */ - if ($input === false) { - $this->output->writeln(''); - - if ($this->hasCode()) { - $this->resetCodeBuffer(); - } else { - throw new BreakException('Ctrl+D'); - } - } - - // handle empty input - if (trim($input) === '') { - continue; - } - - if ($this->hasCommand($input)) { - $this->readline->addHistory($input); - $this->runCommand($input); - - continue; - } - - $this->addCode($input); - } while (!$this->hasValidCode()); - } - - /** - * Pass the beforeLoop callback through to the Loop instance. - * - * @see Loop::beforeLoop - */ - public function beforeLoop() - { - $this->loop->beforeLoop(); - } - - /** - * Pass the afterLoop callback through to the Loop instance. - * - * @see Loop::afterLoop - */ - public function afterLoop() - { - $this->loop->afterLoop(); - } - - /** - * Set the variables currently in scope. - * - * @param array $vars - */ - public function setScopeVariables(array $vars) - { - $this->context->setAll($vars); - } - - /** - * Return the set of variables currently in scope. - * - * @param bool $includeBoundObject Pass false to exclude 'this'. If you're - * passing the scope variables to `extract` - * in PHP 7.1+, you _must_ exclude 'this' - * - * @return array Associative array of scope variables - */ - public function getScopeVariables($includeBoundObject = true) - { - $vars = $this->context->getAll(); - - if (!$includeBoundObject) { - unset($vars['this']); - } - - return $vars; - } - - /** - * Return the set of magic variables currently in scope. - * - * @param bool $includeBoundObject Pass false to exclude 'this'. If you're - * passing the scope variables to `extract` - * in PHP 7.1+, you _must_ exclude 'this' - * - * @return array Associative array of magic scope variables - */ - public function getSpecialScopeVariables($includeBoundObject = true) - { - $vars = $this->context->getSpecialVariables(); - - if (!$includeBoundObject) { - unset($vars['this']); - } - - return $vars; - } - - /** - * Get the set of unused command-scope variable names. - * - * @return array Array of unused variable names - */ - public function getUnusedCommandScopeVariableNames() - { - return $this->context->getUnusedCommandScopeVariableNames(); - } - - /** - * Get the set of variable names currently in scope. - * - * @return array Array of variable names - */ - public function getScopeVariableNames() - { - return array_keys($this->context->getAll()); - } - - /** - * Get a scope variable value by name. - * - * @param string $name - * - * @return mixed - */ - public function getScopeVariable($name) - { - return $this->context->get($name); - } - - /** - * Set the bound object ($this variable) for the interactive shell. - * - * @param object|null $boundObject - */ - public function setBoundObject($boundObject) - { - $this->context->setBoundObject($boundObject); - } - - /** - * Get the bound object ($this variable) for the interactive shell. - * - * @return object|null - */ - public function getBoundObject() - { - return $this->context->getBoundObject(); - } - - /** - * Add includes, to be parsed and executed before running the interactive shell. - * - * @param array $includes - */ - public function setIncludes(array $includes = array()) - { - $this->includes = $includes; - } - - /** - * Get PHP files to be parsed and executed before running the interactive shell. - * - * @return array - */ - public function getIncludes() - { - return array_merge($this->config->getDefaultIncludes(), $this->includes); - } - - /** - * Check whether this shell's code buffer contains code. - * - * @return bool True if the code buffer contains code - */ - public function hasCode() - { - return !empty($this->codeBuffer); - } - - /** - * Check whether the code in this shell's code buffer is valid. - * - * If the code is valid, the code buffer should be flushed and evaluated. - * - * @return bool True if the code buffer content is valid - */ - protected function hasValidCode() - { - return !$this->codeBufferOpen && $this->code !== false; - } - - /** - * Add code to the code buffer. - * - * @param string $code - */ - public function addCode($code) - { - try { - // Code lines ending in \ keep the buffer open - if (substr(rtrim($code), -1) === '\\') { - $this->codeBufferOpen = true; - $code = substr(rtrim($code), 0, -1); - } else { - $this->codeBufferOpen = false; - } - - $this->codeBuffer[] = $code; - $this->code = $this->cleaner->clean($this->codeBuffer, $this->config->requireSemicolons()); - } catch (\Exception $e) { - // Add failed code blocks to the readline history. - $this->addCodeBufferToHistory(); - - throw $e; - } - } - - /** - * Get the current code buffer. - * - * This is useful for commands which manipulate the buffer. - * - * @return array - */ - public function getCodeBuffer() - { - return $this->codeBuffer; - } - - /** - * Run a Psy Shell command given the user input. - * - * @throws InvalidArgumentException if the input is not a valid command - * - * @param string $input User input string - * - * @return mixed Who knows? - */ - protected function runCommand($input) - { - $command = $this->getCommand($input); - - if (empty($command)) { - throw new \InvalidArgumentException('Command not found: ' . $input); - } - - $input = new ShellInput(str_replace('\\', '\\\\', rtrim($input, " \t\n\r\0\x0B;"))); - - if ($input->hasParameterOption(array('--help', '-h'))) { - $helpCommand = $this->get('help'); - $helpCommand->setCommand($command); - - return $helpCommand->run($input, $this->output); - } - - return $command->run($input, $this->output); - } - - /** - * Reset the current code buffer. - * - * This should be run after evaluating user input, catching exceptions, or - * on demand by commands such as BufferCommand. - */ - public function resetCodeBuffer() - { - $this->codeBuffer = array(); - $this->code = false; - } - - /** - * Inject input into the input buffer. - * - * This is useful for commands which want to replay history. - * - * @param string|array $input - * @param bool $silent - */ - public function addInput($input, $silent = false) - { - foreach ((array) $input as $line) { - $this->inputBuffer[] = $silent ? new SilentInput($line) : $line; - } - } - - /** - * Flush the current (valid) code buffer. - * - * If the code buffer is valid, resets the code buffer and returns the - * current code. - * - * @return string PHP code buffer contents - */ - public function flushCode() - { - if ($this->hasValidCode()) { - $this->addCodeBufferToHistory(); - $code = $this->code; - $this->resetCodeBuffer(); - - return $code; - } - } - - /** - * Filter silent input from code buffer, write the rest to readline history. - */ - private function addCodeBufferToHistory() - { - $codeBuffer = array_filter($this->codeBuffer, function ($line) { - return !$line instanceof SilentInput; - }); - - $code = implode("\n", $codeBuffer); - - if (trim($code) !== '') { - $this->readline->addHistory($code); - } - } - - /** - * Get the current evaluation scope namespace. - * - * @see CodeCleaner::getNamespace - * - * @return string Current code namespace - */ - public function getNamespace() - { - if ($namespace = $this->cleaner->getNamespace()) { - return implode('\\', $namespace); - } - } - - /** - * Write a string to stdout. - * - * This is used by the shell loop for rendering output from evaluated code. - * - * @param string $out - * @param int $phase Output buffering phase - */ - public function writeStdout($out, $phase = PHP_OUTPUT_HANDLER_END) - { - $isCleaning = false; - if (version_compare(PHP_VERSION, '5.4', '>=')) { - $isCleaning = $phase & PHP_OUTPUT_HANDLER_CLEAN; - } - - // Incremental flush - if ($out !== '' && !$isCleaning) { - $this->output->write($out, false, ShellOutput::OUTPUT_RAW); - $this->outputWantsNewline = (substr($out, -1) !== "\n"); - $this->stdoutBuffer .= $out; - } - - // Output buffering is done! - if ($phase & PHP_OUTPUT_HANDLER_END) { - // Write an extra newline if stdout didn't end with one - if ($this->outputWantsNewline) { - $this->output->writeln(sprintf('', $this->config->useUnicode() ? '⏎' : '\\n')); - $this->outputWantsNewline = false; - } - - // Save the stdout buffer as $__out - if ($this->stdoutBuffer !== '') { - $this->context->setLastStdout($this->stdoutBuffer); - $this->stdoutBuffer = ''; - } - } - } - - /** - * Write a return value to stdout. - * - * The return value is formatted or pretty-printed, and rendered in a - * visibly distinct manner (in this case, as cyan). - * - * @see self::presentValue - * - * @param mixed $ret - */ - public function writeReturnValue($ret) - { - if ($ret instanceof NoReturnValue) { - return; - } - - $this->context->setReturnValue($ret); - $ret = $this->presentValue($ret); - $indent = str_repeat(' ', strlen(static::RETVAL)); - - $this->output->writeln(static::RETVAL . str_replace(PHP_EOL, PHP_EOL . $indent, $ret)); - } - - /** - * Renders a caught Exception. - * - * Exceptions are formatted according to severity. ErrorExceptions which were - * warnings or Strict errors aren't rendered as harshly as real errors. - * - * Stores $e as the last Exception in the Shell Context. - * - * @param \Exception $e An exception instance - * @param OutputInterface $output An OutputInterface instance - */ - public function writeException(\Exception $e) - { - $this->context->setLastException($e); - $this->output->writeln($this->formatException($e)); - $this->resetCodeBuffer(); - } - - /** - * Helper for formatting an exception for writeException(). - * - * @todo extract this to somewhere it makes more sense - * - * @param \Exception $e - * - * @return string - */ - public function formatException(\Exception $e) - { - $message = $e->getMessage(); - if (!$e instanceof PsyException) { - if ($message === '') { - $message = get_class($e); - } else { - $message = sprintf('%s with message \'%s\'', get_class($e), $message); - } - } - - $severity = ($e instanceof \ErrorException) ? $this->getSeverity($e) : 'error'; - - return sprintf('<%s>%s', $severity, OutputFormatter::escape($message), $severity); - } - - /** - * Helper for getting an output style for the given ErrorException's level. - * - * @param \ErrorException $e - * - * @return string - */ - protected function getSeverity(\ErrorException $e) - { - $severity = $e->getSeverity(); - if ($severity & error_reporting()) { - switch ($severity) { - case E_WARNING: - case E_NOTICE: - case E_CORE_WARNING: - case E_COMPILE_WARNING: - case E_USER_WARNING: - case E_USER_NOTICE: - case E_STRICT: - return 'warning'; - - default: - return 'error'; - } - } else { - // Since this is below the user's reporting threshold, it's always going to be a warning. - return 'warning'; - } - } - - /** - * Helper for throwing an ErrorException. - * - * This allows us to: - * - * set_error_handler(array($psysh, 'handleError')); - * - * Unlike ErrorException::throwException, this error handler respects the - * current error_reporting level; i.e. it logs warnings and notices, but - * doesn't throw an exception unless it's above the current error_reporting - * threshold. This should probably only be used in the inner execution loop - * of the shell, as most of the time a thrown exception is much more useful. - * - * If the error type matches the `errorLoggingLevel` config, it will be - * logged as well, regardless of the `error_reporting` level. - * - * @see \Psy\Exception\ErrorException::throwException - * @see \Psy\Shell::writeException - * - * @throws \Psy\Exception\ErrorException depending on the current error_reporting level - * - * @param int $errno Error type - * @param string $errstr Message - * @param string $errfile Filename - * @param int $errline Line number - */ - public function handleError($errno, $errstr, $errfile, $errline) - { - if ($errno & error_reporting()) { - ErrorException::throwException($errno, $errstr, $errfile, $errline); - } elseif ($errno & $this->config->errorLoggingLevel()) { - // log it and continue... - $this->writeException(new ErrorException($errstr, 0, $errno, $errfile, $errline)); - } - } - - /** - * Format a value for display. - * - * @see Presenter::present - * - * @param mixed $val - * - * @return string Formatted value - */ - protected function presentValue($val) - { - return $this->config->getPresenter()->present($val); - } - - /** - * Get a command (if one exists) for the current input string. - * - * @param string $input - * - * @return null|BaseCommand - */ - protected function getCommand($input) - { - $input = new StringInput($input); - if ($name = $input->getFirstArgument()) { - return $this->get($name); - } - } - - /** - * Check whether a command is set for the current input string. - * - * @param string $input - * - * @return bool True if the shell has a command for the given input - */ - protected function hasCommand($input) - { - $input = new StringInput($input); - if ($name = $input->getFirstArgument()) { - return $this->has($name); - } - - return false; - } - - /** - * Get the current input prompt. - * - * @return string - */ - protected function getPrompt() - { - if ($this->hasCode()) { - return static::BUFF_PROMPT; - } - - return $this->config->getPrompt() ?: static::PROMPT; - } - - /** - * Read a line of user input. - * - * This will return a line from the input buffer (if any exist). Otherwise, - * it will ask the user for input. - * - * If readline is enabled, this delegates to readline. Otherwise, it's an - * ugly `fgets` call. - * - * @return string One line of user input - */ - protected function readline() - { - if (!empty($this->inputBuffer)) { - $line = array_shift($this->inputBuffer); - if (!$line instanceof SilentInput) { - $this->output->writeln(sprintf('', static::REPLAY, OutputFormatter::escape($line))); - } - - return $line; - } - - if ($bracketedPaste = $this->config->useBracketedPaste()) { - printf("\e[?2004h"); // Enable bracketed paste - } - - $line = $this->readline->readline($this->getPrompt()); - - if ($bracketedPaste) { - printf("\e[?2004l"); // ... and disable it again - } - - return $line; - } - - /** - * Get the shell output header. - * - * @return string - */ - protected function getHeader() - { - return sprintf('', $this->getVersion()); - } - - /** - * Get the current version of Psy Shell. - * - * @return string - */ - public function getVersion() - { - $separator = $this->config->useUnicode() ? '—' : '-'; - - return sprintf('Psy Shell %s (PHP %s %s %s)', self::VERSION, phpversion(), $separator, php_sapi_name()); - } - - /** - * Get a PHP manual database instance. - * - * @return \PDO|null - */ - public function getManualDb() - { - return $this->config->getManualDb(); - } - - /** - * Autocomplete variable names. - * - * This is used by `readline` for tab completion. - * - * @param string $text - * - * @return mixed Array possible completions for the given input, if any - */ - protected function autocomplete($text) - { - $info = readline_info(); - // $line = substr($info['line_buffer'], 0, $info['end']); - - // Check whether there's a command for this - // $words = explode(' ', $line); - // $firstWord = reset($words); - - // check whether this is a variable... - $firstChar = substr($info['line_buffer'], max(0, $info['end'] - strlen($text) - 1), 1); - if ($firstChar === '$') { - return $this->getScopeVariableNames(); - } - } - - /** - * Initialize tab completion matchers. - * - * If tab completion is enabled this adds tab completion matchers to the - * auto completer and sets context if needed. - */ - protected function initializeTabCompletion() - { - // auto completer needs shell to be linked to configuration because of the context aware matchers - if ($this->config->getTabCompletion()) { - $this->completion = $this->config->getAutoCompleter(); - $this->addTabCompletionMatchers($this->config->getTabCompletionMatchers()); - foreach ($this->getTabCompletionMatchers() as $matcher) { - if ($matcher instanceof ContextAware) { - $matcher->setContext($this->context); - } - $this->completion->addMatcher($matcher); - } - $this->completion->activate(); - } - } - - /** - * @todo Implement self-update - * @todo Implement prompt to start update - * - * @return void|string - */ - protected function writeVersionInfo() - { - if (PHP_SAPI !== 'cli') { - return; - } - - try { - $client = $this->config->getChecker(); - if (!$client->isLatest()) { - $this->output->writeln(sprintf('New version is available (current: %s, latest: %s)', self::VERSION, $client->getLatest())); - } - } catch (\InvalidArgumentException $e) { - $this->output->writeln($e->getMessage()); - } - } - - /** - * Write a startup message if set. - */ - protected function writeStartupMessage() - { - $message = $this->config->getStartupMessage(); - if ($message !== null && $message !== '') { - $this->output->writeln($message); - } - } -}