diff --git a/src/Editor/Editor.php b/src/Editor/Editor.php index ea46af0..7c6ac7b 100644 --- a/src/Editor/Editor.php +++ b/src/Editor/Editor.php @@ -174,8 +174,8 @@ class Editor 'value' => "Insert Value", 'object' => "Insert Object{}", 'array' => "Insert Array[]", - 'sep0' => "---", - '__paste' => "Paste from clipboard", + //'sep0' => "---", + //'__paste' => "Paste from clipboard", ], 'Insert'); $this->redrawInfoBar([ '^C' => 'Cancel', '↑/↓' => 'Select option', 'Enter' => 'Accept' ]); $sel = $menu->display(0, 0, 30, 0, "value"); @@ -213,6 +213,18 @@ class Editor $this->running = false; break; + case "g": + Settings::$indentationGuides = !Settings::$indentationGuides; + $this->redrawEditor(); + $this->showMessage("Toggle indentation guides (g)"); + break; + + case "b": + Settings::$collapseBefore = !Settings::$collapseBefore; + $this->redrawEditor(); + $this->showMessage("Toggle collapse icon before item (b)"); + break; + case "+": $node = $this->list->getNodeForIndex($this->currentRow); if ($node instanceof CollapsibleNode) { @@ -221,16 +233,36 @@ class Editor $this->redrawEditor(); } break; - + + case "k{LEFT}": + $node = $this->list->getNodeForIndex($this->currentRow); + if ($node instanceof CollapsibleNode) { + $node->collapse(true); + $this->list->parseTree(); + $this->redrawEditor(); + } + break; + + case "k{RIGHT}": + $node = $this->list->getNodeForIndex($this->currentRow); + if ($node instanceof CollapsibleNode) { + $node->collapse(false); + $this->list->parseTree(); + $this->redrawEditor(); + } + break; + case "q": Settings::$editorQuotedKeys = !Settings::$editorQuotedKeys; $this->redrawEditor(); + $this->showMessage("Toggle quoted keys (q)"); break; case "c": Settings::$compactGroups = !Settings::$compactGroups; $this->list->parseTree(); $this->redrawEditor(); + $this->showMessage("Toggle compact groups (c)"); break; case "\x0e": // ctrl-n diff --git a/src/Editor/Menu.php b/src/Editor/Menu.php index b613e26..4a72064 100644 --- a/src/Editor/Menu.php +++ b/src/Editor/Menu.php @@ -39,7 +39,7 @@ class Menu [$w,$h] = $this->terminal->getSize(); if ($height == 0) { - $height = min($h - 5, count($this->items) + 4); + $height = min($h - 5, count($this->items) + 2); } if ($left == 0) { $left = round(($w - $width) / 2); diff --git a/src/List/TreeList.php b/src/List/TreeList.php index 89797f9..a1832f1 100644 --- a/src/List/TreeList.php +++ b/src/List/TreeList.php @@ -5,6 +5,7 @@ namespace NoccyLabs\JsonEdit\List; use Countable; use NoccyLabs\JsonEdit\Settings; use NoccyLabs\JsonEdit\Tree\ArrayNode; +use NoccyLabs\JsonEdit\Tree\CollapsibleNode; use NoccyLabs\JsonEdit\Tree\Tree; use NoccyLabs\JsonEdit\Tree\Node; use NoccyLabs\JsonEdit\Tree\ObjectNode; @@ -15,6 +16,11 @@ class TreeList implements Countable /** @var array */ public array $list = []; + private const TREE_FOLD_OPEN = "\u{f0fe}"; + private const TREE_FOLD_CLOSE = "\u{f146}"; + private const TREE_INDENT_GUIDE = "\u{258f} "; + private const TREE_INDENT = " "; + public function __construct(private Tree $tree) { } @@ -151,7 +157,10 @@ class TreeList implements Countable } echo "\e[{$screenRow};1H\e[0m"; echo ($selected?"\e[44;97m":"\e[0;37m")."\e[K"; - echo "\e[90m".str_repeat("\u{258f} ",$entry->depth)."\e[37m"; + echo "\e[90m".str_repeat( + Settings::$indentationGuides ? self::TREE_INDENT_GUIDE : self::TREE_INDENT, + $entry->depth + )."\e[37m"; if ($entry->closer) { if (!Settings::$compactGroups) { @@ -164,6 +173,18 @@ class TreeList implements Countable return; } + if (Settings::$collapseBefore) { + if ($entry->node instanceof CollapsibleNode) { + if ($entry->node->isCollapsed()) { + //echo "\e[90m\u{25ba} \e[37m"; + echo "\e[90m".self::TREE_FOLD_OPEN." \e[37m"; + } else { + //echo "\e[90m\u{25bc} \e[37m"; + echo "\e[90m".self::TREE_FOLD_CLOSE." \e[37m"; + } + } + } + if (!is_null($entry->key)) { echo (is_int($entry->key) ?"\e[36;2m\u{e0b6}\e[7m#{$entry->key}\e[27m\u{e0b4}\e[22;37m " @@ -175,16 +196,20 @@ 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"; + if (!Settings::$collapseBefore) echo " \e[90m\u{25ba}"; + echo " \e[90;2m[".count($entry->node->items)."]\e[22m"; + if (!Settings::$compactGroups) echo "\e[37m ]"; } else { - echo " \e[90m\u{25bc}"; + if (!Settings::$collapseBefore) echo " \e[90m\u{25bc}"; } } elseif ($entry->node instanceof ObjectNode) { echo "{" . (Settings::$compactGroups ? "…}":""); if ($entry->node->isCollapsed()) { - echo " \e[90m\u{25ba} \e[2m".join(", ",array_keys($entry->node->properties))."\e[22m"; + if (!Settings::$collapseBefore) echo " \e[90m\u{25ba}"; + echo " \e[90;2;3m".join(", ",array_keys($entry->node->properties))."\e[22;23m"; + if (!Settings::$compactGroups) echo "\e[37m }"; } else { - echo " \e[90m\u{25bc}"; + if (!Settings::$collapseBefore) echo " \e[90m\u{25bc}"; } } elseif ($entry->node instanceof ValueNode) { $value = $entry->node->value; diff --git a/src/Settings.php b/src/Settings.php index 755b457..9ac4448 100644 --- a/src/Settings.php +++ b/src/Settings.php @@ -8,12 +8,20 @@ class Settings public static bool $compactGroups = false; + public static bool $indentationGuides = true; + + public static bool $collapseBefore = true; + + public static bool $highlightRow = true; + public static function load(string $filename): void { if (file_exists($filename) && is_readable($filename)) { $data = json_decode(file_get_contents($filename)); self::$editorQuotedKeys = $data->editorQuotedKeys ?? false; self::$compactGroups = $data->compactGroups ?? false; + self::$indentationGuides = $data->indentationGuides ?? true; + self::$collapseBefore = $data->collapseBefore ?? true; } } @@ -22,6 +30,9 @@ class Settings $data = json_encode([ 'editorQuotedKeys' => self::$editorQuotedKeys, 'compactGroups' => self::$compactGroups, + 'indentationGuides' => self::$indentationGuides, + 'collapseBefore' => self::$collapseBefore, + 'highlightRow' => self::$highlightRow, ], JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT)."\n"; @file_put_contents($filename, $data); }