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:
		@@ -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)[]);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user