protected function runLoop()
    {
        while ($this->isListening) {
            $this->stream->select();

            // special key sequence has started
            if (true === $this->charSequenceEnabled && null !== $this->escapePressedAt) {
                if ($this->escapeKeyHasExpired()) {
                    $this->disableKeySequence();

                    $this->setCurrentKey($this->matcher->getKey($this->matcher->getEscapeKey()));

                    // run key listeners, if one of the key callbacks returns true
                    // break the loop and restore default terminal functionality
                    $this->dispatchKeyPressEvents($this->getCurrentKey());
                }
            }

            // proceed if the stream isn't empty
            if ($this->stream->isAvailable()) {
                $char = $this->stream->getChar();

                // start of the special key sequence
                // mark the sequence start and setup the timer for the escape key
                if ($this->matcher->getEscapeKey() === $char) {
                    $this->enableKeySequence();
                    $this->setCurrentKey($char);
                } else {
                    $this->escapePressedAt = null;

                    if ($this->charSequenceEnabled) {
                        // if special key was pressed, concatenate the current
                        // escape character with the next characters that come
                        // in through the stream
                        $this->concatCurrentKey($char);

                        $mapped = $this->matcher->getKey($this->getCurrentKey());
                        // check and get which arrow key was pressed
                        if ($mapped) {
                            $this->setCurrentKey($mapped);
                            $this->disableKeySequence();
                        } else {
                            // we skip this iteration because the sequence isn't
                            // finished yet and we don't need to run the key
                            // listeners
                            continue;
                        }
                    } else {
                        // something out of basic latin charset so we ignore it
                        if ($this->matcher->isBasicLatin($char)) {
                            continue;
                        } else {
                            // normal keyboard key was pressed
                            $this->setCurrentKey($this->matcher->getKey($char) ?: $char);
                        }
                    }

                    // run key listeners, if one of the key callbacks returns true
                    // break the loop and restore default terminal functionality
                    $this->dispatchKeyPressEvents($this->getCurrentKey());
                }
            }
        }

        return $this;
    }
protected function runLoop()
    {
        while ($this->isListening) {
            $this->stream->select();

            // special key sequence has started
            if (true === $this->charSequenceEnabled && null !== $this->escapePressedAt) {
                if ($this->escapeKeyHasExpired()) {
                    $this->disableKeySequence();

                    $this->setCurrentKey($this->matcher->getKey($this->matcher->getEscapeKey()));

                    // run key listeners, if one of the key callbacks returns true
                    // break the loop and restore default terminal functionality
                    $this->dispatchKeyPressEvents($this->getCurrentKey());
                }
            }

            // proceed if the stream isn't empty
            if ($this->stream->isAvailable()) {
                $char = $this->stream->getChar();

                // start of the special key sequence
                // mark the sequence start and setup the timer for the escape key
                if ($this->matcher->getEscapeKey() === $char) {
                    $this->enableKeySequence();
                    $this->setCurrentKey($char);
                } else {
                    $this->escapePressedAt = null;

                    if ($this->charSequenceEnabled) {
                        // if special key was pressed, concatenate the current
                        // escape character with the next characters that come
                        // in through the stream
                        $this->concatCurrentKey($char);

                        $mapped = $this->matcher->getKey($this->getCurrentKey());
                        // check and get which arrow key was pressed
                        if ($mapped) {
                            $this->setCurrentKey($mapped);
                            $this->disableKeySequence();
                        } else {
                            // we skip this iteration because the sequence isn't
                            // finished yet and we don't need to run the key
                            // listeners
                            continue;
                        }
                    } else {
                        // something out of basic latin charset so we ignore it
                        if ($this->matcher->isBasicLatin($char)) {
                            continue;
                        } else {
                            // normal keyboard key was pressed
                            $this->setCurrentKey($this->matcher->getKey($char) ?: $char);
                        }
                    }

                    // run key listeners, if one of the key callbacks returns true
                    // break the loop and restore default terminal functionality
                    $this->dispatchKeyPressEvents($this->getCurrentKey());
                }
            }
        }

        return $this;
    }
protected function runLoop ( ) { while ( $ this -> isListening ) { $ this -> stream -> select ( ) ; // special key sequence has started if ( true === $ this -> charSequenceEnabled && null !== $ this -> escapePressedAt ) { if ( $ this -> escapeKeyHasExpired ( ) ) { $ this -> disableKeySequence ( ) ; $ this -> setCurrentKey ( $ this -> matcher -> getKey ( $ this -> matcher -> getEscapeKey ( ) ) ) ; // run key listeners, if one of the key callbacks returns true // break the loop and restore default terminal functionality $ this -> dispatchKeyPressEvents ( $ this -> getCurrentKey ( ) ) ; } } // proceed if the stream isn't empty if ( $ this -> stream -> isAvailable ( ) ) { $ char = $ this -> stream -> getChar ( ) ; // start of the special key sequence // mark the sequence start and setup the timer for the escape key if ( $ this -> matcher -> getEscapeKey ( ) === $ char ) { $ this -> enableKeySequence ( ) ; $ this -> setCurrentKey ( $ char ) ; } else { $ this -> escapePressedAt = null ; if ( $ this -> charSequenceEnabled ) { // if special key was pressed, concatenate the current // escape character with the next characters that come // in through the stream $ this -> concatCurrentKey ( $ char ) ; $ mapped = $ this -> matcher -> getKey ( $ this -> getCurrentKey ( ) ) ; // check and get which arrow key was pressed if ( $ mapped ) { $ this -> setCurrentKey ( $ mapped ) ; $ this -> disableKeySequence ( ) ; } else { // we skip this iteration because the sequence isn't // finished yet and we don't need to run the key // listeners continue ; } } else { // something out of basic latin charset so we ignore it if ( $ this -> matcher -> isBasicLatin ( $ char ) ) { continue ; } else { // normal keyboard key was pressed $ this -> setCurrentKey ( $ this -> matcher -> getKey ( $ char ) ? : $ char ) ; } } // run key listeners, if one of the key callbacks returns true // break the loop and restore default terminal functionality $ this -> dispatchKeyPressEvents ( $ this -> getCurrentKey ( ) ) ; } } } return $ this ; }
Starts capturing keys

Reads every single character in STDIN one by one
and figures out which keys were pressed

Supports special keys such as arrows, function keys etc.
by combining separate characters into unicode characters

@todo add multi-language support
or not since even js doesn't support it(?)
'/[\x00-\x7F]/' basic latin range including special keys

@return $this
Starts capturing keys