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:
parent
1f74bbfc0d
commit
ca61374654
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)[]);
|
||||||
|
Loading…
Reference in New Issue
Block a user