vendor/symfony/src/Symfony/Component/Console/Shell.php
changeset 0 7f95f8617b0b
equal deleted inserted replaced
-1:000000000000 0:7f95f8617b0b
       
     1 <?php
       
     2 
       
     3 /*
       
     4  * This file is part of the Symfony package.
       
     5  *
       
     6  * (c) Fabien Potencier <fabien@symfony.com>
       
     7  *
       
     8  * For the full copyright and license information, please view the LICENSE
       
     9  * file that was distributed with this source code.
       
    10  */
       
    11 
       
    12 namespace Symfony\Component\Console;
       
    13 
       
    14 use Symfony\Component\Console\Application;
       
    15 use Symfony\Component\Console\Input\StringInput;
       
    16 use Symfony\Component\Console\Output\ConsoleOutput;
       
    17 
       
    18 /**
       
    19  * A Shell wraps an Application to add shell capabilities to it.
       
    20  *
       
    21  * This class only works with a PHP compiled with readline support
       
    22  * (either --with-readline or --with-libedit)
       
    23  *
       
    24  * @author Fabien Potencier <fabien@symfony.com>
       
    25  */
       
    26 class Shell
       
    27 {
       
    28     private $application;
       
    29     private $history;
       
    30     private $output;
       
    31 
       
    32     /**
       
    33      * Constructor.
       
    34      *
       
    35      * If there is no readline support for the current PHP executable
       
    36      * a \RuntimeException exception is thrown.
       
    37      *
       
    38      * @param Application $application An application instance
       
    39      *
       
    40      * @throws \RuntimeException When Readline extension is not enabled
       
    41      */
       
    42     public function __construct(Application $application)
       
    43     {
       
    44         if (!function_exists('readline')) {
       
    45             throw new \RuntimeException('Unable to start the shell as the Readline extension is not enabled.');
       
    46         }
       
    47 
       
    48         $this->application = $application;
       
    49         $this->history = getenv('HOME').'/.history_'.$application->getName();
       
    50         $this->output = new ConsoleOutput();
       
    51     }
       
    52 
       
    53     /**
       
    54      * Runs the shell.
       
    55      */
       
    56     public function run()
       
    57     {
       
    58         $this->application->setAutoExit(false);
       
    59         $this->application->setCatchExceptions(true);
       
    60 
       
    61         readline_read_history($this->history);
       
    62         readline_completion_function(array($this, 'autocompleter'));
       
    63 
       
    64         $this->output->writeln($this->getHeader());
       
    65         while (true) {
       
    66             $command = readline($this->application->getName().' > ');
       
    67 
       
    68             if (false === $command) {
       
    69                 $this->output->writeln("\n");
       
    70 
       
    71                 break;
       
    72             }
       
    73 
       
    74             readline_add_history($command);
       
    75             readline_write_history($this->history);
       
    76 
       
    77             if (0 !== $ret = $this->application->run(new StringInput($command), $this->output)) {
       
    78                 $this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
       
    79             }
       
    80         }
       
    81     }
       
    82 
       
    83     /**
       
    84      * Tries to return autocompletion for the current entered text.
       
    85      *
       
    86      * @param string  $text     The last segment of the entered text
       
    87      * @param integer $position The current position
       
    88      */
       
    89     private function autocompleter($text, $position)
       
    90     {
       
    91         $info = readline_info();
       
    92         $text = substr($info['line_buffer'], 0, $info['end']);
       
    93 
       
    94         if ($info['point'] !== $info['end']) {
       
    95             return true;
       
    96         }
       
    97 
       
    98         // task name?
       
    99         if (false === strpos($text, ' ') || !$text) {
       
   100             return array_keys($this->application->all());
       
   101         }
       
   102 
       
   103         // options and arguments?
       
   104         try {
       
   105             $command = $this->application->find(substr($text, 0, strpos($text, ' ')));
       
   106         } catch (\Exception $e) {
       
   107             return true;
       
   108         }
       
   109 
       
   110         $list = array('--help');
       
   111         foreach ($command->getDefinition()->getOptions() as $option) {
       
   112             $list[] = '--'.$option->getName();
       
   113         }
       
   114 
       
   115         return $list;
       
   116     }
       
   117 
       
   118     /**
       
   119      * Returns the shell header.
       
   120      *
       
   121      * @return string The header string
       
   122      */
       
   123     protected function getHeader()
       
   124     {
       
   125         return <<<EOF
       
   126 
       
   127 Welcome to the <info>{$this->application->getName()}</info> shell (<comment>{$this->application->getVersion()}</comment>).
       
   128 
       
   129 At the prompt, type <comment>help</comment> for some help,
       
   130 or <comment>list</comment> to get a list available commands.
       
   131 
       
   132 To exit the shell, type <comment>^D</comment>.
       
   133 
       
   134 EOF;
       
   135     }
       
   136 }