4 * This file is part of Psy Shell.
6 * (c) 2012-2017 Justin Hileman
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
14 use Psy\Exception\RuntimeException;
15 use Symfony\Component\Console\Input\InputInterface;
16 use Symfony\Component\Console\Input\InputOption;
19 * Parse, validate and match --grep, --insensitive and --invert command options.
23 private $filter = false;
29 * Get input option definitions for filtering.
31 * @return InputOption[]
33 public static function getOptions()
36 new InputOption('grep', 'G', InputOption::VALUE_REQUIRED, 'Limit to items matching the given pattern (string or regex).'),
37 new InputOption('insensitive', 'i', InputOption::VALUE_NONE, 'Case-insensitive search (requires --grep).'),
38 new InputOption('invert', 'v', InputOption::VALUE_NONE, 'Inverted search (requires --grep).'),
43 * Bind input and prepare filter.
45 * @param InputInterface $input
47 public function bind(InputInterface $input)
49 $this->validateInput($input);
51 if (!$pattern = $input->getOption('grep')) {
52 $this->filter = false;
57 if (!$this->stringIsRegex($pattern)) {
58 $pattern = '/' . preg_quote($pattern, '/') . '/';
61 if ($insensitive = $input->getOption('insensitive')) {
65 $this->validateRegex($pattern);
68 $this->pattern = $pattern;
69 $this->insensitive = $insensitive;
70 $this->invert = $input->getOption('invert');
74 * Check whether the bound input has filter options.
78 public function hasFilter()
84 * Check whether a string matches the current filter options.
86 * @param string $string
87 * @param array $matches
91 public function match($string, array &$matches = null)
93 return $this->filter === false || (preg_match($this->pattern, $string, $matches) xor $this->invert);
97 * Validate that grep, invert and insensitive input options are consistent.
99 * @param InputInterface $input
103 private function validateInput(InputInterface $input)
105 if (!$input->getOption('grep')) {
106 foreach (array('invert', 'insensitive') as $option) {
107 if ($input->getOption($option)) {
108 throw new RuntimeException('--' . $option . ' does not make sense without --grep');
115 * Check whether a string appears to be a regular expression.
117 * @param string $string
121 private function stringIsRegex($string)
123 return substr($string, 0, 1) === '/' && substr($string, -1) === '/' && strlen($string) >= 3;
127 * Validate that $pattern is a valid regular expression.
129 * @param string $pattern
133 private function validateRegex($pattern)
135 set_error_handler(array('Psy\Exception\ErrorException', 'throwException'));
137 preg_match($pattern, '');
138 } catch (ErrorException $e) {
139 throw new RuntimeException(str_replace('preg_match(): ', 'Invalid regular expression: ', $e->getRawMessage()));
141 restore_error_handler();