diff --git a/app/Common/IdeaHttp/BodyData.php b/app/Common/IdeaHttp/BodyData.php index 2ff2c80..225da5b 100644 --- a/app/Common/IdeaHttp/BodyData.php +++ b/app/Common/IdeaHttp/BodyData.php @@ -4,7 +4,7 @@ use Inhere\Kite\Http\ContentType; use RuntimeException; -use Toolkit\Stdlib\Obj\ConfigObject; +use Toolkit\Stdlib\Obj\DataObject; use Toolkit\Stdlib\Str\UrlHelper; use Toolkit\Stdlib\Type; use function count; @@ -19,7 +19,7 @@ * * @package Inhere\Kite\Common\IdeaHttp */ -class BodyData extends ConfigObject +class BodyData extends DataObject { /** * @var string @@ -190,22 +190,6 @@ public function genMethodParams(int $limitParam = 3): string return implode(', ', $params); } - /** - * @return bool - */ - public function isEmpty(): bool - { - return $this->count() === 0; - } - - /** - * @return string - */ - public function __toString(): string - { - return $this->toString(); - } - /** * @param string $cType * diff --git a/app/Common/IdeaHttp/UrlInfo.php b/app/Common/IdeaHttp/UrlInfo.php index 8cfa6ee..0e3b8d8 100644 --- a/app/Common/IdeaHttp/UrlInfo.php +++ b/app/Common/IdeaHttp/UrlInfo.php @@ -2,7 +2,7 @@ namespace Inhere\Kite\Common\IdeaHttp; -use Toolkit\Stdlib\Obj\ConfigObject; +use Toolkit\Stdlib\Obj\DataObject; use Toolkit\Stdlib\Str; use function basename; use function strpos; @@ -14,7 +14,7 @@ * @see \parse_url() * @package Inhere\Kite\Common\IdeaHttp */ -class UrlInfo extends ConfigObject +class UrlInfo extends DataObject { /** * @param bool $newline diff --git a/app/Component/ClassGenerator.php b/app/Component/ClassGenerator.php new file mode 100644 index 0000000..8b7a484 --- /dev/null +++ b/app/Component/ClassGenerator.php @@ -0,0 +1,13 @@ +getArg('tpl'); + $tplFile = Kite::alias($tplFile); $content = file_get_contents($tplFile); [$varDefine, $template] = explode('###', $content); @@ -97,7 +99,7 @@ public function parseCommand(FlagsParser $fs, Output $output): void if (is_string($var)) { $str = trim($var); // is array - if (strpos($str, '[') === 0) { + if (str_starts_with($str, '[')) { $vars[$k] = Str::explode(trim($str, '[]'), ','); } } diff --git a/app/Console/Controller/GitController.php b/app/Console/Controller/GitController.php index 789a56c..5578e9f 100644 --- a/app/Console/Controller/GitController.php +++ b/app/Console/Controller/GitController.php @@ -29,7 +29,7 @@ use PhpGit\Repo; use Throwable; use Toolkit\PFlag\FlagsParser; -use Toolkit\Stdlib\Obj\ConfigObject; +use Toolkit\Stdlib\Obj\DataObject; use Toolkit\Stdlib\Str; use function abs; use function array_keys; @@ -54,9 +54,9 @@ class GitController extends Controller protected static $description = 'Provide useful tool commands for quick use git'; /** - * @var ConfigObject + * @var DataObject */ - private ConfigObject $settings; + private DataObject $settings; public static function aliases(): array { @@ -113,7 +113,7 @@ protected function options(): array protected function beforeRun(): void { if ($this->app && !isset($this->settings)) { - $this->settings = ConfigObject::new($this->app->getArrayParam('git')); + $this->settings = DataObject::new($this->app->getArrayParam('git')); } if ($workdir = $this->flags->getOpt('workdir')) { diff --git a/app/Console/Controller/JsonController.php b/app/Console/Controller/JsonController.php index 52c1b36..95c12ae 100644 --- a/app/Console/Controller/JsonController.php +++ b/app/Console/Controller/JsonController.php @@ -62,7 +62,6 @@ protected static function commandAliases(): array ]; } - protected function init(): void { parent::init(); @@ -292,18 +291,36 @@ public function ml2lineCommand(): void } /** - * convert JSON object string to PHP class. + * convert JSON object string to PHP/JAVA DTO class. * * @options - * --cb bool;read input from clipboard - * -f,--file The source markdown code - * -o,--output The output target. default is stdout. + * -s, --source The source json contents + * -o, --output The output target. default is STDOUT. + * -t, --type string;the generate code language type, allow: java, php;;php * * @param FlagsParser $fs * @param Output $output + * + * @throws JsonException */ public function toClassCommand(FlagsParser $fs, Output $output): void { + $json = $fs->getArg('json'); + $json = ContentsAutoReader::readFrom($json, [ + 'loadedFile' => $this->dumpfile, + ]); + + if (!$json = trim($json)) { + throw new InvalidArgumentException('empty input json(5) text for handle'); + } + + if ($json[0] !== '{') { + $json = '{' . $json . '}'; + } + + $data = json_decode($json, true, 512, JSON_THROW_ON_ERROR); + + $output->success('Complete'); } diff --git a/app/Console/Controller/PhpController.php b/app/Console/Controller/PhpController.php index 6e00cee..6b51f95 100644 --- a/app/Console/Controller/PhpController.php +++ b/app/Console/Controller/PhpController.php @@ -14,10 +14,12 @@ use Inhere\Console\Exception\PromptException; use Inhere\Console\IO\Output; use Inhere\Console\Util\PhpDevServe; +use Inhere\Kite\Common\Cmd; use Inhere\Kite\Common\CmdRunner; use Inhere\Kite\Common\GitLocal\GitHub; use Inhere\Kite\Console\Component\Clipboard; use Inhere\Kite\Helper\AppHelper; +use Inhere\Kite\Helper\KiteUtil; use InvalidArgumentException; use Toolkit\PFlag\FlagsParser; use Toolkit\Stdlib\Json; @@ -26,9 +28,11 @@ use function addslashes; use function array_filter; use function array_merge; +use function dirname; use function function_exists; use function implode; use function is_dir; +use function is_file; use function is_numeric; use function ob_get_clean; use function ob_start; @@ -58,6 +62,7 @@ protected static function commandAliases(): array 'pkgOpen' => ['open', 'pkg-open'], 'runCode' => ['eval', 'run-code', 'run-codes'], 'runFunc' => ['run', 'exec', 'run-func'], + 'runUnit' => ['run-unit', 'unit', 'run-test', 'phpunit'], ]; } @@ -82,8 +87,37 @@ public function str2arrCommand(FlagsParser $fs, Output $output): void * convert create mysql table SQL to PHP class * * @options - * --cb bool;read source code from clipboard - * -f,--file The source code file + * -s,--source The source code string or file + * -o,--output The output target. default is stdout. + * + * @param FlagsParser $fs + * @param Output $output + */ + public function text2classCommand(FlagsParser $fs, Output $output): void + { + $output->success('Complete'); + } + + /** + * convert create mysql table SQL to PHP class + * + * @options + * -s,--source The source code string or file + * -o,--output The output target. default is stdout. + * + * @param FlagsParser $fs + * @param Output $output + */ + public function arr2classCommand(FlagsParser $fs, Output $output): void + { + $output->success('Complete'); + } + + /** + * convert create mysql table SQL to PHP class + * + * @options + * -s,--source The source code string or file * -o,--output The output target. default is stdout. * * @param FlagsParser $fs @@ -98,8 +132,7 @@ public function json2classCommand(FlagsParser $fs, Output $output): void * convert create mysql table SQL to PHP class * * @options - * --cb bool;read source code from clipboard - * -f,--file The source code file + * -s,--source The source code string or file * -o,--output The output target. default is stdout. * * @param FlagsParser $fs @@ -114,7 +147,7 @@ public function sql2classCommand(FlagsParser $fs, Output $output): void * convert an mysql INSERT SQL to php k-v array * * @options - * -f,--file The source markdown code + * -s,--source The source code string or file * -o,--output The output target. default is stdout. * * @param FlagsParser $fs @@ -125,6 +158,46 @@ public function sql2arrCommand(FlagsParser $fs, Output $output): void $output->success('Complete'); } + /** + * auto find the phpunit.xml dir and run phpunit tests + * + * @arguments + * dir The php unit tests code dir or file path + * + * @options + * --no-debug bool;not set the --debug option on run test + * -f, --filter Set the --filter option for phpunit + * --php-bin manual set the php bin file path. + * --phpunit manual set the phpunit(.phar) file path. + * + * @param FlagsParser $fs + * @param Output $output + */ + public function runUnitCommand(FlagsParser $fs, Output $output): void + { + $dir = $fs->getOpt('dir', $this->getInput()->getWorkDir()); + if (is_file($dir)) { + $dir = dirname($dir); + } + + $runDir = KiteUtil::findPhpUnitConfigFile($dir); + if (!$runDir) { + throw new InvalidArgumentException("not found the phpunit.xml(.dist) in $dir or any parent dir"); + } + + // phpunit --debug --filter KEYWORDS + $cmd = Cmd::new('phpunit'); + $cmd->addIf('--debug', !$fs->getOpt('no-debug')); + + if ($filter = $fs->getOpt('filter')) { + $cmd->addArgs('--filter', $filter); + } + + $cmd->runAndPrint(); + + $output->success('Complete'); + } + /** * run php-cs-fixer for an dir, and auto add git commit message * @@ -268,6 +341,7 @@ public function serveCommand(FlagsParser $fs, Output $output): void * * @example * {binWithCmd} strlen "inhere" # output: 6 + * {binWithCmd} basename refs/heads/master # output: master * */ public function runFuncCommand(FlagsParser $fs, Output $output): void diff --git a/app/Console/Controller/StringController.php b/app/Console/Controller/StringController.php index 1595c5b..ff9dcff 100644 --- a/app/Console/Controller/StringController.php +++ b/app/Console/Controller/StringController.php @@ -24,6 +24,7 @@ use function explode; use function implode; use function is_file; +use function parse_str; use function preg_match; use function str_contains; use function str_replace; @@ -354,6 +355,21 @@ public function fieldsCommand(FlagsParser $fs, Output $output): void $output->aList($fields); } + /** + * decode query string and print data. + * + * @arguments + * query The URI query string. + */ + public function dequeryCommand(FlagsParser $fs, Output $output): void + { + $str = $fs->getArg('query'); + + parse_str($str, $ret); + + $output->aList($ret); + } + /** * Change case for input string. * diff --git a/app/Helper/KiteUtil.php b/app/Helper/KiteUtil.php index 2e1531c..7087495 100644 --- a/app/Helper/KiteUtil.php +++ b/app/Helper/KiteUtil.php @@ -2,7 +2,36 @@ namespace Inhere\Kite\Helper; +use function dirname; +use function is_file; + +/** + * class KiteUtil + */ class KiteUtil { + /** + * @param string $dir + * + * @return string + */ + public static function findPhpUnitConfigFile(string $dir): string + { + while (true) { + if (!$dir) { + break; + } + + if ( + is_file($dir . '/phpunit.xml') || + is_file($dir . '/phpunit.xml.dist') + ) { + break; + } + + $dir = dirname($dir); + } + return $dir; + } } diff --git a/app/Lib/Parser/IniParser.php b/app/Lib/Parser/IniParser.php new file mode 100644 index 0000000..1a67876 --- /dev/null +++ b/app/Lib/Parser/IniParser.php @@ -0,0 +1,142 @@ +parse($str); + } + + /** + * parse ini string. + * + * - ignores commented lines that start with ";" or "#" + * - ignores broken lines that do not have "=" + * - supports array values and array value keys + * - supports inline array value + * + * @param string $str + * + * @return array + * @url https://www.php.net/manual/en/function.parse-ini-string.php#111845 + */ + public function parse(string $str): array + { + if (!$str = trim($str)) { + return []; + } + + $ret = []; + $lines = explode("\n", $str); + + $sectionName = ''; + foreach ($lines as $line) { + $line = trim($line); + + // empty or comments line + if (!$line || $line[0] === "#" || $line[0] === ";") { + continue; + } + + // section line. eg: [arrayName] + if ($line[0] === '[' && $endIdx = strpos($line, ']')) { + $sectionName = substr($line, 1, $endIdx - 1); + continue; + } + + // invalid line + if (!strpos($line, '=')) { + continue; + } + + $tmp = explode('=', $line, 2); + $key = rtrim($tmp[0]); + $val = ltrim($tmp[1]); + + // inline array value. eg: tags=[abc, 234] + if ($val && $val[0] === '[' && str_ends_with($val, ']')) { + $val = Str::splitTrimmed(substr($val, 1, - 1)); + } + + // in section. eg: [arrayName] -> $sectionName='arrayName' + if ($sectionName) { + // remove quote chars + if (preg_match("/^\".*\"$/", $val) || preg_match("/^'.*'$/", $val)) { + $val = mb_substr($val, 1, -1); + } + + // is array. + // eg: val_arr[] = "arr_elem_one" + // eg: val_arr_two[some_key] = "some_key_value" + // $t = preg_match("^\[(.*?)\]^", $key, $matches); + $ok = preg_match("^\[(.*?)]^", $key, $matches); + if ($ok === 1 && isset($matches[0])) { + // $arr_name = preg_replace('#\[(.*?)\]#is', '', $key); + [$arrName, $subKey] = explode('[', trim($key, ']')); + + if (!isset($ret[$sectionName][$arrName]) || !is_array($ret[$sectionName][$arrName])) { + $ret[$sectionName][$arrName] = []; + } + + if ($subKey !== '') { + $ret[$sectionName][$arrName][$subKey] = $val; + } else { // eg: val_arr[] = "arr_elem_one" + $ret[$sectionName][$arrName][] = $val; + } + } else { + $ret[$sectionName][$key] = $val; + } + } else { + $ret[$key] = $val; + } + } + + return $ret; + } + + protected function removeQuotes(string $str): string + { + if (preg_match("/^\".*\"$/", $str) || preg_match("/^'.*'$/", $str)) { + return mb_substr($str, 1, -1); + } + + return $str; + } + + protected function str2array(string $str): array + { + if (!$str) { + return []; + } + + $arr = Str::splitTrimmed(substr($str, 1, - 1)); + foreach ($arr as $val) { + if (is_numeric($val) && strlen($val) < 11) { + + } + } + + return $arr; + } +} diff --git a/app/Lib/Parser/TextParser.php b/app/Lib/Parser/TextParser.php index 0c71e9f..478d691 100644 --- a/app/Lib/Parser/TextParser.php +++ b/app/Lib/Parser/TextParser.php @@ -117,7 +117,6 @@ public function parse(string $text): self $this->text = $text; $text = trim($text, $this->lineSep); - if (str_contains($text, $this->headerSep)) { [$header, $text] = explode($this->headerSep, $text); @@ -138,6 +137,11 @@ public function parse(string $text): self continue; } + // is not contains fieldSep + // if (!str_contains($line, $this->fieldSep)) { + // continue; + // } + // do filtering line text if ($filterFn && !($line = $filterFn($line))) { continue; @@ -147,7 +151,7 @@ public function parse(string $text): self if ($parserFn) { $values = $parserFn($line, $fieldNum); } else { // default parser func - $values = $this->applyParser($line); + $values = $this->applyDefaultParser($line); } $this->collectRow($fieldNum, $values); @@ -170,6 +174,9 @@ protected function parseHeader(string $header): void [$key, $value] = Str::explode($line, '='); switch ($key) { + case 'fieldNum': + $this->fieldNum = (int)$value; + break; case 'fields': $this->fieldNames = Str::explode($value, ','); break; @@ -240,6 +247,9 @@ public function each(callable $handlerFn): void } } + /** + * @return Closure + */ public static function spaceSplitParser(): Closure { return static function (string $line, int $fieldNum) { @@ -252,7 +262,7 @@ public static function spaceSplitParser(): Closure $values = array_slice($nodes, 0, $fieldNum - 1); $others = array_slice($nodes, $fieldNum - 1); - // merge others as last ele + // merge others as last elem $values[] = implode(' ', $others); return $values; }; @@ -263,7 +273,7 @@ public static function spaceSplitParser(): Closure * * @return array */ - public function applyParser(string $rawLine): array + public function applyDefaultParser(string $rawLine): array { $values = explode($this->fieldSep, $rawLine, $this->fieldNum); diff --git a/plugin/AddCommentsToJson5.php b/plugin/AddCommentsToJson5.php new file mode 100644 index 0000000..b4021c1 --- /dev/null +++ b/plugin/AddCommentsToJson5.php @@ -0,0 +1,161 @@ + 'add field comments for text(eg: json5) contents', + 'example' => 'kite plug AddComments2Json -- -h' + ]; + } + + protected function options(): array + { + return [ + 's,source' => [ + 'desc' => 'the source json contents, allow: FILEPATH, @stdin, @clipboard', + 'helpType' => 'SOURCE', + ], + 'l, list' => 'bool;list the field comments data map', + 'm, map-file' => 'the field comments data map file;true', + // 'w, map-file' => 'the field comments data map file;true', + 'c, case' => 'want change field case', + 'output,o' => 'write formatted result to output, default is STDOUT. +if equals @source will write to the source FILEPATH' + ]; + } + + /** + * @var array + */ + private array $exclude = []; + + /** + * @var array + */ + private array $mapData = []; + + /** + * @param Application $app + * @param Input $input + */ + public function exec(Application $app, Input $input): void + { + $mapFile = $this->fs->getOpt('map-file'); + $this->loadMapData($mapFile); + + // vdump($this->mapData); + $app->colored('Loaded fields count: ' . count($this->mapData)); + if ($this->fs->getOpt('list')) { + $app->getOutput()->aList($this->mapData, 'Fields'); + return; + } + + $source = $this->fs->getOpt('source'); + + $reader = ContentsAutoReader::new(); + $srcText = $reader->read($source); + + $fmtLines = []; + foreach (explode("\n", $srcText) as $line) { + $trimmed = trim($line); + if (!$trimmed || str_contains($trimmed, '//')) { + $fmtLines[] = $line; + continue; + } + + if (preg_match('/[a-zA-Z][\w_]+/', $trimmed, $matches)) { + // vdump($matches); + $field = $matches[0]; + + // add comments + if (isset($this->mapData[$field]) && !in_array($field, $this->exclude, true)) { + $line .= ' // ' . $this->mapData[$field]; + } + } + + $fmtLines[] = $line; + } + + $result = implode("\n", $fmtLines); + $output = $this->fs->getOpt('output'); + + if ($output === '@c' || $output === '@cb' || $output === '@clipboard') { + Clipboard::writeString($result); + } else { + $app->getOutput()->writeRaw($result); + } + } + + protected function loadMapData(string $mapFile): void + { + $settings = ''; + $mapText = File::readAll(Kite::alias($mapFile)); + + if (str_contains($mapText, "\n###")) { + [$settings, $mapText] = explode("\n###", $mapText); + } else { + $mapText = trim($mapText); + } + + if ($settings) { + foreach (explode("\n", $settings) as $line) { + if (!$line = trim($line)) { + continue; + } + + if (!str_contains($line, '=')) { + continue; + } + + // is comments line + if (str_starts_with($line, '#') || str_starts_with($line, '//')) { + continue; + } + + [$key, $value] = Str::explode($line, '='); + switch ($key) { + case 'exclude': + $this->exclude = Str::explode($value, ','); + break; + } + } + } + + // load fields + foreach (explode("\n", $mapText) as $line) { + if (!$line = trim($line)) { + continue; + } + + if (!str_contains($line, ' ')) { + continue; + } + + // is comments line + if (str_starts_with($line, '#') || str_starts_with($line, '//')) { + continue; + } + + [$field, $desc] = Str::explode($line, ' ', 2); + if ($field && $desc) { + $field = str_contains($field, '_') ? Str::toCamelCase($field) : $field; + // add + $this->mapData[$field] = $desc; + } + } + } +} diff --git a/resource/awesome.md b/resource/awesome.md index 87ea800..e038cac 100644 --- a/resource/awesome.md +++ b/resource/awesome.md @@ -7,4 +7,5 @@ **theme** +- https://bschwarz.github.io/puml-themes/gallery.html - https://the-lum.github.io/puml-themes-gallery/#bluegray \ No newline at end of file diff --git a/resource/example/gen-go-funcs.tpl b/resource/example/gen-go-funcs.tpl new file mode 100644 index 0000000..0a9bed2 --- /dev/null +++ b/resource/example/gen-go-funcs.tpl @@ -0,0 +1,14 @@ +# +# usage: kite gen parse @kite/resource/example/gen-go-funcs.tpl +# +vars=[Info, Error, Warn] + +### + + +// f print message with style +func f(format string, a ...interface{}) { + .Printf(format, a...) +} + + \ No newline at end of file diff --git a/resource/example/gen-php-dto-class.tpl b/resource/example/gen-php-dto-class.tpl new file mode 100644 index 0000000..8911581 --- /dev/null +++ b/resource/example/gen-php-dto-class.tpl @@ -0,0 +1,36 @@ +# +# usage: kite gen parse @kite/resource/example/gen-php-dto-class.tpl +# +strProps=[project, repoPath, projectId, homepage, lastCid] +arrProps=[prInfo,lastValid] +intProps=[commitNum] +class=MyClass + +### + +class + +{ + + + /** + * @param int + */ + public $ = 0; + + + + /** + * @param string + */ + public $ = ''; + + + + /** + * @param array + */ + public $ = []; + + +} \ No newline at end of file diff --git a/resource/examples/md2sql.md b/resource/example/md2sql.md similarity index 100% rename from resource/examples/md2sql.md rename to resource/example/md2sql.md diff --git a/resource/example/puml-testdot.puml b/resource/example/puml-testdot.puml new file mode 100644 index 0000000..dee623f --- /dev/null +++ b/resource/example/puml-testdot.puml @@ -0,0 +1,3 @@ +@startuml +testdot +@enduml diff --git a/resource/example/puml-themes.puml b/resource/example/puml-themes.puml new file mode 100644 index 0000000..cf5e501 --- /dev/null +++ b/resource/example/puml-themes.puml @@ -0,0 +1,3 @@ +@startuml +help theme +@enduml