Version 1
[yaffs-website] / vendor / stecman / symfony-console-completion / src / CompletionContext.php
diff --git a/vendor/stecman/symfony-console-completion/src/CompletionContext.php b/vendor/stecman/symfony-console-completion/src/CompletionContext.php
new file mode 100644 (file)
index 0000000..6029253
--- /dev/null
@@ -0,0 +1,256 @@
+<?php
+
+
+namespace Stecman\Component\Symfony\Console\BashCompletion;
+
+/**
+ * Command line context for completion
+ *
+ * Represents the current state of the command line that is being completed
+ */
+class CompletionContext
+{
+    /**
+     * The current contents of the command line as a single string
+     *
+     * Bash equivalent: COMP_LINE
+     *
+     * @var string
+     */
+    protected $commandLine;
+
+    /**
+     * The index of the user's cursor relative to the start of the command line.
+     *
+     * If the current cursor position is at the end of the current command,
+     * the value of this variable is equal to the length of $this->commandLine
+     *
+     * Bash equivalent: COMP_POINT
+     *
+     * @var int
+     */
+    protected $charIndex = 0;
+
+    /**
+     * An array containing the individual words in the current command line.
+     *
+     * This is not set until $this->splitCommand() is called, when it is populated by
+     * $commandLine exploded by $wordBreaks
+     *
+     * Bash equivalent: COMP_WORDS
+     *
+     * @var array|null
+     */
+    protected $words = null;
+
+    /**
+     * The index in $this->words containing the word at the current cursor position.
+     *
+     * This is not set until $this->splitCommand() is called.
+     *
+     * Bash equivalent: COMP_CWORD
+     *
+     * @var int|null
+     */
+    protected $wordIndex = null;
+
+    /**
+     * Characters that $this->commandLine should be split on to get a list of individual words
+     *
+     * Bash equivalent: COMP_WORDBREAKS
+     *
+     * @var string
+     */
+    protected $wordBreaks = "'\"()= \t\n";
+
+    /**
+     * Set the whole contents of the command line as a string
+     *
+     * @param string $commandLine
+     */
+    public function setCommandLine($commandLine)
+    {
+        $this->commandLine = $commandLine;
+        $this->reset();
+    }
+
+    /**
+     * Return the current command line verbatim as a string
+     *
+     * @return string
+     */
+    public function getCommandLine()
+    {
+        return $this->commandLine;
+    }
+
+    /**
+     * Return the word from the command line that the cursor is currently in
+     *
+     * Most of the time this will be a partial word. If the cursor has a space before it,
+     * this will return an empty string, indicating a new word.
+     *
+     * @return string
+     */
+    public function getCurrentWord()
+    {
+        if (isset($this->words[$this->wordIndex])) {
+            return $this->words[$this->wordIndex];
+        }
+
+        return '';
+    }
+
+    /**
+     * Return a word by index from the command line
+     *
+     * @see $words, $wordBreaks
+     * @param int $index
+     * @return string
+     */
+    public function getWordAtIndex($index)
+    {
+        if (isset($this->words[$index])) {
+            return $this->words[$index];
+        }
+
+        return '';
+    }
+
+    /**
+     * Get the contents of the command line, exploded into words based on the configured word break characters
+     *
+     * @see $wordBreaks, setWordBreaks
+     * @return array
+     */
+    public function getWords()
+    {
+        if ($this->words === null) {
+            $this->splitCommand();
+        }
+
+        return $this->words;
+    }
+
+    /**
+     * Get the index of the word the cursor is currently in
+     *
+     * @see getWords, getCurrentWord
+     * @return int
+     */
+    public function getWordIndex()
+    {
+        if ($this->wordIndex === null) {
+            $this->splitCommand();
+        }
+
+        return $this->wordIndex;
+    }
+
+    /**
+     * Get the character index of the user's cursor on the command line
+     *
+     * This is in the context of the full command line string, so includes word break characters.
+     * Note that some shells can only provide an approximation for character index. Under ZSH for
+     * example, this will always be the character at the start of the current word.
+     *
+     * @return int
+     */
+    public function getCharIndex()
+    {
+        return $this->charIndex;
+    }
+
+    /**
+     * Set the cursor position as a character index relative to the start of the command line
+     *
+     * @param int $index
+     */
+    public function setCharIndex($index)
+    {
+        $this->charIndex = $index;
+        $this->reset();
+    }
+
+    /**
+     * Set characters to use as split points when breaking the command line into words
+     *
+     * This defaults to a sane value based on BASH's word break characters and shouldn't
+     * need to be changed unless your completions contain the default word break characters.
+     *
+     * @see wordBreaks
+     * @param string $charList - a single string containing all of the characters to break words on
+     */
+    public function setWordBreaks($charList)
+    {
+        $this->wordBreaks = $charList;
+        $this->reset();
+    }
+
+    /**
+     * Split the command line into words using the configured word break characters
+     *
+     * @return string[]
+     */
+    protected function splitCommand()
+    {
+        $this->words = array();
+        $this->wordIndex = null;
+        $cursor = 0;
+
+        $breaks = preg_quote($this->wordBreaks);
+
+        if (!preg_match_all("/([^$breaks]*)([$breaks]*)/", $this->commandLine, $matches)) {
+            return;
+        }
+
+        // Groups:
+        // 1: Word
+        // 2: Break characters
+        foreach ($matches[0] as $index => $wholeMatch) {
+            // Determine which word the cursor is in
+            $cursor += strlen($wholeMatch);
+            $word = $matches[1][$index];
+            $breaks = $matches[2][$index];
+
+            if ($this->wordIndex === null && $cursor >= $this->charIndex) {
+                $this->wordIndex = $index;
+
+                // Find the user's cursor position relative to the end of this word
+                // The end of the word is the internal cursor minus any break characters that were captured
+                $cursorWordOffset = $this->charIndex - ($cursor - strlen($breaks));
+
+                if ($cursorWordOffset < 0) {
+                    // Cursor is inside the word - truncate the word at the cursor
+                    // (This emulates normal BASH completion behaviour I've observed, though I'm not entirely sure if it's useful)
+                    $word = substr($word, 0, strlen($word) + $cursorWordOffset);
+
+                } elseif ($cursorWordOffset > 0) {
+                    // Cursor is in the break-space after a word
+                    // Push an empty word at the cursor to allow completion of new terms at the cursor, ignoring words ahead
+                    $this->wordIndex++;
+                    $this->words[] = $word;
+                    $this->words[] = '';
+                    continue;
+                }
+            }
+
+            if ($word !== '') {
+                $this->words[] = $word;
+            }
+        }
+
+        if ($this->wordIndex > count($this->words) - 1) {
+            $this->wordIndex = count($this->words) - 1;
+        }
+    }
+
+    /**
+     * Reset the computed words so that $this->splitWords is forced to run again
+     */
+    protected function reset()
+    {
+        $this->words = null;
+        $this->wordIndex = null;
+    }
+}