Chris@13
|
1 <?php
|
Chris@13
|
2
|
Chris@13
|
3 /*
|
Chris@13
|
4 * This file is part of Psy Shell.
|
Chris@13
|
5 *
|
Chris@13
|
6 * (c) 2012-2018 Justin Hileman
|
Chris@13
|
7 *
|
Chris@13
|
8 * For the full copyright and license information, please view the LICENSE
|
Chris@13
|
9 * file that was distributed with this source code.
|
Chris@13
|
10 */
|
Chris@13
|
11
|
Chris@13
|
12 namespace Psy\Command;
|
Chris@13
|
13
|
Chris@13
|
14 use Psy\Context;
|
Chris@13
|
15 use Psy\ContextAware;
|
Chris@13
|
16 use Psy\Input\FilterOptions;
|
Chris@13
|
17 use Psy\Output\ShellOutput;
|
Chris@13
|
18 use Symfony\Component\Console\Input\InputArgument;
|
Chris@13
|
19 use Symfony\Component\Console\Input\InputInterface;
|
Chris@13
|
20 use Symfony\Component\Console\Input\InputOption;
|
Chris@13
|
21 use Symfony\Component\Console\Output\OutputInterface;
|
Chris@13
|
22
|
Chris@13
|
23 /**
|
Chris@13
|
24 * Show the last uncaught exception.
|
Chris@13
|
25 */
|
Chris@13
|
26 class WtfCommand extends TraceCommand implements ContextAware
|
Chris@13
|
27 {
|
Chris@13
|
28 /**
|
Chris@13
|
29 * Context instance (for ContextAware interface).
|
Chris@13
|
30 *
|
Chris@13
|
31 * @var Context
|
Chris@13
|
32 */
|
Chris@13
|
33 protected $context;
|
Chris@13
|
34
|
Chris@13
|
35 /**
|
Chris@13
|
36 * ContextAware interface.
|
Chris@13
|
37 *
|
Chris@13
|
38 * @param Context $context
|
Chris@13
|
39 */
|
Chris@13
|
40 public function setContext(Context $context)
|
Chris@13
|
41 {
|
Chris@13
|
42 $this->context = $context;
|
Chris@13
|
43 }
|
Chris@13
|
44
|
Chris@13
|
45 /**
|
Chris@13
|
46 * {@inheritdoc}
|
Chris@13
|
47 */
|
Chris@13
|
48 protected function configure()
|
Chris@13
|
49 {
|
Chris@13
|
50 list($grep, $insensitive, $invert) = FilterOptions::getOptions();
|
Chris@13
|
51
|
Chris@13
|
52 $this
|
Chris@13
|
53 ->setName('wtf')
|
Chris@13
|
54 ->setAliases(['last-exception', 'wtf?'])
|
Chris@13
|
55 ->setDefinition([
|
Chris@13
|
56 new InputArgument('incredulity', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, 'Number of lines to show.'),
|
Chris@13
|
57 new InputOption('all', 'a', InputOption::VALUE_NONE, 'Show entire backtrace.'),
|
Chris@13
|
58
|
Chris@13
|
59 $grep,
|
Chris@13
|
60 $insensitive,
|
Chris@13
|
61 $invert,
|
Chris@13
|
62 ])
|
Chris@13
|
63 ->setDescription('Show the backtrace of the most recent exception.')
|
Chris@13
|
64 ->setHelp(
|
Chris@13
|
65 <<<'HELP'
|
Chris@13
|
66 Shows a few lines of the backtrace of the most recent exception.
|
Chris@13
|
67
|
Chris@13
|
68 If you want to see more lines, add more question marks or exclamation marks:
|
Chris@13
|
69
|
Chris@13
|
70 e.g.
|
Chris@13
|
71 <return>>>> wtf ?</return>
|
Chris@13
|
72 <return>>>> wtf ?!???!?!?</return>
|
Chris@13
|
73
|
Chris@13
|
74 To see the entire backtrace, pass the -a/--all flag:
|
Chris@13
|
75
|
Chris@13
|
76 e.g.
|
Chris@13
|
77 <return>>>> wtf -a</return>
|
Chris@13
|
78 HELP
|
Chris@13
|
79 );
|
Chris@13
|
80 }
|
Chris@13
|
81
|
Chris@13
|
82 /**
|
Chris@13
|
83 * {@inheritdoc}
|
Chris@13
|
84 */
|
Chris@13
|
85 protected function execute(InputInterface $input, OutputInterface $output)
|
Chris@13
|
86 {
|
Chris@13
|
87 $this->filter->bind($input);
|
Chris@13
|
88
|
Chris@17
|
89 $incredulity = \implode('', $input->getArgument('incredulity'));
|
Chris@17
|
90 if (\strlen(\preg_replace('/[\\?!]/', '', $incredulity))) {
|
Chris@13
|
91 throw new \InvalidArgumentException('Incredulity must include only "?" and "!"');
|
Chris@13
|
92 }
|
Chris@13
|
93
|
Chris@13
|
94 $exception = $this->context->getLastException();
|
Chris@17
|
95 $count = $input->getOption('all') ? PHP_INT_MAX : \max(3, \pow(2, \strlen($incredulity) + 1));
|
Chris@13
|
96
|
Chris@13
|
97 $shell = $this->getApplication();
|
Chris@13
|
98 $output->startPaging();
|
Chris@13
|
99 do {
|
Chris@17
|
100 $traceCount = \count($exception->getTrace());
|
Chris@13
|
101 $showLines = $count;
|
Chris@13
|
102 // Show the whole trace if we'd only be hiding a few lines
|
Chris@17
|
103 if ($traceCount < \max($count * 1.2, $count + 2)) {
|
Chris@13
|
104 $showLines = PHP_INT_MAX;
|
Chris@13
|
105 }
|
Chris@13
|
106
|
Chris@13
|
107 $trace = $this->getBacktrace($exception, $showLines);
|
Chris@17
|
108 $moreLines = $traceCount - \count($trace);
|
Chris@13
|
109
|
Chris@13
|
110 $output->writeln($shell->formatException($exception));
|
Chris@13
|
111 $output->writeln('--');
|
Chris@13
|
112 $output->write($trace, true, ShellOutput::NUMBER_LINES);
|
Chris@13
|
113 $output->writeln('');
|
Chris@13
|
114
|
Chris@13
|
115 if ($moreLines > 0) {
|
Chris@17
|
116 $output->writeln(\sprintf(
|
Chris@13
|
117 '<aside>Use <return>wtf -a</return> to see %d more lines</aside>',
|
Chris@13
|
118 $moreLines
|
Chris@13
|
119 ));
|
Chris@13
|
120 $output->writeln('');
|
Chris@13
|
121 }
|
Chris@13
|
122 } while ($exception = $exception->getPrevious());
|
Chris@13
|
123 $output->stopPaging();
|
Chris@13
|
124 }
|
Chris@13
|
125 }
|