Much awesome, very Wow!
* Import native PHP code as callable functions (load) * Include other scripts (include) * Multitude of fixes
This commit is contained in:
parent
a7278bd50a
commit
e23559fd72
16
examples/boxdraw.ftm
Normal file
16
examples/boxdraw.ftm
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
set terminal 80x25
|
||||||
|
|
||||||
|
load boxdraw.php
|
||||||
|
|
||||||
|
writefile boxdraw.ftm
|
||||||
|
|
||||||
|
drawhline 5 0 70
|
||||||
|
drawvline 5 0 5
|
||||||
|
|
||||||
|
drawbox 22 3 40 14
|
||||||
|
|
||||||
|
write <sgr fg:white bg:blue>
|
||||||
|
drawfilledbox 37 5 30 8
|
||||||
|
write <sgr>
|
||||||
|
|
||||||
|
savepng boxdraw.png
|
77
examples/boxdraw.php
Normal file
77
examples/boxdraw.php
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<?php return [
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw a box frame
|
||||||
|
*/
|
||||||
|
'drawbox' => function ($term, $column, $line, $width, $height) {
|
||||||
|
fprintf(STDERR, "drawbox: {%d,%d}+[%d,%d]\n", $column, $line, $width, $height);
|
||||||
|
$oldpos = $term->getCursorPosition();
|
||||||
|
|
||||||
|
$term->setCursor($line, $column);
|
||||||
|
$term->write("\u{250c}" . str_repeat("\u{2500}", $width - 2) . "\u{2510}");
|
||||||
|
|
||||||
|
$term->setCursor($line + $height, $column);
|
||||||
|
$term->write("\u{2514}" . str_repeat("\u{2500}", $width - 2) . "\u{2518}");
|
||||||
|
|
||||||
|
for ($l = $line + 1; $l < $line + $height; $l++) {
|
||||||
|
$term->setCursor($l, $column);
|
||||||
|
$term->write("\u{2502}");
|
||||||
|
$term->setCursor($l, $column + $width - 1);
|
||||||
|
$term->write("\u{2502}");
|
||||||
|
}
|
||||||
|
|
||||||
|
$term->setCursor($oldpos[0], $oldpos[1]);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw a box and fill it
|
||||||
|
*/
|
||||||
|
'drawfilledbox' => function ($term, $column, $line, $width, $height) {
|
||||||
|
fprintf(STDERR, "drawbox: {%d,%d}+[%d,%d]\n", $column, $line, $width, $height);
|
||||||
|
$oldpos = $term->getCursorPosition();
|
||||||
|
|
||||||
|
$term->setCursor($line, $column);
|
||||||
|
$term->write("\u{250c}" . str_repeat("\u{2500}", $width - 2) . "\u{2510}");
|
||||||
|
|
||||||
|
$term->setCursor($line + $height, $column);
|
||||||
|
$term->write("\u{2514}" . str_repeat("\u{2500}", $width - 2) . "\u{2518}");
|
||||||
|
|
||||||
|
for ($l = $line + 1; $l < $line + $height; $l++) {
|
||||||
|
$term->setCursor($l, $column);
|
||||||
|
$term->write("\u{2502}" . str_repeat(" ", $width - 2) . "\u{2502}");
|
||||||
|
}
|
||||||
|
|
||||||
|
$term->setCursor($oldpos[0], $oldpos[1]);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw a horizontal line
|
||||||
|
*/
|
||||||
|
'drawhline' => function ($term, $line, $fromCol, $toCol) {
|
||||||
|
|
||||||
|
$oldpos = $term->getCursorPosition();
|
||||||
|
|
||||||
|
$term->setCursor($line, $fromCol);
|
||||||
|
$term->write(str_repeat("\u{2500}", ($toCol-$fromCol)));
|
||||||
|
|
||||||
|
$term->setCursor($oldpos[0], $oldpos[1]);
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw a vertical line
|
||||||
|
*/
|
||||||
|
'drawvline' => function ($term, $column, $fromLine, $toLine) {
|
||||||
|
|
||||||
|
$oldpos = $term->getCursorPosition();
|
||||||
|
|
||||||
|
for ($l = $fromLine; $l <= $toLine; $l++) {
|
||||||
|
$term->setCursor($l, $column);
|
||||||
|
$term->write("\u{2502}");
|
||||||
|
}
|
||||||
|
|
||||||
|
$term->setCursor($oldpos[0], $oldpos[1]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
];
|
BIN
examples/boxdraw.png
Normal file
BIN
examples/boxdraw.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
@ -1,5 +1,5 @@
|
|||||||
set terminal 80x5
|
set terminal 80x10
|
||||||
set typedelay 250
|
set typedelay 100
|
||||||
set fps 30
|
set fps 30
|
||||||
|
|
||||||
sub prompt
|
sub prompt
|
||||||
@ -7,33 +7,93 @@ sub prompt
|
|||||||
delay 500
|
delay 500
|
||||||
endsub
|
endsub
|
||||||
|
|
||||||
|
write <sgr bold> "dd" <sgr> " - convert and copy a file" <return>
|
||||||
|
write u{2500} *80 <return>
|
||||||
|
|
||||||
|
mark %top
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
write <sgr fg:cyan bold> Example 1: <sgr fg:cyan> " Creating a disk image" <sgr> <return> <return>
|
||||||
prompt "~"
|
prompt "~"
|
||||||
|
|
||||||
type "dd "
|
type "dd "
|
||||||
|
|
||||||
|
delay 1000
|
||||||
|
|
||||||
mark dd-if
|
mark dd-if
|
||||||
type "if=/dev/sdb "
|
type "if=/dev/sdb "
|
||||||
annotate @dd-if "Input" at dd-if
|
annotate @dd-if "Input file\n(Source)" at dd-if
|
||||||
annotatelength @dd-if 11
|
annotatelength @dd-if 11
|
||||||
|
delay 2000
|
||||||
|
|
||||||
mark dd-of
|
mark dd-of
|
||||||
type "of=image.img "
|
type "of=image.img "
|
||||||
annotate @dd-of "Output" at dd-of
|
annotate @dd-of "Output file\n(Destination)" at dd-of
|
||||||
annotatelength @dd-of 12
|
annotatelength @dd-of 12
|
||||||
|
delay 2000
|
||||||
|
|
||||||
mark dd-bs
|
mark dd-bs
|
||||||
type "bs=16M "
|
type "bs=16M "
|
||||||
annotate @dd-bs "Block\nsize" at dd-bs
|
annotate @dd-bs "Block\nsize" at dd-bs
|
||||||
annotatelength @dd-bs 6
|
annotatelength @dd-bs 6
|
||||||
|
delay 2000
|
||||||
|
|
||||||
mark dd-status
|
mark dd-status
|
||||||
type "status=progress "
|
type "status=progress "
|
||||||
annotate @dd-status "Show progress" at dd-status
|
annotate @dd-status "Show progress" at dd-status
|
||||||
annotatelength @dd-status 15
|
annotatelength @dd-status 15
|
||||||
|
delay 2000
|
||||||
|
|
||||||
write <return>
|
write <return>
|
||||||
|
|
||||||
prompt "~"
|
|
||||||
|
|
||||||
delay 2000
|
delay 2000
|
||||||
|
|
||||||
clearannotate
|
clearannotate
|
||||||
|
moveto %top
|
||||||
|
clear to-bottom
|
||||||
|
delay 500
|
||||||
|
|
||||||
|
|
||||||
delay 500
|
write <sgr fg:cyan bold> Example 2: <sgr fg:cyan> " Create a file with empty data" <sgr> <return> <return>
|
||||||
|
prompt "~"
|
||||||
|
|
||||||
|
type "dd "
|
||||||
|
|
||||||
|
delay 1000
|
||||||
|
|
||||||
|
mark dd-if
|
||||||
|
type "if=/dev/zero "
|
||||||
|
annotate @dd-if "Reading from\n/dev/zero will\nreturn '0'\nindefinitely" at dd-if
|
||||||
|
annotatelength @dd-if 12
|
||||||
|
delay 2000
|
||||||
|
|
||||||
|
mark dd-bs
|
||||||
|
type "bs=1M "
|
||||||
|
annotate @dd-bs "Block\nsize" at dd-bs
|
||||||
|
annotatelength @dd-bs 5
|
||||||
|
delay 2000
|
||||||
|
|
||||||
|
mark dd-count
|
||||||
|
type "count=100 "
|
||||||
|
annotate @dd-count "Number of\nblocks to\ncopy:\n100*1M=100MB" at dd-count
|
||||||
|
annotatelength @dd-count 9
|
||||||
|
delay 2000
|
||||||
|
|
||||||
|
mark dd-of
|
||||||
|
type "> "
|
||||||
|
annotate @dd-of "Without of= the output\nwill go to standard output,\nwhich can be redirected" at dd-of
|
||||||
|
annotatelength @dd-of 1
|
||||||
|
delay 2000
|
||||||
|
|
||||||
|
type "empty.img"
|
||||||
|
|
||||||
|
write <return>
|
||||||
|
|
||||||
|
delay 2000
|
||||||
|
|
||||||
|
clearannotate
|
||||||
|
moveto %top
|
||||||
|
clear to-bottom
|
||||||
|
delay 500
|
||||||
|
|
||||||
|
BIN
examples/dd.gif
BIN
examples/dd.gif
Binary file not shown.
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 1.0 MiB |
BIN
examples/dd.mp4
Normal file
BIN
examples/dd.mp4
Normal file
Binary file not shown.
5
examples/keys.ftm
Normal file
5
examples/keys.ftm
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
set terminal 80x25
|
||||||
|
|
||||||
|
showkeys ctrl alt shift F4 up up down down left right left right B A
|
||||||
|
|
||||||
|
savepng keys.png
|
BIN
examples/keys.png
Normal file
BIN
examples/keys.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
@ -16,6 +16,8 @@ class FakeTerminal
|
|||||||
|
|
||||||
private $subs = [];
|
private $subs = [];
|
||||||
|
|
||||||
|
private $funcs = [];
|
||||||
|
|
||||||
private $execMode = null;
|
private $execMode = null;
|
||||||
|
|
||||||
private $execTarget = null;
|
private $execTarget = null;
|
||||||
@ -32,6 +34,12 @@ class FakeTerminal
|
|||||||
|
|
||||||
private $frameDuration = 0;
|
private $frameDuration = 0;
|
||||||
|
|
||||||
|
private $startTime;
|
||||||
|
|
||||||
|
private $nextStat;
|
||||||
|
|
||||||
|
private $lastFrames;
|
||||||
|
|
||||||
private $output;
|
private $output;
|
||||||
|
|
||||||
private $bookmarks = [];
|
private $bookmarks = [];
|
||||||
@ -47,6 +55,20 @@ class FakeTerminal
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function showStats()
|
||||||
|
{
|
||||||
|
if ($this->nextStat === null) {
|
||||||
|
$this->nextStat = microtime(true) + 2;
|
||||||
|
return;
|
||||||
|
} elseif ($this->nextStat > microtime(true)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$this->nextStat = microtime(true) + 2;
|
||||||
|
$fps = ($this->frame - $this->lastFrames) / 2;
|
||||||
|
$this->lastFrames = $this->frame;
|
||||||
|
fprintf(STDERR, "rendering: f=%d fps=%.1f t=%.1d\n", $this->frame, $fps, microtime(true) - $this->startTime);
|
||||||
|
}
|
||||||
|
|
||||||
public function setOutput(string $output)
|
public function setOutput(string $output)
|
||||||
{
|
{
|
||||||
$this->output = $output;
|
$this->output = $output;
|
||||||
@ -57,9 +79,36 @@ class FakeTerminal
|
|||||||
$this->outputVideo = $outputVideo;
|
$this->outputVideo = $outputVideo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function loadModule(string $filename)
|
||||||
|
{
|
||||||
|
$funcs = include $filename;
|
||||||
|
foreach ($funcs as $name=>$func) {
|
||||||
|
$this->funcs[$name] = $func;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function executeFile(string $filename)
|
public function executeFile(string $filename)
|
||||||
|
{
|
||||||
|
$this->startTime = microtime(true);
|
||||||
|
|
||||||
|
$this->includeFile($filename);
|
||||||
|
|
||||||
|
echo "\r\e[K";
|
||||||
|
if ($this->outputVideo) {
|
||||||
|
fprintf(STDERR, "Converting %s → %s\n", $this->output, $this->outputVideo);
|
||||||
|
passthru(sprintf("ffmpeg -v error -r %d -i %s -y %s", $this->fps, $this->output, $this->outputVideo));
|
||||||
|
fprintf(STDERR, "Cleaning up %d files...\n", count($this->writtenFiles));
|
||||||
|
foreach ($this->writtenFiles as $fn) {
|
||||||
|
unlink($fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function includeFile(string $filename)
|
||||||
{
|
{
|
||||||
$fp = fopen($filename, "r");
|
$fp = fopen($filename, "r");
|
||||||
|
if (!$fp) return;
|
||||||
$lc = 0;
|
$lc = 0;
|
||||||
while (!feof($fp)) {
|
while (!feof($fp)) {
|
||||||
$lc++;
|
$lc++;
|
||||||
@ -73,17 +122,7 @@ class FakeTerminal
|
|||||||
fprintf(STDERR, "Error executing %s line %d: %s\n", $filename, $lc, $t->getMessage());
|
fprintf(STDERR, "Error executing %s line %d: %s\n", $filename, $lc, $t->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fclose($fp);
|
||||||
echo "\r\e[K";
|
|
||||||
if ($this->outputVideo) {
|
|
||||||
fprintf(STDERR, "Converting %s → %s\n", $this->output, $this->outputVideo);
|
|
||||||
passthru(sprintf("ffmpeg -v error -r %d -i %s -y %s", $this->fps, $this->output, $this->outputVideo));
|
|
||||||
fprintf(STDERR, "Cleaning up %d files...\n", count($this->writtenFiles));
|
|
||||||
foreach ($this->writtenFiles as $fn) {
|
|
||||||
unlink($fn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function evaluate(array $data)
|
public function evaluate(array $data)
|
||||||
@ -108,6 +147,16 @@ class FakeTerminal
|
|||||||
$this->setProp($prop, $value);
|
$this->setProp($prop, $value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'include':
|
||||||
|
$file = array_shift($args);
|
||||||
|
$this->includeFile($file);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'load':
|
||||||
|
$file = array_shift($args);
|
||||||
|
$this->loadModule($file);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'sub':
|
case 'sub':
|
||||||
$subname = array_shift($args);
|
$subname = array_shift($args);
|
||||||
$subargs = $args;
|
$subargs = $args;
|
||||||
@ -202,11 +251,81 @@ class FakeTerminal
|
|||||||
$this->renderer->updateAnnotation($id, [ 'length' => intval(array_shift($args))]);
|
$this->renderer->updateAnnotation($id, [ 'length' => intval(array_shift($args))]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'showkeys':
|
||||||
|
$this->renderer->setKeyOverlay($args);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'clear':
|
||||||
|
$what = array_shift($args);
|
||||||
|
$tw = $this->term->getColumns();
|
||||||
|
$th = $this->term->getLines();
|
||||||
|
[$cl,$cc] = $this->term->getCursorPosition();
|
||||||
|
$sa = $this->term->getAttributes();
|
||||||
|
switch ($what) {
|
||||||
|
case 'screen':
|
||||||
|
for ($l = 0; $l < $th; $l++) {
|
||||||
|
for ($c = 0; $c < $tw; $c++) {
|
||||||
|
$this->term->bufferSetRaw($l, $c, [ ' ', $sa ]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'line':
|
||||||
|
for ($c = 0; $c < $tw; $c++) {
|
||||||
|
$this->term->bufferSetRaw($cl, $c, [ ' ', $sa ]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'to-eol':
|
||||||
|
for ($c = $cc; $c < $tw; $c++) {
|
||||||
|
$this->term->bufferSetRaw($cl, $c, [ ' ', $sa ]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'to-bol':
|
||||||
|
for ($c = 0; $c <= $cc; $c++) {
|
||||||
|
$this->term->bufferSetRaw($cl, $c, [ ' ', $sa ]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'above':
|
||||||
|
for ($l = 0; $l < $cl; $l++) {
|
||||||
|
for ($c = 0; $c < $tw; $c++) {
|
||||||
|
$this->term->bufferSetRaw($l, $c, [ ' ', $sa ]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'to-top':
|
||||||
|
for ($l = 0; $l <= $cl; $l++) {
|
||||||
|
for ($c = 0; $c < $tw; $c++) {
|
||||||
|
$this->term->bufferSetRaw($l, $c, [ ' ', $sa ]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'below':
|
||||||
|
for ($l = $cl + 1; $l < $th; $l++) {
|
||||||
|
for ($c = 0; $c < $tw; $c++) {
|
||||||
|
$this->term->bufferSetRaw($l, $c, [ ' ', $sa ]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'to-bottom':
|
||||||
|
for ($l = $cl; $l < $th; $l++) {
|
||||||
|
for ($c = 0; $c < $tw; $c++) {
|
||||||
|
$this->term->bufferSetRaw($l, $c, [ ' ', $sa ]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(STDERR, "error: Can't clear '%s'\n", $what);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (array_key_exists($cmd, $this->subs)) {
|
if (array_key_exists($cmd, $this->subs)) {
|
||||||
$this->callSub($cmd, $args);
|
$this->callSub($cmd, $args);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (array_key_exists($cmd, $this->funcs)) {
|
||||||
|
$this->callFunc($cmd, $args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
throw new \LogicException("No such command ${cmd}");
|
throw new \LogicException("No such command ${cmd}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,8 +343,7 @@ class FakeTerminal
|
|||||||
$file = sprintf($this->output, $this->frame++);
|
$file = sprintf($this->output, $this->frame++);
|
||||||
$this->renderer->writePng($file);
|
$this->renderer->writePng($file);
|
||||||
|
|
||||||
//$this->dumper->render($this->term);
|
$this->showStats();
|
||||||
//printf("\e[0m\rwrite: \e[1m%s\e[0m", $file);
|
|
||||||
$this->writtenFiles[] = $file;
|
$this->writtenFiles[] = $file;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,9 +373,10 @@ class FakeTerminal
|
|||||||
{
|
{
|
||||||
//printf("write: %s\n", json_encode($args));
|
//printf("write: %s\n", json_encode($args));
|
||||||
$buf = null;
|
$buf = null;
|
||||||
|
$lastArg = null;
|
||||||
while (count($args)) {
|
while (count($args)) {
|
||||||
$arg = array_shift($args);
|
$arg = array_shift($args);
|
||||||
if ($arg[0] == "<" && strlen($arg) > 1) {
|
if ($arg && $arg[0] == "<" && strlen($arg) > 1) {
|
||||||
if (substr($arg, -1, 1) == ">") {
|
if (substr($arg, -1, 1) == ">") {
|
||||||
$this->setupTerm(substr($arg, 1, -1));
|
$this->setupTerm(substr($arg, 1, -1));
|
||||||
continue;
|
continue;
|
||||||
@ -272,9 +391,11 @@ class FakeTerminal
|
|||||||
$buf = join(" ", $buf);
|
$buf = join(" ", $buf);
|
||||||
$this->setupTerm(substr($buf, 1, -1));
|
$this->setupTerm(substr($buf, 1, -1));
|
||||||
$buf = null;
|
$buf = null;
|
||||||
|
|
||||||
} elseif (preg_match('/u\{([0-9a-f]+)\}/', $arg, $match)) {
|
} elseif (preg_match('/u\{([0-9a-f]+)\}/', $arg, $match)) {
|
||||||
|
|
||||||
$arg = mb_chr(hexdec($match[1]));
|
$arg = mb_chr(hexdec($match[1]));
|
||||||
|
$lastArg = $arg;
|
||||||
//printf("write: '%s'\n", $arg);
|
//printf("write: '%s'\n", $arg);
|
||||||
if (!$type) {
|
if (!$type) {
|
||||||
$this->term->write($arg);
|
$this->term->write($arg);
|
||||||
@ -284,9 +405,26 @@ class FakeTerminal
|
|||||||
$this->delayMs($this->typeDelay + rand(-$this->typeJitter,$this->typeJitter));
|
$this->delayMs($this->typeDelay + rand(-$this->typeJitter,$this->typeJitter));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} elseif (preg_match('/\*([0-9]+)/', $arg, $match)) {
|
||||||
|
|
||||||
|
$repeat = intval($match[1]) - 1;
|
||||||
|
|
||||||
|
//printf("repeat: '%s' * %d\n", $lastArg, $repeat);
|
||||||
|
for ($n = 0; $n < $repeat; $n++) {
|
||||||
|
if (!$type) {
|
||||||
|
$this->term->write((string)$lastArg);
|
||||||
|
} else {
|
||||||
|
for ($c = 0; $c < mb_strlen($lastArg); $c++) {
|
||||||
|
$this->term->write(mb_substr($lastArg, $c, 1));
|
||||||
|
$this->delayMs($this->typeDelay + rand(-$this->typeJitter,$this->typeJitter));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//printf("write: '%s'\n", $arg);
|
//printf("write: '%s'\n", $arg);
|
||||||
|
$lastArg = $arg;
|
||||||
if (!$type) {
|
if (!$type) {
|
||||||
$this->term->write($arg);
|
$this->term->write($arg);
|
||||||
} else {
|
} else {
|
||||||
@ -310,6 +448,7 @@ class FakeTerminal
|
|||||||
$this->term->setCursor($this->term->getCursorPosition()[0], 0);
|
$this->term->setCursor($this->term->getCursorPosition()[0], 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'br':
|
||||||
case 'return':
|
case 'return':
|
||||||
$this->term->setCursor($this->term->getCursorPosition()[0] + 1, 0);
|
$this->term->setCursor($this->term->getCursorPosition()[0] + 1, 0);
|
||||||
break;
|
break;
|
||||||
@ -371,13 +510,18 @@ class FakeTerminal
|
|||||||
foreach ($data as $k=>$v) {
|
foreach ($data as $k=>$v) {
|
||||||
if ($v[0] == '$' && strlen($v) > 1) {
|
if ($v[0] == '$' && strlen($v) > 1) {
|
||||||
$i = intval(substr($v, 1)) - 1;
|
$i = intval(substr($v, 1)) - 1;
|
||||||
$data[$k] = array_key_exists($i, $args)?$args[$i]:"";
|
$data[$k] = array_key_exists($i, $args)?$args[$i]:$v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->evaluate($data);
|
$this->evaluate($data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function callFunc(string $func, array $args=[])
|
||||||
|
{
|
||||||
|
call_user_func($this->funcs[$func], $this->term, ...$args);
|
||||||
|
}
|
||||||
|
|
||||||
public function setProp(string $prop, $value)
|
public function setProp(string $prop, $value)
|
||||||
{
|
{
|
||||||
switch ($prop) {
|
switch ($prop) {
|
||||||
|
Loading…
Reference in New Issue
Block a user