Implement folding (use '+' key), clean up code
This commit is contained in:
parent
989cc89e4b
commit
1cccfc0187
@ -6,6 +6,7 @@ use NoccyLabs\JsonEdit\List\TreeList;
|
||||
use NoccyLabs\JsonEdit\Settings;
|
||||
use NoccyLabs\JsonEdit\Terminal\Terminal;
|
||||
use NoccyLabs\JsonEdit\Tree\ArrayNode;
|
||||
use NoccyLabs\JsonEdit\Tree\CollapsibleNode;
|
||||
use NoccyLabs\JsonEdit\Tree\ObjectNode;
|
||||
use NoccyLabs\JsonEdit\Tree\Tree;
|
||||
use NoccyLabs\JsonEdit\Tree\ValueNode;
|
||||
@ -79,7 +80,7 @@ class Editor
|
||||
/**
|
||||
* Load a document from array/object
|
||||
*
|
||||
* @param mixed $document
|
||||
< * @param mixed $document
|
||||
* @return void
|
||||
*/
|
||||
public function loadDocument(mixed $document): void
|
||||
@ -147,8 +148,7 @@ class Editor
|
||||
$this->redrawEditor();
|
||||
$this->modified = true;
|
||||
} else {
|
||||
$this->term->setCursor(1, $h);
|
||||
echo "\e[97;41mCan only delete from object, array\e[K\e[0m";
|
||||
$this->showMessage("\e[97;41mCan only delete from object, array");
|
||||
}
|
||||
break;
|
||||
|
||||
@ -176,7 +176,7 @@ class Editor
|
||||
'array' => "Insert Array[]",
|
||||
], 'Insert');
|
||||
$this->redrawInfoBar([ '^C' => 'Cancel', '↑/↓' => 'Select option', 'Enter' => 'Accept' ]);
|
||||
$sel = $menu->display(5, 2, 30, 0, "value");
|
||||
$sel = $menu->display(0, 0, 30, 0, "value");
|
||||
$this->redrawEditor();
|
||||
switch ($sel) {
|
||||
case 'value':
|
||||
@ -211,6 +211,15 @@ class Editor
|
||||
$this->running = false;
|
||||
break;
|
||||
|
||||
case "+":
|
||||
$node = $this->list->getNodeForIndex($this->currentRow);
|
||||
if ($node instanceof CollapsibleNode) {
|
||||
$node->collapse(!$node->isCollapsed());
|
||||
$this->list->parseTree();
|
||||
$this->redrawEditor();
|
||||
}
|
||||
break;
|
||||
|
||||
case "q":
|
||||
Settings::$editorQuotedKeys = !Settings::$editorQuotedKeys;
|
||||
$this->redrawEditor();
|
||||
@ -269,13 +278,12 @@ class Editor
|
||||
|
||||
$readFrom = $this->ask("\e[33mRead from:\e[0m ", "");
|
||||
|
||||
$this->term->setCursor(1, $h);
|
||||
if (!file_exists($readFrom)) {
|
||||
echo "\e[97;41mFile does not exist\e[K\e[0m";
|
||||
$this->showMessage("\e[97;41mFile does not exist");
|
||||
return;
|
||||
}
|
||||
if (!is_readable($readFrom)) {
|
||||
echo "\e[97;41mFile not readable\e[K\e[0m";
|
||||
$this->showMessage("\e[97;41mFile not readable");
|
||||
return;
|
||||
}
|
||||
$ext = strtolower(pathinfo($readFrom, PATHINFO_EXTENSION));
|
||||
@ -288,7 +296,7 @@ class Editor
|
||||
$doc = Yaml::parseFile($readFrom);
|
||||
break;
|
||||
default:
|
||||
echo "\e[97;41mUnable to read format: {$ext}\e[K\e[0m";
|
||||
$this->showMessage("\e[97;41mUnable to read format: {$ext}");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -300,8 +308,7 @@ class Editor
|
||||
$this->list->parseTree();
|
||||
$this->redrawEditor();
|
||||
|
||||
$this->term->setCursor(1, $h);
|
||||
echo "\e[97;42mLoaded {$readFrom}\e[K\e[0m";
|
||||
$this->showMessage("\e[97;42mLoaded {$readFrom}");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -329,8 +336,7 @@ class Editor
|
||||
file_put_contents($saveTo, Yaml::dump($doc));
|
||||
break;
|
||||
default:
|
||||
$this->term->setCursor(1, $h);
|
||||
echo "\e[97;41mUnable to write format: {$ext}\e[K\e[0m";
|
||||
$this->showMessage("\e[97;41mUnable to write format: {$ext}");
|
||||
}
|
||||
|
||||
$this->filename = $saveTo;
|
||||
@ -338,8 +344,7 @@ class Editor
|
||||
$this->modified = false;
|
||||
$this->redrawEditor();
|
||||
|
||||
$this->term->setCursor(1, $h);
|
||||
echo "\e[97;42mWrote to {$saveTo}\e[K\e[0m";
|
||||
$this->showMessage("\e[97;42mWrote to {$saveTo}");
|
||||
|
||||
|
||||
}
|
||||
@ -375,20 +380,20 @@ class Editor
|
||||
## Doing stuff
|
||||
|
||||
### Adding keys or values
|
||||
|
||||
To add a key or a value, navigate to a value in an array or object, or to a specific array or object, and press "i". You will be prompted for the value, and for objects the key.
|
||||
|
||||
You can also press "I" to add arrays and objects. Just select what you want to add in the menu and press enter.
|
||||
|
||||
### Editing keys
|
||||
|
||||
You can edit keys on objects. For this, press "E".
|
||||
|
||||
### Editing values
|
||||
|
||||
To edit a value, press "e". The value is verbatim JSON, so strings should be quoted and all that. Anything that is unparsable JSON will be used as is, resulting in a string.
|
||||
|
||||
### Loading and Saving files
|
||||
To load a file, press ^R and enter the filename to read. To write to a file, press ^W and enter the filename to write to.
|
||||
|
||||
### YAML or JSON?
|
||||
There is no need to select YAML or JSON mode. All operations work the same, and the format is determined on load or save.
|
||||
|
||||
# Disclaimer
|
||||
|
||||
@ -472,8 +477,9 @@ class Editor
|
||||
$this->redrawEditor();
|
||||
}
|
||||
} else {
|
||||
$this->term->setCursor(1, $h);
|
||||
echo "\e[97;41mCan only edit keys on objects\e[K\e[0m";
|
||||
// $this->term->setCursor(1, $h);
|
||||
// echo "\e[97;41mCan only edit keys on objects\e[K\e[0m";
|
||||
$this->showMessage("\e[97;41mCan only edit keys on objects");
|
||||
}
|
||||
|
||||
}
|
||||
@ -505,8 +511,7 @@ class Editor
|
||||
$this->redrawInfoBar();
|
||||
}
|
||||
} else {
|
||||
$this->term->setCursor(1, $h);
|
||||
echo "\e[97;41mCan not edit array/object\e[K\e[0m";
|
||||
$this->showMessage("\e[97;41mCan not edit array/object");
|
||||
}
|
||||
}
|
||||
|
||||
@ -702,4 +707,12 @@ class Editor
|
||||
//echo " \e[1m{$key}\e[2m \e[3m{$info}\e[0m \e[90m\u{2502}\e[0m";
|
||||
}
|
||||
|
||||
private function showMessage(string $message): void
|
||||
{
|
||||
[$w,$h] = $this->term->getSize();
|
||||
$this->term->setCursor(1, $h);
|
||||
echo $message."\e[K\e[0m";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -27,6 +27,8 @@ class Menu
|
||||
|
||||
private int $index = 0;
|
||||
|
||||
private int $scroll = 0;
|
||||
|
||||
public function __construct(private Terminal $terminal, private array $items, private string $title = 'Menu')
|
||||
{
|
||||
|
||||
@ -35,7 +37,16 @@ class Menu
|
||||
public function display(int $left, int $top, int $width, int $height = 0, string|int|null $value): mixed
|
||||
{
|
||||
|
||||
if ($height == 0) $height = count($this->items) + 4;
|
||||
[$w,$h] = $this->terminal->getSize();
|
||||
if ($height == 0) {
|
||||
$height = min($h - 5, count($this->items) + 4);
|
||||
}
|
||||
if ($left == 0) {
|
||||
$left = round(($w - $width) / 2);
|
||||
}
|
||||
if ($top == 0) {
|
||||
$top = round(($h - $height) / 2);
|
||||
}
|
||||
|
||||
$this->redraw($left, $top, $width, $height);
|
||||
|
||||
@ -69,7 +80,15 @@ class Menu
|
||||
}
|
||||
|
||||
private function redraw(int $left, int $top, int $width, int $height) {
|
||||
|
||||
$visibleItems = $height - 4;
|
||||
|
||||
$scrollTop = $this->scroll;
|
||||
$scrollVisible = $visibleItems / count($this->items); // / $visibleItems;
|
||||
$scrollBottom = $scrollTop + $scrollVisible;
|
||||
$thumbTop = round($scrollTop * $visibleItems);
|
||||
$thumbBottom = round($visibleItems * $scrollBottom);
|
||||
|
||||
// draw head
|
||||
echo "\e[40;37m";
|
||||
$this->terminal
|
||||
@ -83,12 +102,23 @@ class Menu
|
||||
for ($n = 0; $n < $visibleItems; $n++) {
|
||||
$key = $keys[$n]??null;
|
||||
$item = " " . ($key ? ($this->items[$key]) : null);
|
||||
$item = $item . str_repeat(" ", $width - 2 - mb_strlen($item)) . "\e[40;37m";
|
||||
$item = $item . str_repeat(" ", $width - 2 - $this->itemlen($item)) . "\e[40;37m";
|
||||
$item = (($n == $this->index)?"\e[37;44m":"\e[40;37m") . $item;
|
||||
if ($n >= $thumbTop && $n <= $thumbBottom) {
|
||||
$scrollbar = "\e[97;1m".self::U_EDGE_VERTICAL_THUMB."\e[40;37;22m";
|
||||
} else {
|
||||
$scrollbar = "\e[37;2m".self::U_EDGE_VERTICAL_SCROLL."\e[40;37;22m";
|
||||
}
|
||||
$this->terminal
|
||||
->writeAt($left, $top + 3 + $n, self::U_EDGE_VERTICAL.$item.self::U_EDGE_VERTICAL_THUMB);
|
||||
->writeAt($left, $top + 3 + $n, self::U_EDGE_VERTICAL.$item.$scrollbar);
|
||||
}
|
||||
echo "\e[0m";
|
||||
}
|
||||
|
||||
private function itemlen(string $item): int
|
||||
{
|
||||
$item = preg_replace('<\e\[.+?m>', '', $item);
|
||||
return mb_strlen($item);
|
||||
}
|
||||
|
||||
}
|
@ -35,7 +35,16 @@ class MessageBox
|
||||
{
|
||||
$wrapped = explode("\n", wordwrap($this->text, $width - 4, cut_long_words:true));
|
||||
|
||||
if ($height == 0) $height = count($wrapped) + 4;
|
||||
[$w,$h] = $this->terminal->getSize();
|
||||
if ($height == 0) {
|
||||
$height = min($h - 5, count($wrapped) + 4);
|
||||
}
|
||||
if ($left == 0) {
|
||||
$left = round(($w - $width) / 2);
|
||||
}
|
||||
if ($top == 0) {
|
||||
$top = round(($h - $height) / 2);
|
||||
}
|
||||
|
||||
$maxScroll = (count($wrapped) > $height) ? count($wrapped) - $height + 4 : 0;
|
||||
|
||||
|
@ -47,12 +47,14 @@ class TreeList implements Countable
|
||||
|
||||
if ($node instanceof ArrayNode) {
|
||||
$index = 0;
|
||||
if ($node->isCollapsed()) return;
|
||||
foreach ($node->items as $item) {
|
||||
$this->parseNode($item, [ ...$path, $key ], $index++);
|
||||
}
|
||||
if (!Settings::$compactGroups)
|
||||
$this->list[$entryKey.'$'] = new Entry(depth: $level, key: $key, node: $node, closer: true);
|
||||
} elseif ($node instanceof ObjectNode) {
|
||||
if ($node->isCollapsed()) return;
|
||||
foreach ($node->properties as $nodekey=>$item) {
|
||||
$this->parseNode($item, [ ...$path, $key ], $nodekey);
|
||||
}
|
||||
@ -172,8 +174,18 @@ class TreeList implements Countable
|
||||
}
|
||||
if ($entry->node instanceof ArrayNode) {
|
||||
echo "[" . (Settings::$compactGroups ? "…]":"");
|
||||
if ($entry->node->isCollapsed()) {
|
||||
echo " \e[90m\u{25ba} \e[2m".count($entry->node->items)."\e[22m";
|
||||
} else {
|
||||
echo " \e[90m\u{25bc}";
|
||||
}
|
||||
} elseif ($entry->node instanceof ObjectNode) {
|
||||
echo "{" . (Settings::$compactGroups ? "…}":"");
|
||||
if ($entry->node->isCollapsed()) {
|
||||
echo " \e[90m\u{25ba} \e[2m".count($entry->node->properties)."\e[22m";
|
||||
} else {
|
||||
echo " \e[90m\u{25bc}";
|
||||
}
|
||||
} elseif ($entry->node instanceof ValueNode) {
|
||||
$value = $entry->node->value;
|
||||
echo match (gettype($value)) {
|
||||
|
Loading…
Reference in New Issue
Block a user