12 namespace Symfony\Component\Console;
16 use Symfony\Component\Process\ProcessBuilder;
17 use Symfony\Component\Process\PhpExecutableFinder;
46 $this->hasReadline = function_exists(
'readline');
48 $this->history = getenv(
'HOME').
'/.history_'.$application->
getName();
57 $this->application->setAutoExit(
false);
58 $this->application->setCatchExceptions(
true);
60 if ($this->hasReadline) {
61 readline_read_history($this->history);
62 readline_completion_function(array($this,
'autocompleter'));
65 $this->output->writeln($this->
getHeader());
67 if ($this->processIsolation) {
68 $finder =
new PhpExecutableFinder();
69 $php = $finder->find();
70 $this->output->writeln(<<<EOF
71 <info>Running with process isolation, you should consider
this:</info>
72 * each command is executed as separate process,
73 * commands don
't support interactivity, all params must be passed explicitly,
74 * commands output is not colorized.
81 $command = $this->readline();
83 if (false === $command) {
84 $this->output->writeln("\n");
89 if ($this->hasReadline) {
90 readline_add_history($command);
91 readline_write_history($this->history);
94 if ($this->processIsolation) {
95 $pb = new ProcessBuilder();
99 ->add($_SERVER['argv
'][0])
101 ->inheritEnvironmentVariables(true)
105 $output = $this->output;
106 $process->run(function ($type, $data) use ($output) {
107 $output->writeln($data);
110 $ret = $process->getExitCode();
112 $ret = $this->application->run(new StringInput($command), $this->output);
116 $this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>
', $ret));
126 protected function getHeader()
130 Welcome to the <info>{$this->application->getName()}</info> shell (<comment>{$this->application->getVersion()}</comment>).
132 At the prompt, type <comment>help</comment> for some help,
133 or <comment>list</comment> to get a list of available commands.
135 To exit the shell, type <comment>^D</comment>.
145 protected function getPrompt()
147 // using the formatter here is required when using readline
148 return $this->output->getFormatter()->format($this->application->getName().' >
');
151 protected function getOutput()
153 return $this->output;
156 protected function getApplication()
158 return $this->application;
168 private function autocompleter($text)
170 $info = readline_info();
171 $text = substr($info['line_buffer
'], 0, $info['end
']);
173 if ($info['point
'] !== $info['end
']) {
178 if (false === strpos($text, ' ') || !$text) {
179 return array_keys($this->application->all());
182 // options and arguments?
184 $command = $this->application->find(substr($text, 0, strpos($text, ' ')));
185 } catch (\Exception $e) {
189 $list = array('--help
');
190 foreach ($command->getDefinition()->getOptions() as $option) {
191 $list[] = '--
'.$option->getName();
202 private function readline()
204 if ($this->hasReadline) {
205 $line = readline($this->getPrompt());
207 $this->output->write($this->getPrompt());
208 $line = fgets(STDIN, 1024);
209 $line = (false === $line || '' === $line) ? false : rtrim($line);
215 public function getProcessIsolation()
217 return $this->processIsolation;
220 public function setProcessIsolation($processIsolation)
222 $this->processIsolation = (bool) $processIsolation;
224 if ($this->processIsolation && !class_exists('Symfony\\Component\\Process\\Process
')) {
225 throw new \RuntimeException('Unable to isolate processes as the Symfony Process Component is not installed.
');