From 0e5a25567c5df98e1e6e0e8b7d5e6148248670fc Mon Sep 17 00:00:00 2001 From: Christopher Vagnetoft Date: Mon, 21 Nov 2016 01:26:06 +0100 Subject: [PATCH] Added exception handling to run() --- README.md | 12 +++++++ lib/Shell.php | 93 +++++++++++++++++++++++++++------------------------ 2 files changed, 61 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index e69de29..61be340 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,12 @@ +NoccyLabs Shell Core +==================== + +This library helps make elegant command line applications that spawn an isolated shell. +It uses a standalone implementation for buffered input with support for arrow keys to +navigate the history and more. + +Note that this library requirements a fully ANSI compatible terminal with UTF-8 support +in order to use colors, control the cursor position etc. As it uses `stty` to configure +input buffering, it will likely not work on Windows. + + diff --git a/lib/Shell.php b/lib/Shell.php index 8f067ad..99509c9 100644 --- a/lib/Shell.php +++ b/lib/Shell.php @@ -321,57 +321,62 @@ class Shell public function run() { - $this->lineReader = new LineRead(); + try { + $this->lineReader = new LineRead(); - $this->lineReader->setPromptText($this->prompt); - $this->lineReader->setPromptStyle(new Style(Style::BR_GREEN)); - $this->lineReader->setCommandStyle(new Style(Style::GREEN)); + $this->lineReader->setPromptText($this->prompt); + $this->lineReader->setPromptStyle(new Style(Style::BR_GREEN)); + $this->lineReader->setCommandStyle(new Style(Style::GREEN)); - $this->running = true; + $this->running = true; - $this->dispatchEvent("prompt", [ "context"=>$this->context ]); + $this->dispatchEvent("prompt", [ "context"=>$this->context ]); - while ($this->running) { - // Update the input stuff, sleep if nothing to do. - if (!($buffer = $this->lineReader->update())) { - usleep(10000); - } - // Escape is handy too... - if ($buffer == "\e") { - $this->dispatchEvent("shell.abort"); - continue; - } - // we get a ^C on ^C, so deal with the ^C. - if ($buffer == "\x03") { - $this->dispatchEvent("shell.stop"); - $this->stop(); - continue; - } - // Execute the buffer - ob_start(); - $this->dispatchEvent("update"); - foreach ($this->timers as $timer) { - $timer->update(); - } - if ($buffer) { - $this->executeBuffer($buffer); - } - $output = ob_get_contents(); - ob_end_clean(); + while ($this->running) { + // Update the input stuff, sleep if nothing to do. + if (!($buffer = $this->lineReader->update())) { + usleep(10000); + } + // Escape is handy too... + if ($buffer == "\e") { + $this->dispatchEvent("shell.abort"); + continue; + } + // we get a ^C on ^C, so deal with the ^C. + if ($buffer == "\x03") { + $this->dispatchEvent("shell.stop"); + $this->stop(); + continue; + } + // Execute the buffer + ob_start(); + $this->dispatchEvent("update"); + foreach ($this->timers as $timer) { + $timer->update(); + } + if ($buffer) { + $this->executeBuffer($buffer); + } + $output = ob_get_contents(); + ob_end_clean(); - if (trim($output)) { - $this->lineReader->erase(); - echo rtrim($output)."\n"; - $this->lineReader->redraw(); + if (trim($output)) { + $this->lineReader->erase(); + echo rtrim($output)."\n"; + $this->lineReader->redraw(); + } + + if (!$this->context) { + $this->stop(); + } + + if ($buffer) { + $this->dispatchEvent("prompt", [ "context"=>$this->context ]); + } } - if (!$this->context) { - $this->stop(); - } - - if ($buffer) { - $this->dispatchEvent("prompt", [ "context"=>$this->context ]); - } + } catch (\Exception $e) { + fprintf(STDERR, "\e[31;1mFatal: Unhandled exception\e[0m\n\n%s\n", $e); } $this->lineReader = null;