diff options
author | Maxence Lange <maxence@artificial-owl.com> | 2018-08-03 13:47:15 +0300 |
---|---|---|
committer | Maxence Lange <maxence@artificial-owl.com> | 2018-08-03 13:47:15 +0300 |
commit | b94b7d377c3b031dd4183e57156113b4dd36c81f (patch) | |
tree | 4e0b32ec3466155f89f27ef704b5699e3217f630 /lib | |
parent | 88988c7086374d10127acf5055e4cb77dbdc8837 (diff) |
UX wrapper
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Command/Index.php | 130 | ||||
-rw-r--r-- | lib/Model/Runner.php | 34 | ||||
-rw-r--r-- | lib/Service/CliService.php | 178 |
3 files changed, 338 insertions, 4 deletions
diff --git a/lib/Command/Index.php b/lib/Command/Index.php index 6fadb0a..836b790 100644 --- a/lib/Command/Index.php +++ b/lib/Command/Index.php @@ -31,6 +31,7 @@ use OCA\FullTextSearch\IFullTextSearchProvider; use OCA\FullTextSearch\Model\ExtendedBase; use OCA\FullTextSearch\Model\IndexOptions; use OCA\FullTextSearch\Model\Runner; +use OCA\FullTextSearch\Service\CliService; use OCA\FullTextSearch\Service\IndexService; use OCA\FullTextSearch\Service\MiscService; use OCA\FullTextSearch\Service\PlatformService; @@ -44,12 +45,41 @@ use Symfony\Component\Console\Output\OutputInterface; class Index extends ExtendedBase { + + const PANEL_INDEX = 'indexing'; + const PANEL_INDEX_LINE_HEADER = '┌─ Indexing ────'; + const PANEL_INDEX_LINE_ACCOUNT = '│ Account: %userId%'; + const PANEL_INDEX_LINE_DOCUMENT = "│ Indexing <info>provider</info>/<info>document</info>"; + const PANEL_INDEX_LINE_TITLE = '│ Title: %title%'; + const PANEL_INDEX_LINE_CONTENT = '│ Content: empty'; + const PANEL_INDEX_LINE_OPTIONS = '│ Options: []'; + const PANEL_INDEX_LINE_RESULT = '│ Result: %result%'; + const PANEL_INDEX_LINE_FOOTER = '└──'; + + const PANEL_STATUS = 'status'; + const PANEL_STATUS_LINE_HEADER = '┌─ Status ────'; + const PANEL_STATUS_LINE_DOCUMENTS_TOTAL = '│ Total document for this user:'; + const PANEL_STATUS_LINE_DOCUMENTS_LEFT = '│ Document left:'; + const PANEL_STATUS_LINE_ERRORS = '│ Errors:'; + const PANEL_STATUS_LINE_FOOTER = '└──'; + + const PANEL_LINE_EMPTY = '│ '; + + const PANEL_COMMANDS_ROOT = 'root'; + const PANEL_COMMANDS_ROOT_LINE = '## q:quit ## p:pause'; + const PANEL_COMMANDS_PAUSED = 'paused'; + const PANEL_COMMANDS_PAUSED_LINE = '## q:quit ## u:unpause ## n:next'; + + /** @var IUserManager */ private $userManager; /** @var RunningService */ private $runningService; + /** @var CliService */ + private $cliService; + /** @var IndexService */ private $indexService; @@ -72,19 +102,22 @@ class Index extends ExtendedBase { * * @param IUserManager $userManager * @param RunningService $runningService + * @param CliService $cliService * @param IndexService $indexService * @param PlatformService $platformService * @param ProviderService $providerService * @param MiscService $miscService */ public function __construct( - IUserManager $userManager, RunningService $runningService, IndexService $indexService, - PlatformService $platformService, ProviderService $providerService, MiscService $miscService + IUserManager $userManager, RunningService $runningService, CliService $cliService, + IndexService $indexService, PlatformService $platformService, + ProviderService $providerService, MiscService $miscService ) { parent::__construct(); $this->userManager = $userManager; $this->runningService = $runningService; + $this->cliService = $cliService; $this->indexService = $indexService; $this->platformService = $platformService; @@ -105,6 +138,16 @@ class Index extends ExtendedBase { /** + * @throws Exception + */ + public function interrupted() { + if ($this->hasBeenInterrupted()) { + throw new \Exception('ctrl-c'); + } + } + + + /** * @param InputInterface $input * @param OutputInterface $output * @@ -113,11 +156,69 @@ class Index extends ExtendedBase { */ protected function execute(InputInterface $input, OutputInterface $output) { + readline_callback_handler_install( + '', function() { + } + ); + stream_set_blocking(STDIN, false); + $options = $this->generateIndexOptions($input); $this->runner = new Runner($this->runningService, 'commandIndex'); + $this->runner->onKeyPress([$this, 'onKeyPressed']); $this->indexService->setRunner($this->runner); - + $this->cliService->setRunner($this->runner); + + $this->cliService->createPanel( + self::PANEL_INDEX, [ + self::PANEL_INDEX_LINE_HEADER, + self::PANEL_INDEX_LINE_ACCOUNT, + self::PANEL_INDEX_LINE_DOCUMENT, + self::PANEL_INDEX_LINE_TITLE, + self::PANEL_INDEX_LINE_CONTENT, + self::PANEL_INDEX_LINE_OPTIONS, + self::PANEL_INDEX_LINE_RESULT, + self::PANEL_INDEX_LINE_FOOTER, + + ] + ); + + $this->cliService->createPanel( + self::PANEL_STATUS, [ + self::PANEL_STATUS_LINE_HEADER, + self::PANEL_STATUS_LINE_DOCUMENTS_TOTAL, + self::PANEL_STATUS_LINE_DOCUMENTS_LEFT, + self::PANEL_STATUS_LINE_ERRORS, + self::PANEL_LINE_EMPTY, + self::PANEL_LINE_EMPTY, + self::PANEL_LINE_EMPTY, + self::PANEL_STATUS_LINE_FOOTER, + ] + ); + + $this->cliService->createPanel( + self::PANEL_COMMANDS_ROOT, [ + self::PANEL_COMMANDS_ROOT_LINE + ] + ); + + $this->cliService->createPanel( + self::PANEL_COMMANDS_PAUSED, [ + self::PANEL_COMMANDS_PAUSED_LINE + ] + ); + + + $this->cliService->initDisplay(); + $this->cliService->displayPanel('topPanel', self::PANEL_INDEX); + $this->cliService->displayPanel('bottomPanel', self::PANEL_STATUS); + $this->cliService->displayPanel('commands', self::PANEL_COMMANDS_ROOT); + $this->cliService->runDisplay($output); + +// while (1) { +// $this->runner->update(); +// sleep(1); +// } try { $this->runner->sourceIsCommandLine($this, $output); @@ -146,6 +247,29 @@ class Index extends ExtendedBase { /** + * @param $key + */ + public function onKeyPressed($key) { + $key = strtolower($key); + if ($key === 'q') { + exit(); + } + + $current = $this->cliService->currentPanel('commands'); + if ($current === self::PANEL_COMMANDS_ROOT) { + if ($key === 'p') { + $this->cliService->switchPanel('commands', self::PANEL_COMMANDS_PAUSED); + } + } + if ($current === self::PANEL_COMMANDS_PAUSED) { + if ($key === 'u') { + $this->cliService->switchPanel('commands', self::PANEL_COMMANDS_ROOT); + } + } + } + + + /** * @param IFullTextSearchProvider $provider * @param IndexOptions $options * diff --git a/lib/Model/Runner.php b/lib/Model/Runner.php index 57a9a3d..326ed6f 100644 --- a/lib/Model/Runner.php +++ b/lib/Model/Runner.php @@ -69,6 +69,10 @@ class Runner { /** @var int */ private $ramTick = 0; + /** @var array */ + private $methodOnKeyPress = []; + + /** * Runner constructor. * @@ -98,7 +102,17 @@ class Runner { * @throws InterruptException * @throws TickDoesNotExistException */ - public function update($action) { + public function update($action = '') { + if (sizeof($this->methodOnKeyPress) > 0) { + $n = fread(STDIN, 1); + if ($n !== '') { + $this->keyPressed($n); + } + } + + if ($action === '') { + return; + } $tick = time(); try { @@ -126,6 +140,24 @@ class Runner { /** + * @param array $method + */ + public function onKeyPress($method) { + $this->methodOnKeyPress[] = $method; + } + + + /** + * @param $key + */ + public function keyPressed($key) { + foreach ($this->methodOnKeyPress as $method) { + call_user_func($method, $key); + } + } + + + /** * @throws InterruptException */ private function hasBeenInterrupted() { diff --git a/lib/Service/CliService.php b/lib/Service/CliService.php new file mode 100644 index 0000000..f6f39a8 --- /dev/null +++ b/lib/Service/CliService.php @@ -0,0 +1,178 @@ +<?php +/** + * FullTextSearch - Full text search framework for Nextcloud + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Maxence Lange <maxence@artificial-owl.com> + * @copyright 2018 + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\FullTextSearch\Service; + +use OCA\FullTextSearch\Model\Runner; +use Symfony\Component\Console\Helper\ProgressBar; +use Symfony\Component\Console\Output\OutputInterface; + +class CliService { + + + /** @var MiscService */ + private $miscService; + + /** @var Runner */ + private $runner; + + /** @var array */ + private $panels = []; + + /** @var array */ + private $displayedPanel = []; + + /** @var ProgressBar */ + private $display; + + /** @var OutputInterface */ + private $output = null; + + /** + * TestService constructor. + * + * @param MiscService $miscService + */ + public function __construct(MiscService $miscService) { + $this->miscService = $miscService; + } + + + /** + * @param Runner $runner + */ + public function setRunner(Runner $runner) { + $this->runner = $runner; + } + + + /** + * @param string $panelId + * @param array $lines + */ + public function createPanel($panelId, $lines) { + if (!is_array($lines)) { + $lines = [$lines]; + } + + $this->panels[$panelId] = $lines; + } + + + /** + * + */ + public function initDisplay() { + $this->displayedPanel = []; + } + + + /** + * @param string $panelSlot + * @param string $panelId + */ + public function displayPanel($panelSlot, $panelId) { + $this->displayedPanel[] = [ + 'slot' => $panelSlot, + 'id' => $panelId + ]; + } + + + /** + * @param string $panelSlot + * + * @return mixed + */ + public function currentPanel($panelSlot) { + foreach ($this->displayedPanel as $panel) { + if ($panel['slot'] === $panelSlot) { + return $panel['id']; + } + } + } + + + /** + * @param string $panelSlot + * @param string $panelId + */ + public function switchPanel($panelSlot, $panelId) { + $this->displayedPanel = array_map( + function($item) use ($panelId, $panelSlot) { + if ($item['slot'] === $panelSlot) { + $item['id'] = $panelId; + } + + return $item; + }, $this->displayedPanel + ); + + $this->refreshDisplay(); + } + + /** + * @param OutputInterface $output + */ + public function runDisplay(OutputInterface $output) { + $this->output = $output; + + foreach ($this->displayedPanel as $displayedPanel) { + $panel = $this->panels[$displayedPanel['id']]; + for ($i = 0; $i < sizeof($panel); $i++) { + $output->writeLn(''); + } + } + + $this->display = new ProgressBar($this->output); + $this->display->setOverwrite(true); + $this->display->clear(); + + $this->refreshDisplay(); + } + + + public function refreshDisplay() { + + $format = []; + foreach ($this->displayedPanel as $displayedPanel) { + $panel = $this->panels[$displayedPanel['id']]; + for ($i = 0; $i < sizeof($panel); $i++) { + $format[] = $panel[$i]; + } + } + +// $this->display->setMessage('<info>toto</info>'); +// $progress->setMessage('', 'jvm'); +// $progress->setMessage('', 'duration'); + $this->display->setFormat(implode("\n", $format) . "\n"); + $this->display->start(); + } + +// '%job:1s%%message:-40s%%current:6s%/%max:6s% [%bar%] %percent:3s%% \n %duration% %infos:-12s% %jvm:-30s% ' + + +} |