From 9ca53df0ecfb896682965c0848a7e6222c03a600 Mon Sep 17 00:00:00 2001 From: Christopher Vagnetoft Date: Tue, 1 Oct 2024 22:51:58 +0200 Subject: [PATCH] Clean up code, add comments --- src/Editor/Editor.php | 284 ++++++++++++++++++++++++++++-------------- 1 file changed, 189 insertions(+), 95 deletions(-) diff --git a/src/Editor/Editor.php b/src/Editor/Editor.php index d3e50a7..9ef0a6d 100644 --- a/src/Editor/Editor.php +++ b/src/Editor/Editor.php @@ -25,6 +25,13 @@ class Editor private ?string $shortfilename = "untitled.json"; + private bool $running = true; + + /** + * Constructor + * + * @param Terminal $term + */ public function __construct(private Terminal $term) { $this->document = new Tree(); @@ -40,6 +47,12 @@ class Editor $this->list = new TreeList($this->document); } + /** + * Read a file into the Tree and TreeList + * + * @param string $filename + * @return void + */ public function loadFile(string $filename): void { $this->filename = $filename; @@ -60,14 +73,23 @@ class Editor $this->list->parseTree(); } + /** + * Load a document from array/object + * + * @param mixed $document + * @return void + */ public function loadDocument(mixed $document): void { $this->document->load($document); $this->list->parseTree(); } - private bool $running = true; - + /** + * Run the editor + * + * @return void + */ public function run() { $this->list->parseTree(); @@ -95,45 +117,11 @@ class Editor break; case 'E': - //$coll = $this->list->findNearestCollection($this->currentRow); - $entry = $this->list->getEntryForIndex($this->currentRow); - $path = $this->list->getPathForIndex($this->currentRow); - $parentIndex = $this->list->getIndexForPath(dirname($path)); - $parent = $this->list->getEntryForIndex($parentIndex); - - if ($parent->node instanceof ObjectNode) { - $newVal = $this->ask("\e[0;33mnew key:\e[0m ", $entry->key); - if ($newVal !== null) { - $entry->key = $newVal; - $this->redrawEditor(); - } - } else { - $this->term->setCursor(1, $h); - echo "\e[97;41mCan only edit keys on objects\e[K\e[0m"; - } + $this->doEditKey(); break; case 'e': - //$coll = $this->list->findNearestCollection($this->currentRow); - $node = $this->list->getNodeForIndex($this->currentRow); - if ($node instanceof ValueNode) { - $val = json_encode($node->value, JSON_UNESCAPED_SLASHES); - $newVal = $this->ask("\e[33;1mnew value:\e[0m ", $val); - if ($newVal !== null) { - $val = json_decode($newVal); - // If the string decodes to null, but isn't 'null', treat it as a string - if ($val === null && $newVal !== 'null') { - $val = $newVal; - } - $node->value = $val; - $this->redrawEditor(); - } else { - $this->redrawInfoBar(); - } - } else { - $this->term->setCursor(1, $h); - echo "\e[97;41mCan not edit array/object\e[K\e[0m"; - } + $this->doEditValue(); break; case '[': @@ -207,66 +195,11 @@ class Editor break; case "\x12": // ctrl-r - $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"; - break; - } - if (!is_readable($readFrom)) { - echo "\e[97;41mFile not readable\e[K\e[0m"; - break; - } - $ext = strtolower(pathinfo($readFrom, PATHINFO_EXTENSION)); - switch ($ext) { - case 'json': - $doc = json_decode(file_get_contents($readFrom)); - break; - case 'yml': - case 'yaml': - $doc = Yaml::parseFile($readFrom); - break; - default: - echo "\e[97;41mUnable to read format: {$ext}\e[K\e[0m"; - break(2); - } - - $this->filename = $readFrom; - $this->shortfilename = basename($readFrom); - - $this->document->load($doc); - $this->currentRow = 0; - $this->list->parseTree(); - $this->redrawEditor(); - - $this->term->setCursor(1, $h); - echo "\e[97;42mLoaded {$readFrom}\e[K\e[0m"; + $this->doReadFile(); break; - case "\x17": // ctrl-w - $saveTo = $this->ask("\e[33mWrite to:\e[0m ", $this->filename); - - $doc = $this->document->save(); - - $this->term->setCursor(1, $h); - - $ext = strtolower(pathinfo($saveTo, PATHINFO_EXTENSION)); - switch ($ext) { - case 'json': - file_put_contents($saveTo, json_encode($doc, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES)."\n"); - break; - case 'yml': - case 'yaml': - $doc = json_decode(json_encode($doc), true); - file_put_contents($saveTo, Yaml::dump($doc)); - break; - default: - echo "\e[97;41mUnable to write format: {$ext}\e[K\e[0m"; - } - - echo "\e[97;42mWrote to {$saveTo}\e[K\e[0m"; + $this->doWriteFile(); break; case null: @@ -286,6 +219,150 @@ class Editor } + /** + * Handler for read file command (ctrl-R) + * + * @return void + */ + private function doReadFile(): void + { + [$w,$h] = $this->term->getSize(); + + $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"; + break; + } + if (!is_readable($readFrom)) { + echo "\e[97;41mFile not readable\e[K\e[0m"; + break; + } + $ext = strtolower(pathinfo($readFrom, PATHINFO_EXTENSION)); + switch ($ext) { + case 'json': + $doc = json_decode(file_get_contents($readFrom)); + break; + case 'yml': + case 'yaml': + $doc = Yaml::parseFile($readFrom); + break; + default: + echo "\e[97;41mUnable to read format: {$ext}\e[K\e[0m"; + break(2); + } + + $this->filename = $readFrom; + $this->shortfilename = basename($readFrom); + + $this->document->load($doc); + $this->currentRow = 0; + $this->list->parseTree(); + $this->redrawEditor(); + + $this->term->setCursor(1, $h); + echo "\e[97;42mLoaded {$readFrom}\e[K\e[0m"; + } + + /** + * Handler for the write file command (ctrl-W) + * + * @return void + */ + private function doWriteFile(): void + { + [$w,$h] = $this->term->getSize(); + + $saveTo = $this->ask("\e[33mWrite to:\e[0m ", $this->filename); + + $doc = $this->document->save(); + + $this->term->setCursor(1, $h); + + $ext = strtolower(pathinfo($saveTo, PATHINFO_EXTENSION)); + switch ($ext) { + case 'json': + file_put_contents($saveTo, json_encode($doc, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES)."\n"); + break; + case 'yml': + case 'yaml': + $doc = json_decode(json_encode($doc), true); + file_put_contents($saveTo, Yaml::dump($doc)); + break; + default: + echo "\e[97;41mUnable to write format: {$ext}\e[K\e[0m"; + } + + echo "\e[97;42mWrote to {$saveTo}\e[K\e[0m"; + + } + + /** + * Edit selected key + * + * @return void + */ + private function doEditKey(): void + { + [$w,$h] = $this->term->getSize(); + + //$coll = $this->list->findNearestCollection($this->currentRow); + $entry = $this->list->getEntryForIndex($this->currentRow); + $path = $this->list->getPathForIndex($this->currentRow); + $parentIndex = $this->list->getIndexForPath(dirname($path)); + $parent = $this->list->getEntryForIndex($parentIndex); + + if ($parent->node instanceof ObjectNode) { + $newVal = $this->ask("\e[0;33mnew key:\e[0m ", $entry->key); + if ($newVal !== null) { + $entry->key = $newVal; + $this->redrawEditor(); + } + } else { + $this->term->setCursor(1, $h); + echo "\e[97;41mCan only edit keys on objects\e[K\e[0m"; + } + + } + + /** + * Edit selected value + * + * @return void + */ + private function doEditValue(): void + { + [$w,$h] = $this->term->getSize(); + + //$coll = $this->list->findNearestCollection($this->currentRow); + $node = $this->list->getNodeForIndex($this->currentRow); + if ($node instanceof ValueNode) { + $val = json_encode($node->value, JSON_UNESCAPED_SLASHES); + $newVal = $this->ask("\e[33;1mnew value:\e[0m ", $val); + if ($newVal !== null) { + $val = json_decode($newVal); + // If the string decodes to null, but isn't 'null', treat it as a string + if ($val === null && $newVal !== 'null') { + $val = $newVal; + } + $node->value = $val; + $this->redrawEditor(); + } else { + $this->redrawInfoBar(); + } + } else { + $this->term->setCursor(1, $h); + echo "\e[97;41mCan not edit array/object\e[K\e[0m"; + } + } + + /** + * Insert a new value + * + * @param mixed $value + * @return void + */ private function doInsertValue(mixed $value = null): void { $coll = $this->list->findNearestCollection($this->currentRow); @@ -325,6 +402,13 @@ class Editor } } + /** + * Ask for input + * + * @param string $prompt + * @param string $value + * @return string|null + */ public function ask(string $prompt, $value = ''): ?string { $plainPrompt = preg_replace('<\e\[.+?m>', '', $prompt); @@ -378,6 +462,11 @@ class Editor } + /** + * Redraw the editor + * + * @return void + */ public function redrawEditor() { [$w,$h] = $this->term->getSize(); @@ -414,6 +503,11 @@ class Editor // echo "\e[90;3m«Empty»\e[0m"; } + /** + * Redraw the info bar + * + * @return void + */ private function redrawInfoBar() { [$w,$h] = $this->term->getSize();