From 7e04b6c0011b82566e0db025129a1b3ce0d948e2 Mon Sep 17 00:00:00 2001 From: Christopher Vagnetoft Date: Tue, 8 Feb 2022 01:45:55 +0100 Subject: [PATCH] Various fixes * Fixed the init command not being registered * pdoshell: Improved configuration handling --- .../com.noccy.pdo.shell/Shell/PdoShell.php | 72 ++++++++- .../com.noccy.pdo.shell/Shell/ShellState.php | 138 ++++++++++++++++++ src/SparkApplication.php | 4 +- 3 files changed, 210 insertions(+), 4 deletions(-) create mode 100644 plugins/com.noccy.pdo.shell/Shell/ShellState.php diff --git a/plugins/com.noccy.pdo.shell/Shell/PdoShell.php b/plugins/com.noccy.pdo.shell/Shell/PdoShell.php index 5b2d78d..721531d 100644 --- a/plugins/com.noccy.pdo.shell/Shell/PdoShell.php +++ b/plugins/com.noccy.pdo.shell/Shell/PdoShell.php @@ -29,23 +29,46 @@ class PdoShell { private ?array $lastQuery = null; + private ShellState $state; + #[EnumSetting('output', [ 'table', 'vertical', 'dump' ])] #[EnumSetting('table.style', [ 'box', 'compact', 'borderless' ])] private array $defaultOptions = [ 'output' => 'table', 'table.maxwidth' => 40, 'table.style' => 'box', + 'capture' => false, + 'syntax' => 'none', + ]; + private array $validOptions = [ + 'output' => [ 'table', 'vertical', 'dump' ], + 'table.maxwidth' => 'int', + 'table.style' => [ 'box', 'compact', 'borderless' ], + 'capture' => 'bool', + 'syntax' => [ 'none', 'mysql', 'sqlite' ] ]; public function __construct(OutputInterface $output) { $this->output = $output; + $this->state = new ShellState(); $this->options = $this->defaultOptions; } + public function getState(): ShellState + { + return $this->state; + } + private function promptForCommand() { - $prompt = sprintf("PDO:[%s%s]> ", $this->resource, $this->db?"":"?"); + $info = $this->resource . ($this->db?"":"?"); + + if ($this->getOption('capture')) { + $info .= '][#' . $this->vars['capture_index']; + } + + $prompt = sprintf("PDO:[%s]> ", $info); $input = readline($prompt); return $input; @@ -62,6 +85,11 @@ class PdoShell { ]; } + private function getOption(string $name): mixed + { + return $this->options[$name] ?? null; + } + private function expand(string $string): string { return $string; @@ -125,6 +153,10 @@ class PdoShell { case '.help': $this->doHelpCommand($args); break; + case '.capture': + $this->doSetCommand(['capture', 1]); + $this->doVarCommand(['capture_index', 0]); + break; case '.quit': case '.exit': @@ -211,7 +243,14 @@ class PdoShell { if (empty($varname)) { foreach ($this->options as $var=>$value) { - $this->output->writeln("{$var}: ".var_export($value,true).""); + if (!array_key_exists($var, $this->validOptions)) { + $info = ""; + } elseif (is_array($this->validOptions[$var])) { + $info = "[".join(",", $this->validOptions[$var])."]"; + } else { + $info = "<".$this->validOptions[$var].">"; + } + $this->output->writeln("{$var}: ".var_export($value,true)." ".$info); } return; } @@ -221,6 +260,33 @@ class PdoShell { $this->output->writeln("No such option {$varname}"); return; } + if (array_key_exists($varname, $this->validOptions)) { + $v = $this->validOptions[$varname]; + if (is_array($v)) { + if (!in_array($value, $v)) { + $this->output->writeln("Bad value for {$varname} Valid values: ".join(", ",$v).""); + return; + } + } elseif (is_string($v)) { + switch ($v) { + case 'int': + if (!ctype_digit($value)) { + $this->output->writeln("Bad value for {$varname} Expected integer"); + return; + } + break; + case 'bool': + $true = in_array($value, [ 1, "true", "yes", "on" ]); + $false = in_array($value, [ 0, "false", "no", "off" ]); + if (!$true && !$false) { + $this->output->writeln("Bad value for {$varname} Expected boolean"); + return; + } + $value = $true; + break; + } + } + } $this->options[$varname] = $value; } else { $this->output->writeln(var_export($this->options[$varname]??null,true)); @@ -368,4 +434,4 @@ class EnumSetting { } -} \ No newline at end of file +} diff --git a/plugins/com.noccy.pdo.shell/Shell/ShellState.php b/plugins/com.noccy.pdo.shell/Shell/ShellState.php new file mode 100644 index 0000000..6987e3a --- /dev/null +++ b/plugins/com.noccy.pdo.shell/Shell/ShellState.php @@ -0,0 +1,138 @@ +sessionStorage = new SessionStorage(); + + $this->persistentStorage = new PersistentStorage(); + } + + public function getSessionStorage(): SessionStorage + { + return $this->sessionStorage; + } + + public function getPersistentStorage(): PersistentStorage + { + return $this->persistentStorage; + } + + public function set(string $varname, $value) + { + $this->vars[$varname] = $value; + } + + public function get(string $varname, $default=null): mixed + { + return $this->vars[$varname] ?? $default; + } + + public function expand(string $input): string + { + $expanded = preg_replace_callback('/(%\{(.+?)\})/', function ($m) { + $k = $m[1]; + if (str_contains($k, ':')) { + [$type, $k] = explode(":", $k, 2); + } else { + $type = "var"; + } + switch ($type) { + case 'var': + return $this->get($k, null); + case 'env': + return getenv($k); + } + }, $input); + return $expanded; + } + +} + +class SessionStorage implements StorageInterface +{ + + protected $data = []; + + public function set(string $k, $value) + { + $this->data[$k] = $value; + } + + public function get(string $k, $default=null): mixed + { + return $this->data[$k] ?? $default; + } + + public function has(string $k): bool + { + return array_key_exists($k, $this->data); + } + + public function delete(string $k): void + { + unset($this->data[$k]); + } + +} + +class PersistentStorage implements StorageInterface +{ + + protected $data = []; + + public function set(string $k, $value) + { + $this->data[$k] = $value; + } + + public function get(string $k, $default=null): mixed + { + return $this->data[$k] ?? $default; + } + + public function has(string $k): bool + { + return array_key_exists($k, $this->data); + } + + public function delete(string $k): void + { + unset($this->data[$k]); + } + +} + +interface StorageInterface +{ + public function set(string $k, $value); + + public function get(string $k, $default=null): mixed; + + public function has(string $k): bool; + + public function delete(string $k): void; +} \ No newline at end of file diff --git a/src/SparkApplication.php b/src/SparkApplication.php index f38f784..c0b12f6 100644 --- a/src/SparkApplication.php +++ b/src/SparkApplication.php @@ -48,7 +48,9 @@ class SparkApplication extends Application if (getenv("SPARK_PLUGINS")) { $this->add(new Commands\PluginsCommand()); } - } else { + } + + if (!is_dir(getcwd()."/.spark")) { $this->add(new Commands\InitCommand()); }