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:
114
console.php
114
console.php
@@ -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);
|
||||
}
|
||||
// }}}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user