Skip to content

Commit

Permalink
1. refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
scarwu committed Jun 5, 2022
1 parent d368ec6 commit 31528b7
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 16 deletions.
1 change: 1 addition & 0 deletions example/CLI/tasks/HelpTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public function run()
$this->io->info('Try above tasks:');
$this->io->info(' ./boot.php help');
$this->io->info(' ./boot.php read');
$this->io->info(' ./boot.php menu');
$this->io->info(' ./boot.php color');
$this->io->info(' ./boot.php parse');
}
Expand Down
63 changes: 63 additions & 0 deletions example/CLI/tasks/MenuTask.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php
/**
* Menu Task
*
* @package Oni
* @author Scar Wu
* @copyright Copyright (c) Scar Wu (https://scar.tw)
* @link https://github.com/scarwu/Oni
*/

namespace CLIApp\Task;

use Oni\CLI\Task;

class MenuTask extends Task
{
public function run()
{
$count = $this->io->ask('Item counts of menu? [10] ', function ($value) {
return true === (bool) preg_match('/^\d+$/', $value) || '' === $value;
});

if ('' !== $count) {
$count = (int) $count;
} else {
$count = 10;
}

if (0 === $count) {
$count = 10;
}

$lines = $this->io->ask('Display lines of menu? [3] ', function ($value) {
return true === (bool) preg_match('/^\d+$/', $value) || '' === $value;
});

if ('' !== $lines) {
$lines = (int) $lines;
} else {
$lines = 3;
}

if (0 === $lines) {
$lines = 3;
}

if ($lines > $count) {
$lines = $count;
}

$list = [];

for ($index = 0; $index < $count; $index++) {
$list[] = sprintf('[%3d]', $index) . ' ' . md5($index);
}

$this->io->writeln("Select Index");

$index = $this->io->menuSelect($list, $lines);

$this->io->log("You selected index is {$index}!");
}
}
4 changes: 3 additions & 1 deletion example/CLI/tasks/ReadTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ public function run()

// or

$name = $this->io->ask('What is your name? ');
$name = $this->io->ask('What is your name? ', function ($value) {
return '' !== $value;
});

if (0 === $gender) {
$this->io->log("Hi, Mr.{$name}!");
Expand Down
11 changes: 11 additions & 0 deletions src/Oni/CLI/Helper/ANSIEscapeCode.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@ final class ANSIEscapeCode
const BEL = "\x07";
const SEP = ';';

// Key Code
const KEY_CODE_ENTER = 10;
const KEY_CODE_UP = 65;
const KEY_CODE_DOWN = 66;
const KEY_CODE_LEFT = 68;
const KEY_CODE_RIGHT = 67;
const KEY_CODE_PAGE_UP = 53;
const KEY_CODE_PAGE_DOWN = 54;
const KEY_CODE_HOME = 72;
const KEY_CODE_END = 70;

/**
* @var array
*/
Expand Down
62 changes: 47 additions & 15 deletions src/Oni/CLI/IO.php
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,10 @@ public function ask(string $text, ?callable $callback = null, ?string $fgColor =
*
* @return int
*/
public function menuSelect(array $options): int
public function menuSelect(array $options, ?int $currentDisplayLines = null): int
{
$totalIndex = count($options);
$skipIndex = 0;
$selectedIndex = 0;
$isBreakLoop = false;
$isFirstLoop = true;
Expand All @@ -251,48 +252,79 @@ public function menuSelect(array $options): int
$wWidth = (int) exec('tput cols');
$wHeight = (int) exec('tput lines');

$displayLines = $totalIndex <= $wHeight
? $totalIndex : $wHeight;

if (true === is_integer($currentDisplayLines)
&& $currentDisplayLines > 0
&& $currentDisplayLines < $displayLines
) {
$displayLines = $currentDisplayLines;
}

readline_callback_handler_install('', function() {});

// Set Cursor is Hide
$this->write(AEC::cursorHide());

do {
switch (ord($char)) {
case 10: // Enter Key
case AEC::KEY_CODE_ENTER:
$isBreakLoop = true;

break;
case 65: // Up Key
if ($selectedIndex - 1 >= 0) {
$selectedIndex--;
}
case AEC::KEY_CODE_UP:
$selectedIndex--;

break;
case 66: // Down Key
if ($selectedIndex + 1 < $totalIndex) {
$selectedIndex++;
}
case AEC::KEY_CODE_DOWN:
$selectedIndex++;

break;
case AEC::KEY_CODE_PAGE_UP:
$selectedIndex -= $displayLines;

break;
case AEC::KEY_CODE_PAGE_DOWN:
$selectedIndex += $displayLines;

break;
case AEC::KEY_CODE_HOME:
$selectedIndex = 0;

break;
case AEC::KEY_CODE_END:
$selectedIndex = $totalIndex;

break;
}

if ($selectedIndex < 0) {
$selectedIndex = 0;
} elseif ($selectedIndex >= $totalIndex) {
$selectedIndex = $totalIndex - 1;
}

if (true === $isBreakLoop) {
break;
}

// Set Cursor Prev
if (false === $isFirstLoop) {
$this->write(AEC::cursorPrev($totalIndex - 1));
$this->write(AEC::cursorPrev($displayLines - 1));
} else {
$isFirstLoop = false;
}

// Get Skip Index
$skipIndex = $selectedIndex < $wHeight
? 0 : $selectedIndex - $wHeight + 1;
// Set Skip Index
if ($selectedIndex < $skipIndex) {
$skipIndex = $selectedIndex;
} else if ($selectedIndex > $skipIndex + $displayLines - 1) {
$skipIndex = $selectedIndex - $displayLines + 1;
}

// Get Current Options
$currentOptions = array_slice($options, $skipIndex, $wHeight);
$currentOptions = array_slice($options, $skipIndex, $displayLines);

// Print Menu
$this->write(implode("\n", array_map(function ($option, $currentIndex) use ($selectedIndex, $skipIndex) {
Expand Down

0 comments on commit 31528b7

Please sign in to comment.