[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/vendor/symfony/console/Completion/ -> CompletionInput.php (source)

   1  <?php
   2  
   3  /*
   4   * This file is part of the Symfony package.
   5   *
   6   * (c) Fabien Potencier <[email protected]>
   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\Completion;
  13  
  14  use Symfony\Component\Console\Exception\RuntimeException;
  15  use Symfony\Component\Console\Input\ArgvInput;
  16  use Symfony\Component\Console\Input\InputDefinition;
  17  use Symfony\Component\Console\Input\InputOption;
  18  
  19  /**
  20   * An input specialized for shell completion.
  21   *
  22   * This input allows unfinished option names or values and exposes what kind of
  23   * completion is expected.
  24   *
  25   * @author Wouter de Jong <[email protected]>
  26   */
  27  final class CompletionInput extends ArgvInput
  28  {
  29      public const TYPE_ARGUMENT_VALUE = 'argument_value';
  30      public const TYPE_OPTION_VALUE = 'option_value';
  31      public const TYPE_OPTION_NAME = 'option_name';
  32      public const TYPE_NONE = 'none';
  33  
  34      private $tokens;
  35      private $currentIndex;
  36      private $completionType;
  37      private $completionName = null;
  38      private $completionValue = '';
  39  
  40      /**
  41       * Converts a terminal string into tokens.
  42       *
  43       * This is required for shell completions without COMP_WORDS support.
  44       */
  45      public static function fromString(string $inputStr, int $currentIndex): self
  46      {
  47          preg_match_all('/(?<=^|\s)([\'"]?)(.+?)(?<!\\\\)\1(?=$|\s)/', $inputStr, $tokens);
  48  
  49          return self::fromTokens($tokens[0], $currentIndex);
  50      }
  51  
  52      /**
  53       * Create an input based on an COMP_WORDS token list.
  54       *
  55       * @param string[] $tokens       the set of split tokens (e.g. COMP_WORDS or argv)
  56       * @param          $currentIndex the index of the cursor (e.g. COMP_CWORD)
  57       */
  58      public static function fromTokens(array $tokens, int $currentIndex): self
  59      {
  60          $input = new self($tokens);
  61          $input->tokens = $tokens;
  62          $input->currentIndex = $currentIndex;
  63  
  64          return $input;
  65      }
  66  
  67      /**
  68       * {@inheritdoc}
  69       */
  70      public function bind(InputDefinition $definition): void
  71      {
  72          parent::bind($definition);
  73  
  74          $relevantToken = $this->getRelevantToken();
  75          if ('-' === $relevantToken[0]) {
  76              // the current token is an input option: complete either option name or option value
  77              [$optionToken, $optionValue] = explode('=', $relevantToken, 2) + ['', ''];
  78  
  79              $option = $this->getOptionFromToken($optionToken);
  80              if (null === $option && !$this->isCursorFree()) {
  81                  $this->completionType = self::TYPE_OPTION_NAME;
  82                  $this->completionValue = $relevantToken;
  83  
  84                  return;
  85              }
  86  
  87              if (null !== $option && $option->acceptValue()) {
  88                  $this->completionType = self::TYPE_OPTION_VALUE;
  89                  $this->completionName = $option->getName();
  90                  $this->completionValue = $optionValue ?: (!str_starts_with($optionToken, '--') ? substr($optionToken, 2) : '');
  91  
  92                  return;
  93              }
  94          }
  95  
  96          $previousToken = $this->tokens[$this->currentIndex - 1];
  97          if ('-' === $previousToken[0] && '' !== trim($previousToken, '-')) {
  98              // check if previous option accepted a value
  99              $previousOption = $this->getOptionFromToken($previousToken);
 100              if (null !== $previousOption && $previousOption->acceptValue()) {
 101                  $this->completionType = self::TYPE_OPTION_VALUE;
 102                  $this->completionName = $previousOption->getName();
 103                  $this->completionValue = $relevantToken;
 104  
 105                  return;
 106              }
 107          }
 108  
 109          // complete argument value
 110          $this->completionType = self::TYPE_ARGUMENT_VALUE;
 111  
 112          foreach ($this->definition->getArguments() as $argumentName => $argument) {
 113              if (!isset($this->arguments[$argumentName])) {
 114                  break;
 115              }
 116  
 117              $argumentValue = $this->arguments[$argumentName];
 118              $this->completionName = $argumentName;
 119              if (\is_array($argumentValue)) {
 120                  $this->completionValue = $argumentValue ? $argumentValue[array_key_last($argumentValue)] : null;
 121              } else {
 122                  $this->completionValue = $argumentValue;
 123              }
 124          }
 125  
 126          if ($this->currentIndex >= \count($this->tokens)) {
 127              if (!isset($this->arguments[$argumentName]) || $this->definition->getArgument($argumentName)->isArray()) {
 128                  $this->completionName = $argumentName;
 129                  $this->completionValue = '';
 130              } else {
 131                  // we've reached the end
 132                  $this->completionType = self::TYPE_NONE;
 133                  $this->completionName = null;
 134                  $this->completionValue = '';
 135              }
 136          }
 137      }
 138  
 139      /**
 140       * Returns the type of completion required.
 141       *
 142       * TYPE_ARGUMENT_VALUE when completing the value of an input argument
 143       * TYPE_OPTION_VALUE   when completing the value of an input option
 144       * TYPE_OPTION_NAME    when completing the name of an input option
 145       * TYPE_NONE           when nothing should be completed
 146       *
 147       * @return string One of self::TYPE_* constants. TYPE_OPTION_NAME and TYPE_NONE are already implemented by the Console component
 148       */
 149      public function getCompletionType(): string
 150      {
 151          return $this->completionType;
 152      }
 153  
 154      /**
 155       * The name of the input option or argument when completing a value.
 156       *
 157       * @return string|null returns null when completing an option name
 158       */
 159      public function getCompletionName(): ?string
 160      {
 161          return $this->completionName;
 162      }
 163  
 164      /**
 165       * The value already typed by the user (or empty string).
 166       */
 167      public function getCompletionValue(): string
 168      {
 169          return $this->completionValue;
 170      }
 171  
 172      public function mustSuggestOptionValuesFor(string $optionName): bool
 173      {
 174          return self::TYPE_OPTION_VALUE === $this->getCompletionType() && $optionName === $this->getCompletionName();
 175      }
 176  
 177      public function mustSuggestArgumentValuesFor(string $argumentName): bool
 178      {
 179          return self::TYPE_ARGUMENT_VALUE === $this->getCompletionType() && $argumentName === $this->getCompletionName();
 180      }
 181  
 182      protected function parseToken(string $token, bool $parseOptions): bool
 183      {
 184          try {
 185              return parent::parseToken($token, $parseOptions);
 186          } catch (RuntimeException $e) {
 187              // suppress errors, completed input is almost never valid
 188          }
 189  
 190          return $parseOptions;
 191      }
 192  
 193      private function getOptionFromToken(string $optionToken): ?InputOption
 194      {
 195          $optionName = ltrim($optionToken, '-');
 196          if (!$optionName) {
 197              return null;
 198          }
 199  
 200          if ('-' === ($optionToken[1] ?? ' ')) {
 201              // long option name
 202              return $this->definition->hasOption($optionName) ? $this->definition->getOption($optionName) : null;
 203          }
 204  
 205          // short option name
 206          return $this->definition->hasShortcut($optionName[0]) ? $this->definition->getOptionForShortcut($optionName[0]) : null;
 207      }
 208  
 209      /**
 210       * The token of the cursor, or the last token if the cursor is at the end of the input.
 211       */
 212      private function getRelevantToken(): string
 213      {
 214          return $this->tokens[$this->isCursorFree() ? $this->currentIndex - 1 : $this->currentIndex];
 215      }
 216  
 217      /**
 218       * Whether the cursor is "free" (i.e. at the end of the input preceded by a space).
 219       */
 220      private function isCursorFree(): bool
 221      {
 222          $nrOfTokens = \count($this->tokens);
 223          if ($this->currentIndex > $nrOfTokens) {
 224              throw new \LogicException('Current index is invalid, it must be the number of input tokens or one more.');
 225          }
 226  
 227          return $this->currentIndex >= $nrOfTokens;
 228      }
 229  
 230      public function __toString()
 231      {
 232          $str = '';
 233          foreach ($this->tokens as $i => $token) {
 234              $str .= $token;
 235  
 236              if ($this->currentIndex === $i) {
 237                  $str .= '|';
 238              }
 239  
 240              $str .= ' ';
 241          }
 242  
 243          if ($this->currentIndex > $i) {
 244              $str .= '|';
 245          }
 246  
 247          return rtrim($str);
 248      }
 249  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer