Add duplicate (^D), basic search, bugfixes

* Use ^D to duplicate array items
* Use / to search, matching keys will be highlighted
* Don't attempt to load non-existing files when passed on command line
This commit is contained in:
Chris 2024-10-08 11:04:26 +02:00
parent 1f74bbfc0d
commit ca61374654
4 changed files with 87 additions and 26 deletions

View File

@ -146,21 +146,21 @@ class Editor
break; break;
// FIXME make sure this clones; editing a clone updates original as well // FIXME make sure this clones; editing a clone updates original as well
// case 'd': case "\x04": // ctrl-d
// $node = $this->list->getNodeForIndex($this->currentRow); $node = $this->list->getNodeForIndex($this->currentRow);
// $coll = $this->list->findNearestCollection($this->currentRow, true); $coll = $this->list->findNearestCollection($this->currentRow, true);
// if (!$coll) if (!$coll)
// break; break;
// $collNode = $this->list->getNodeForIndex($coll); $collNode = $this->list->getNodeForIndex($coll);
// if ($collNode instanceof ArrayNode) { if ($collNode instanceof ArrayNode) {
// $collNode->append(clone $node); $collNode->append(clone $node);
// $this->list->parseTree(); $this->modified = true;
// $this->redrawEditor(); $this->list->parseTree();
// } else { $this->redrawEditor();
// $this->term->setCursor(1, $h); } else {
// echo "\e[97;41mCan only duplicate in arrays, node={$this->currentRow}, coll={$coll}\e[K\e[0m"; $this->showMessage("\e[97;41mCan only duplicate in arrays");
// } }
// break; break;
case 'I': case 'I':
$this->doInsertMenu(); $this->doInsertMenu();
@ -259,6 +259,10 @@ class Editor
$this->showMessage("Toggle compact groups (c)"); $this->showMessage("Toggle compact groups (c)");
break; break;
case "/":
$this->doSearch();
break;
case "\x0d": // enter case "\x0d": // enter
$node = $this->list->getNodeForIndex($this->currentRow); $node = $this->list->getNodeForIndex($this->currentRow);
if ($node instanceof ValueNode) { if ($node instanceof ValueNode) {
@ -343,12 +347,25 @@ class Editor
Settings::save(SETTINGS_FILE); Settings::save(SETTINGS_FILE);
// for ($n = 0; $n < 20; $n++) { }
// $this->currentRow = $n;
// $this->redrawEditor();
// sleep(1);
// }
public function doSearch(): void
{
$search = $this->ask("\e[36mSearch: ");
if ($search === null) {
$this->redrawEditor();
return;
}
if ($search === '') {
$this->list->searchResults = [];
} else {
$this->list->searchResults = $this->document->search($search);
}
$this->redrawEditor();
} }
/** /**
@ -1063,6 +1080,7 @@ To get started, press I (shift-i) and add something to the document. Use the arr
E Edit selected key E Edit selected key
Enter Edit string/number, toggle booleans Enter Edit string/number, toggle booleans
D Delete selected key D Delete selected key
^D Duplicate array item
c Toggle compact list view c Toggle compact list view
q Toggle quoted keys in list view q Toggle quoted keys in list view
g Toggle indentation guide lines visibility g Toggle indentation guide lines visibility

View File

@ -36,6 +36,8 @@ class TreeList implements Countable, IteratorAggregate
private const ICON_BOOL_FALSE = "\u{f630}"; private const ICON_BOOL_FALSE = "\u{f630}";
private const ICON_NULL = "\u{f141}"; private const ICON_NULL = "\u{f141}";
public array $searchResults = [];
public function __construct(private Tree $tree) public function __construct(private Tree $tree)
{ {
} }
@ -219,16 +221,20 @@ class TreeList implements Countable, IteratorAggregate
default => self::ICON_STRING, default => self::ICON_STRING,
}." "; }." ";
} }
$keyStyle = "36";
if (in_array($entry->node, $this->searchResults)) {
$keyStyle = "1;97";
}
echo (is_int($entry->key) echo (is_int($entry->key)
?(Settings::$highlightIndices ?(Settings::$highlightIndices
?"\e[36;2m\u{e0b6}\e[7m#{$entry->key}\e[27m\u{e0b4}\e[22;37m " ?"\e[{$keyStyle};2m\u{e0b6}\e[7m#{$entry->key}\e[27m\u{e0b4}\e[22;37m "
:"\e[36;2m#{$entry->key}\e[22;37m " :"\e[{$keyStyle};2m#{$entry->key}\e[22;37m "
) )
:(Settings::$editorQuotedKeys :(Settings::$editorQuotedKeys
? "\e[36m\"{$entry->key}\":\e[37m " ? "\e[{$keyStyle}m\"{$entry->key}\""
: "\e[36m{$entry->key}:\e[37m " : "\e[{$keyStyle}m{$entry->key}"
)); ));
echo ($selected?"\e[22;44;97m":"\e[0;37m").": ";
} }
$node = $entry->node; $node = $entry->node;
if ($node instanceof ArrayNode) { if ($node instanceof ArrayNode) {

View File

@ -43,5 +43,42 @@ class Tree
} }
} }
public function search(string $search): array
{
return $this->searchNode(null, $this->root, $search);
}
/**
*
*
* @return array<Node>
*/
private function searchNode(?string $key, Node $node, string $search): array
{
$results = [];
if ($node instanceof ArrayNode) {
if ($key && str_contains($key, $search)) {
$results[] = $node;
}
foreach ($node->items as $index=>$item) {
$results = [ ...$results, ...$this->searchNode($index, $item, $search) ];
}
} elseif ($node instanceof ObjectNode) {
if ($key && str_contains($key, $search)) {
$results[] = $node;
}
foreach ($node->properties as $key=>$item) {
$results = [ ...$results, ...$this->searchNode($key, $item, $search) ];
}
} elseif ($node instanceof ValueNode) {
if (str_contains($node->value, $search) || ($key && str_contains($key, $search))) {
$results[] = $node;
}
}
return $results;
}
} }

View File

@ -58,7 +58,7 @@ $terminal = new NoccyLabs\JsonEdit\Terminal\Terminal();
Settings::load(SETTINGS_FILE); Settings::load(SETTINGS_FILE);
$editor = new NoccyLabs\JsonEdit\Editor\Editor($terminal); $editor = new NoccyLabs\JsonEdit\Editor\Editor($terminal);
if ($filename) { if ($filename && file_exists($filename)) {
$editor->loadFile($filename); $editor->loadFile($filename);
} else { } else {
$editor->loadDocument((object)[]); $editor->loadDocument((object)[]);