From f389e5985f9fdd3be8113c6801c3a5afb0467736 Mon Sep 17 00:00:00 2001 From: Christopher Vagnetoft Date: Sat, 5 Oct 2024 17:54:49 +0200 Subject: [PATCH] Add PgUp/Dn/Home/End to menu, bugfixes --- src/Editor/Editor.php | 134 ++++++++++++++++++++------------------ src/Editor/Menu.php | 42 +++++++++--- src/Editor/MessageBox.php | 28 ++++++++ 3 files changed, 131 insertions(+), 73 deletions(-) diff --git a/src/Editor/Editor.php b/src/Editor/Editor.php index 79f09ed..e74fc6e 100644 --- a/src/Editor/Editor.php +++ b/src/Editor/Editor.php @@ -43,14 +43,6 @@ class Editor { $this->document = new Tree(); - // $this->document->load((object)[ - // 'foo' => true, - // 'bar' => [ - // 'a', 'b', 'c' - // ], - // 'what' => 42 - // ]); - $this->list = new TreeList($this->document); $this->setWindowTitle($this->shortfilename." - JSONEdit"); @@ -86,7 +78,7 @@ class Editor /** * Load a document from array/object * -< * @param mixed $document + * @param mixed $document * @return void */ public function loadDocument(mixed $document): void @@ -164,30 +156,7 @@ class Editor // break; case 'I': - $menu = new Menu($this->term, [ - 'value' => "Insert Value", - 'object' => "Insert Object{}", - 'array' => "Insert Array[]", - //'sep0' => "---", - //'__paste' => "Paste from clipboard", - ], 'Insert'); - $this->redrawInfoBar([ '^C' => 'Cancel', '↑/↓' => 'Select option', 'Enter' => 'Accept' ]); - $sel = $menu->display(0, 0, 30, 0, "value"); - $this->redrawEditor(); - switch ($sel) { - case 'value': - $this->doInsertValue(); - $this->modified = true; - break; - case 'array': - $this->doInsertValue('[]'); - $this->modified = true; - break; - case 'object': - $this->doInsertValue('{}'); - $this->modified = true; - break; - } + $this->doInsertMenu(); break; case 'H': @@ -204,33 +173,7 @@ class Editor break; case "\x18": // ctrl-x - if ($this->modified) { - $menu = new Menu($this->term, [ - 'cancel' => "Return to editor", - 'save' => "Save changes", - 'discard' => "Discard changes", - //'sep0' => "---", - //'__paste' => "Paste from clipboard", - ], 'Document is modified'); - $this->redrawInfoBar([ '^C' => 'Cancel', '↑/↓' => 'Select option', 'Enter' => 'Accept' ]); - $sel = $menu->display(0, 0, 30, 0, "value"); - $this->redrawEditor(); - switch ($sel) { - case 'cancel': - break; - case 'save': - if ($this->doWriteFile()) { - $this->running = false; - } - break; - case 'discard': - $this->running = false; - break; - } - } else { - $this->running = false; - } - + $this->doExit(); break; case "g": @@ -495,17 +438,28 @@ class Editor $items = [ dirname($wd) => sprintf( "%-30s %10s %20s", - "Parent Directory", + "<..>", "", "-" ) ]; $files = glob($wd."/*"); + // do two sweeps, to sort directories. foreach ($files as $file) { + if (!is_dir($file)) continue; $items[$file] = sprintf( "%-30s %10s %20s", - mb_substr(is_dir($file) ? ("<".basename($file).">") : (basename($file)), 0, 30), - is_dir($file) ? "" : filesize($file), + mb_substr("<".basename($file).">", 0, 30), + "", + date("Y-m-d H:i:s", filemtime($file)) + ); + } + foreach ($files as $file) { + if (is_dir($file)) continue; + $items[$file] = sprintf( + "%-30s %10s %20s", + mb_substr(basename($file), 0, 30), + filesize($file), date("Y-m-d H:i:s", filemtime($file)) ); } @@ -722,6 +676,32 @@ class Editor } } + public function doInsertMenu(): void + { + $menu = new Menu($this->term, [ + 'value' => "Insert Value", + 'object' => "Insert Object{}", + 'array' => "Insert Array[]", + ], 'Insert'); + $this->redrawInfoBar([ '^C' => 'Cancel', '↑/↓' => 'Select option', 'Enter' => 'Accept' ]); + $sel = $menu->display(0, 0, 40, 0, "value"); + $this->redrawEditor(); + switch ($sel) { + case 'value': + $this->doInsertValue(); + $this->modified = true; + break; + case 'array': + $this->doInsertValue('[]'); + $this->modified = true; + break; + case 'object': + $this->doInsertValue('{}'); + $this->modified = true; + break; + } + } + public function doCollapseAll(): void { foreach ($this->list as $path => $entry) { @@ -741,6 +721,34 @@ class Editor $this->redrawEditor(); } + public function doExit(): void + { + if ($this->modified) { + $menu = new Menu($this->term, [ + 'cancel' => "Return to editor", + 'save' => "Save changes", + 'discard' => "Discard changes", + ], 'Document is modified'); + $this->redrawInfoBar([ '^C' => 'Cancel', '↑/↓' => 'Select option', 'Enter' => 'Accept' ]); + $sel = $menu->display(0, 0, 30, 0, "value"); + $this->redrawEditor(); + switch ($sel) { + case 'cancel': + break; + case 'save': + if ($this->doWriteFile()) { + $this->running = false; + } + break; + case 'discard': + $this->running = false; + break; + } + } else { + $this->running = false; + } + } + /** * Ask for input * diff --git a/src/Editor/Menu.php b/src/Editor/Menu.php index 3d26154..2831c5c 100644 --- a/src/Editor/Menu.php +++ b/src/Editor/Menu.php @@ -105,15 +105,37 @@ class Menu return array_keys($this->items)[$this->index]; } } else { - if ($ch == "k{UP}") { - $this->index--; - if ($this->index < 0) $this->index = count($this->items) - 1; - $this->redraw($left, $top, $width, $height); - } elseif ($ch == "k{DOWN}") { - $this->index++; - if ($this->index >= count($this->items)) $this->index = 0; - - $this->redraw($left, $top, $width, $height); + switch ($ch) { + case "k{UP}": + $this->index--; + if ($this->index < 0) $this->index = count($this->items) - 1; + $this->redraw($left, $top, $width, $height); + break; + case "k{DOWN}": + $this->index++; + if ($this->index >= count($this->items)) $this->index = 0; + $this->redraw($left, $top, $width, $height); + break; + case "k{PGUP}": + $this->index -= $height - 2; + if ($this->index < 0) $this->index = count($this->items) - 1; + $this->redraw($left, $top, $width, $height); + break; + case "k{PGDN}": + $this->index += $height - 2; + if ($this->index >= count($this->items)) $this->index = 0; + $this->redraw($left, $top, $width, $height); + break; + case "k{HOME}": + $this->index = 0; + if ($this->index >= count($this->items)) $this->index = 0; + $this->redraw($left, $top, $width, $height); + break; + case "k{END}": + $this->index = count($this->items) - 1; + if ($this->index >= count($this->items)) $this->index = 0; + $this->redraw($left, $top, $width, $height); + break; } } } @@ -146,7 +168,7 @@ class Menu $scrollTop = $this->scroll; $scrollBottom = $scrollTop + $visibleItems - 1; $thumbTop = round(($visibleItems - 1) / count($this->items) * $scrollTop); - $thumbBottom = round(($visibleItems - 1) / count($this->items) * $scrollBottom); + $thumbBottom = round(($visibleItems) / count($this->items) * $scrollBottom); $tleft = round(($width / 2) - ((mb_strlen($this->title) + 2) / 2)); diff --git a/src/Editor/MessageBox.php b/src/Editor/MessageBox.php index 2e5888d..9b79dab 100644 --- a/src/Editor/MessageBox.php +++ b/src/Editor/MessageBox.php @@ -27,10 +27,26 @@ class MessageBox private int $scroll = 0; + /** + * constructor + * + * @param Terminal $terminal + * @param string $text + * @param string $title + */ public function __construct(private Terminal $terminal, private string $text, private string $title = 'Message') { } + /** + * Display the message box + * + * @param int $left + * @param int $top + * @param int $width + * @param int $height + * @return void + */ public function display(int $left, int $top, int $width, int $height = 0): void { $wrapped = explode("\n", wordwrap($this->text, $width - 4, cut_long_words:true)); @@ -76,6 +92,18 @@ class MessageBox return; } + /** + * Redraw the message box + * + * @param int $left + * @param int $top + * @param int $width + * @param int $height + * @param array $wrapped + * @param string $title + * @param int $maxScroll + * @return void + */ private function redraw(int $left, int $top, int $width, int $height, array $wrapped, string $title, int $maxScroll) { $visibleItems = $height - 4;