Файл: vendor/psy/psysh/src/Readline/Hoa/Readline.php
Строк: 853
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
namespace PsyReadlineHoa;
/**
* Class HoaConsoleReadline.
*
* Read, edit, bind… a line from the input.
*/
class Readline
{
/**
* State: continue to read.
*/
const STATE_CONTINUE = 1;
/**
* State: stop to read.
*/
const STATE_BREAK = 2;
/**
* State: no output the current buffer.
*/
const STATE_NO_ECHO = 4;
/**
* Current editing line.
*/
protected $_line = null;
/**
* Current editing line seek.
*/
protected $_lineCurrent = 0;
/**
* Current editing line length.
*/
protected $_lineLength = 0;
/**
* Current buffer (most of the time, a char).
*/
protected $_buffer = null;
/**
* Mapping.
*/
protected $_mapping = [];
/**
* History.
*/
protected $_history = [];
/**
* History current position.
*/
protected $_historyCurrent = 0;
/**
* History size.
*/
protected $_historySize = 0;
/**
* Prefix.
*/
protected $_prefix = null;
/**
* Autocompleter.
*/
protected $_autocompleter = null;
/**
* Initialize the readline editor.
*/
public function __construct()
{
if (defined('PHP_WINDOWS_VERSION_PLATFORM')) {
return;
}
$this->_mapping[" 33[A"] = [$this, '_bindArrowUp'];
$this->_mapping[" 33[B"] = [$this, '_bindArrowDown'];
$this->_mapping[" 33[C"] = [$this, '_bindArrowRight'];
$this->_mapping[" 33[D"] = [$this, '_bindArrowLeft'];
$this->_mapping[" 01"] = [$this, '_bindControlA'];
$this->_mapping[" 02"] = [$this, '_bindControlB'];
$this->_mapping[" 05"] = [$this, '_bindControlE'];
$this->_mapping[" 06"] = [$this, '_bindControlF'];
$this->_mapping[" 10"] =
$this->_mapping["177"] = [$this, '_bindBackspace'];
$this->_mapping[" 27"] = [$this, '_bindControlW'];
$this->_mapping["n"] = [$this, '_bindNewline'];
$this->_mapping["t"] = [$this, '_bindTab'];
return;
}
/**
* Read a line from the input.
*/
public function readLine(string $prefix = null)
{
$input = Console::getInput();
if (true === $input->eof()) {
return false;
}
$direct = Console::isDirect($input->getStream()->getStream());
$output = Console::getOutput();
if (false === $direct || defined('PHP_WINDOWS_VERSION_PLATFORM')) {
$out = $input->readLine();
if (false === $out) {
return false;
}
$out = substr($out, 0, -1);
if (true === $direct) {
$output->writeAll($prefix);
} else {
$output->writeAll($prefix.$out."n");
}
return $out;
}
$this->resetLine();
$this->setPrefix($prefix);
$read = [$input->getStream()->getStream()];
$write = $except = [];
$output->writeAll($prefix);
while (true) {
@stream_select($read, $write, $except, 30, 0);
if (empty($read)) {
$read = [$input->getStream()->getStream()];
continue;
}
$char = $this->_read();
$this->_buffer = $char;
$return = $this->_readLine($char);
if (0 === ($return & self::STATE_NO_ECHO)) {
$output->writeAll($this->_buffer);
}
if (0 !== ($return & self::STATE_BREAK)) {
break;
}
}
return $this->getLine();
}
/**
* Readline core.
*/
public function _readLine(string $char)
{
if (isset($this->_mapping[$char]) &&
is_callable($this->_mapping[$char])) {
$mapping = $this->_mapping[$char];
return $mapping($this);
}
if (isset($this->_mapping[$char])) {
$this->_buffer = $this->_mapping[$char];
} elseif (false === Ustring::isCharPrintable($char)) {
ConsoleCursor::bip();
return static::STATE_CONTINUE | static::STATE_NO_ECHO;
}
if ($this->getLineLength() === $this->getLineCurrent()) {
$this->appendLine($this->_buffer);
return static::STATE_CONTINUE;
}
$this->insertLine($this->_buffer);
$tail = mb_substr(
$this->getLine(),
$this->getLineCurrent() - 1
);
$this->_buffer = " 33[K".$tail.str_repeat(
" 33[D",
mb_strlen($tail) - 1
);
return static::STATE_CONTINUE;
}
/**
* Add mappings.
*/
public function addMappings(array $mappings)
{
foreach ($mappings as $key => $mapping) {
$this->addMapping($key, $mapping);
}
}
/**
* Add a mapping.
* Supported key:
* • e[… for