console : manage correctely the window size

console : Add support to Ctrl+L


git-svn-id: https://svn.fournier38.fr/svn/ProgSVN/trunk@4237 bf3deb0d-5f1a-0410-827f-c0cc1f45334c
This commit is contained in:
2018-06-13 10:17:16 +00:00
parent 07e8b0f5c4
commit a6764f2d8f

View File

@@ -13,6 +13,7 @@ class console
{
// PROPERTIES
// {{{
private $usleep = 0;
/** Save the initial stty value
*/
private $initSttyState;
@@ -46,6 +47,14 @@ class console
/** Set the function called when the completion char is called
*/
private $completionFunction = array ();
/** Set the width of the terminal in chars
*/
private $termWidth;
/** Store the last cursor position in the last readline
*/
private $cursorPos = 1;
// }}}
/** The constructor init the console.
@@ -61,6 +70,17 @@ class console
// Do not display anything, so we don't see the characters when the user is
// deleting.
exec ("stty -echo -icanon min 1 time 0");
$termSize = exec ("stty size", $null, $rc);
if ($rc === 0)
{
list ($termHeight, $termWidth) = explode (" ", $termSize);
if (is_null ($termWidth) || is_bool ($termWidth))
$this->termWidth = 80;
else
$this->termWidth = intval ($termWidth);
}
else
$this->termWidth = 80;
}
// }}}
@@ -210,7 +230,7 @@ class console
{
// Gets can not delete chars before the call. Keep the prompt (if exists)
$prompt = $this->lineContent;
$minLength = mb_strlen ($this->lineContent);
$minLength = mb_strlen ($this->lineContent) + 1;
// The cursor position from first char of line.
$cursorPos = $minLength;
// Manage the history and a temporary buffer if the user has already type
@@ -285,7 +305,7 @@ class console
echo "\n".implode ("\n", $completeArr)."\n";
}
}
$cursorPos = mb_strlen ($prompt.$string);
$cursorPos = mb_strlen ($prompt.$string) + 1;
$this->rewriteLine ($prompt.$string);
$this->moveCursor ($cursorPos);
}
@@ -299,6 +319,16 @@ class console
return $string;
}
// }}}
elseif (ord($char) === 12)
// Refresh page (Ctrl+L)
// {{{
{
echo "\033[2J\033[;H";
$cursorPos = mb_strlen ($prompt.$string) + 1;
$this->rewriteLine ($prompt.$string);
$this->moveCursor ($cursorPos);
}
// }}}
elseif (ord($char) === 21)
// Empty line from prompt to cursor (Ctrl+U)
// {{{
@@ -329,11 +359,11 @@ class console
// Remove the previous char (Backspace)
// {{{
{
if ($cursorPos <= $minLength)
if ($cursorPos -1 <= $minLength)
continue;
$cursorPos--;
$strArr = $this->mb_str_split ($string);
unset ($strArr[$cursorPos - $minLength]);
$cursorPos--;
unset ($strArr[$cursorPos - $minLength - 1]);
$string = implode ($strArr);
$this->rewriteLine ($prompt.$string);
$this->moveCursor ($cursorPos);
@@ -356,7 +386,7 @@ class console
if ($pos !== false)
$cursorPos += $pos +1 ;
else
$cursorPos = mb_strlen ($prompt.$string);
$cursorPos = mb_strlen ($prompt.$string) + 1;
$this->moveCursor ($cursorPos);
}
// }}}
@@ -384,7 +414,7 @@ class console
{
$historyPos--;
$string = $this->history[$historyPos];
$cursorPos = mb_strlen ($prompt.$string);
$cursorPos = mb_strlen ($prompt.$string) + 1;
$this->rewriteLine ($prompt.$string);
$this->moveCursor ($cursorPos);
}
@@ -403,7 +433,7 @@ class console
{
$string = $historyTmp;
}
$cursorPos = mb_strlen ($prompt.$string);
$cursorPos = mb_strlen ($prompt.$string) + 1;
$this->rewriteLine ($prompt.$string);
$this->moveCursor ($cursorPos);
}
@@ -412,7 +442,7 @@ class console
// Cursor right
// {{{
{
if ($cursorPos < mb_strlen ($this->lineContent))
if ($cursorPos <= mb_strlen ($this->lineContent))
{
$cursorPos++;
$this->moveCursor ($cursorPos);
@@ -494,23 +524,64 @@ class console
// {{{
{
if ($this->echoMode)
{
// Based on https://stackoverflow.com/a/27850902/158716
$oldLength = mb_strlen ($this->lineContent);
// 1. Calculate on which line the cursor is positionned
$cursorLine = 1 + floor ((-1+$this->cursorPos) / $this->termWidth);
$lastLines = 1 + floor ((1+$oldLength) / $this->termWidth);
for ($i = $cursorLine ; $i < $lastLines ; $i++)
echo "\033[1B";
// 3. Remove the lines from lastLines to line 1
if ($lastLines > 1)
{
for ($i = $lastLines ; $i > 1 ; $i--)
echo "\r\033[K\033[1A\r";
}
// 4. Clean the line 1
echo "\r\033[K";
$this->lineContent = $text;
echo $this->lineContent;
$this->cursorPos = mb_strlen ($this->lineContent);
}
/* if ($this->echoMode)
{
echo "\r".str_repeat (" ", mb_strlen ($this->lineContent))."\r";
$this->lineContent = $text;
echo $this->lineContent;
}
}*/
}
// }}}
/** Move the cursor on position $position
/** Move the cursor on position $position. The first column is $cursorPos=1
* @param integer $cursorPos The new position on line
*/
private function moveCursor ($cursorPos)
// {{{
{
if ($cursorPos < 1)
$this->consoleException ("MoveCursor lesser than one : $cursorPos");
if ($this->echoMode)
{
echo "\r".str_repeat (chr (27).chr (91).chr (67), $cursorPos);
$oldLength = mb_strlen ($this->lineContent);
// 1. Calculate on which line the cursor is positionned
$cursorLine = 1 + floor ((-1+$this->cursorPos) / $this->termWidth);
// 2. Return the cursor to the first line
for ($i = $cursorLine ; $i > 1 ; $i--)
echo chr (27).chr (91).chr (49).chr (65)."\r";
// 3. Down the cursor to the wanted line
$wantedLine = ceil ($cursorPos / $this->termWidth);
if ($wantedLine > 1)
{
for ($i = 1 ; $i < $wantedLine ; $i++)
echo "\r".chr (27).chr (91).chr (49).chr (66)."\r";
}
// 4. Move the cursor on the last line
$needMovePos = -1 + $cursorPos - ($wantedLine - 1) * $this->termWidth;
echo "\r".str_repeat (chr (27).chr (91).chr (67), $needMovePos);
$this->cursorPos = $cursorPos;
// On unique line :
//echo "\r".str_repeat (chr (27).chr (91).chr (67), $cursorPos);
}
}
// }}}
@@ -674,15 +745,28 @@ class console
/** This function return an array with each char, but supports UTF-8
* @param string $string The string to explode
* @param integer $split_length The number of chars in each split
* @return array
*/
private function mb_str_split ($string)
private function mb_str_split ($string, $split_length = 1)
// {{{
{
$res = array();
for ($i = 0; $i < mb_strlen ($string); $i++)
$res[] = mb_substr ($string, $i, 1);
for ($i = 0; $i < mb_strlen ($string); $i += $split_length)
$res[] = mb_substr ($string, $i, $split_length);
return $res;
}
// }}}
/** This function debug the data
* @param mixed $data The data to store
*/
private function debug ($data)
// {{{
{
if (is_array ($data) || is_bool ($data))
$data = var_export ($data, true);
file_put_contents ("/tmp/debug", date ("H:i:s")." $data\n", FILE_APPEND);
}
// }}}
}