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 // PROPERTIES
// {{{ // {{{
private $usleep = 0;
/** Save the initial stty value /** Save the initial stty value
*/ */
private $initSttyState; private $initSttyState;
@@ -46,6 +47,14 @@ class console
/** Set the function called when the completion char is called /** Set the function called when the completion char is called
*/ */
private $completionFunction = array (); 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. /** 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 // Do not display anything, so we don't see the characters when the user is
// deleting. // deleting.
exec ("stty -echo -icanon min 1 time 0"); 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) // Gets can not delete chars before the call. Keep the prompt (if exists)
$prompt = $this->lineContent; $prompt = $this->lineContent;
$minLength = mb_strlen ($this->lineContent); $minLength = mb_strlen ($this->lineContent) + 1;
// The cursor position from first char of line. // The cursor position from first char of line.
$cursorPos = $minLength; $cursorPos = $minLength;
// Manage the history and a temporary buffer if the user has already type // 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"; echo "\n".implode ("\n", $completeArr)."\n";
} }
} }
$cursorPos = mb_strlen ($prompt.$string); $cursorPos = mb_strlen ($prompt.$string) + 1;
$this->rewriteLine ($prompt.$string); $this->rewriteLine ($prompt.$string);
$this->moveCursor ($cursorPos); $this->moveCursor ($cursorPos);
} }
@@ -299,6 +319,16 @@ class console
return $string; 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) elseif (ord($char) === 21)
// Empty line from prompt to cursor (Ctrl+U) // Empty line from prompt to cursor (Ctrl+U)
// {{{ // {{{
@@ -329,11 +359,11 @@ class console
// Remove the previous char (Backspace) // Remove the previous char (Backspace)
// {{{ // {{{
{ {
if ($cursorPos <= $minLength) if ($cursorPos -1 <= $minLength)
continue; continue;
$cursorPos--;
$strArr = $this->mb_str_split ($string); $strArr = $this->mb_str_split ($string);
unset ($strArr[$cursorPos - $minLength]); $cursorPos--;
unset ($strArr[$cursorPos - $minLength - 1]);
$string = implode ($strArr); $string = implode ($strArr);
$this->rewriteLine ($prompt.$string); $this->rewriteLine ($prompt.$string);
$this->moveCursor ($cursorPos); $this->moveCursor ($cursorPos);
@@ -356,7 +386,7 @@ class console
if ($pos !== false) if ($pos !== false)
$cursorPos += $pos +1 ; $cursorPos += $pos +1 ;
else else
$cursorPos = mb_strlen ($prompt.$string); $cursorPos = mb_strlen ($prompt.$string) + 1;
$this->moveCursor ($cursorPos); $this->moveCursor ($cursorPos);
} }
// }}} // }}}
@@ -384,7 +414,7 @@ class console
{ {
$historyPos--; $historyPos--;
$string = $this->history[$historyPos]; $string = $this->history[$historyPos];
$cursorPos = mb_strlen ($prompt.$string); $cursorPos = mb_strlen ($prompt.$string) + 1;
$this->rewriteLine ($prompt.$string); $this->rewriteLine ($prompt.$string);
$this->moveCursor ($cursorPos); $this->moveCursor ($cursorPos);
} }
@@ -403,7 +433,7 @@ class console
{ {
$string = $historyTmp; $string = $historyTmp;
} }
$cursorPos = mb_strlen ($prompt.$string); $cursorPos = mb_strlen ($prompt.$string) + 1;
$this->rewriteLine ($prompt.$string); $this->rewriteLine ($prompt.$string);
$this->moveCursor ($cursorPos); $this->moveCursor ($cursorPos);
} }
@@ -412,7 +442,7 @@ class console
// Cursor right // Cursor right
// {{{ // {{{
{ {
if ($cursorPos < mb_strlen ($this->lineContent)) if ($cursorPos <= mb_strlen ($this->lineContent))
{ {
$cursorPos++; $cursorPos++;
$this->moveCursor ($cursorPos); $this->moveCursor ($cursorPos);
@@ -494,23 +524,64 @@ class console
// {{{ // {{{
{ {
if ($this->echoMode) 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"; echo "\r".str_repeat (" ", mb_strlen ($this->lineContent))."\r";
$this->lineContent = $text; $this->lineContent = $text;
echo $this->lineContent; 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 * @param integer $cursorPos The new position on line
*/ */
private function moveCursor ($cursorPos) private function moveCursor ($cursorPos)
// {{{ // {{{
{ {
if ($cursorPos < 1)
$this->consoleException ("MoveCursor lesser than one : $cursorPos");
if ($this->echoMode) 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 /** This function return an array with each char, but supports UTF-8
* @param string $string The string to explode * @param string $string The string to explode
* @param integer $split_length The number of chars in each split
* @return array * @return array
*/ */
private function mb_str_split ($string) private function mb_str_split ($string, $split_length = 1)
// {{{ // {{{
{ {
$res = array(); $res = array();
for ($i = 0; $i < mb_strlen ($string); $i++) for ($i = 0; $i < mb_strlen ($string); $i += $split_length)
$res[] = mb_substr ($string, $i, 1); $res[] = mb_substr ($string, $i, $split_length);
return $res; 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);
}
// }}}
} }