diff --git a/app/Common/GitLocal/GitFlow.php b/app/Common/GitLocal/GitFlow.php new file mode 100644 index 0000000..94d56dd --- /dev/null +++ b/app/Common/GitLocal/GitFlow.php @@ -0,0 +1,13 @@ +showHelp(); + } +} diff --git a/app/Console/Attach/Golang/GenerateStructCmd.php b/app/Console/Attach/Golang/GenerateStructCmd.php new file mode 100644 index 0000000..a18af2e --- /dev/null +++ b/app/Console/Attach/Golang/GenerateStructCmd.php @@ -0,0 +1,150 @@ +addOptsByRules([ + '-n, --name' => 'The struct name', + '--tpl-dir' => 'The tpl dir', + '--tpl-file' => 'The tpl file name', + '--cols, --fields' => 'The field names string, split by ","', + '--get-cols, --only-cols' => 'Only get the provide index cols, start is 0. eg: 1,5', + '-o, --output' => 'The output target. default is stdout.', + '--of, --out-fmt' => 'The output format. allow: raw, md-table', + '--is, --item-sep' => 'The item sep char. default is NL(newline).', + '--vn, --value-num' => 'int;set the item value number(cols number), default get from first item.', + '--vs, --value-sep' => 'The item value sep char for "space" parser. default is SPACE', + '--parser, --item-parser' => [ + 'type' => FlagType::STRING, + 'desc' => 'The item parser name for difference data type. +TYPE: + space, text - parser substr by space, use for text data. + json, json5 - parser json(5) line', + 'default' => 'text', + 'validator' => EnumValidator::new(['json', 'json5', 'text', 'space']) + ] + ]); + + $fs->addOptByRule('s, source', 'The source json,text contents. allow: FILEPATH, @clipboard, @stdin'); + } + + /** + * Do execute command + * + * @param Input $input + * @param Output $output + * + * @return void + */ + protected function execute(Input $input, Output $output): void + { + $fs = $this->flags; + + $source = $this->flags->getOpt('source'); + $source = ContentsAutoReader::readFrom($source); + + $indexes = []; + $idxString = $fs->getOpt('only-cols'); + if ($idxString && !$indexes = Str::toInts($idxString)) { + throw new InvalidArgumentException('please provide valid column index string.'); + } + + $p = TextParser::new($source); + $p->setItemSep($fs->getOpt('item-sep')); + $p->setFieldNum($fs->getOpt('value-num')); + + if ($nameString = $fs->getOpt('fields')) { + $p->setFields(Str::explode($nameString, ',')); + } + + switch ($fs->getOpt('item-parser')) { + case 'json': + case 'json5': + $itemParser = new Json5ItemParser; + break; + case 'text': + case 'space': + default: + $valueSep = $fs->getOpt('value-sep', ' '); + $itemParser = TextItemParser::new($valueSep, $indexes); + break; + } + + $p->setItemParser($itemParser); + $p->parse(); + $data = $p->getData(true); + // $output->aList($data, 'parsed field list'); + + $lang = GenCodeFactory::LANG_GO; + + $config = Kite::cliApp()->getArrayParam('gen_code'); + $tplDir = $fs->getOpt('tpl-dir', $config['tplDir'] ?? ''); + $tplDir = str_replace('{type}', $lang, $tplDir); + + $tplFile = $fs->getOpt('tpl-file'); + if (!$tplFile) { + $tplFile = "$tplDir/struct.tpl"; + } + + $config = array_merge($config, array_filter([ + 'tplDir' => $tplDir, + 'tplFile' => $tplFile, + ])); + + $output->aList($config); + + $gen = GenCodeFactory::create($lang) + ->setClassName($fs->getOpt('name')) + ->addTplVar('genMark', $input->getFullScript(true)) + ->configThis($config) + ->setFields(ListStream::new($data)->eachToArray(function (array $item) { + return JsonField::new($item); + })) + ->setPathResolver([Kite::class, 'resolve']); + + $output->aList($gen->getFields(), 'field list'); + + $result = $gen->generate(); + $outFile = $fs->getOpt('output'); + $output->colored('------------------ Generated Codes -------------------'); + + ContentsAutoWriter::writeTo($outFile, $result); + } +} diff --git a/app/Console/Controller/GoController.php b/app/Console/Controller/GoController.php index dae21d7..39f9b83 100644 --- a/app/Console/Controller/GoController.php +++ b/app/Console/Controller/GoController.php @@ -13,6 +13,7 @@ use Inhere\Console\IO\Input; use Inhere\Console\IO\Output; use Inhere\Kite\Common\CmdRunner; +use Inhere\Kite\Console\Attach\Golang\GenerateCmd; use Toolkit\PFlag\FlagsParser; use function file_get_contents; @@ -36,6 +37,17 @@ protected static function commandAliases(): array 'pkgUp' => [ 'up', 'pkgup' ], + 'generate' => GenerateCmd::aliases(), + ]; + } + + /** + * @return array + */ + protected function subCommands(): array + { + return [ + GenerateCmd::class, ]; } diff --git a/app/Console/Controller/StringController.php b/app/Console/Controller/StringController.php index 2b05b68..e69e691 100644 --- a/app/Console/Controller/StringController.php +++ b/app/Console/Controller/StringController.php @@ -404,13 +404,13 @@ public function replaceCommand(FlagsParser $fs, Output $output): void * * @options * --fields The field names, split by ',' - * --get-cols Only get the provide index cols, eg: 1,5 + * --get-cols Only get the provide index cols, start is 0. eg: 1,5 * -o, --output The output target. default is stdout. * --of, --out-fmt The output format. allow: raw, md-table * --is, --item-sep The item sep char. default is NL. * --vn, --value-num int;The item value number. default get from first line. * --vs, --value-sep The item value sep char for 'space' parser. default is SPACE - * --parser, --item-parser The item parser name. allow: + * --parser, --item-parser The item parser name for difference data type. allow: * space - parser substr by space * json, json5 - parser json(5) line * @@ -481,12 +481,20 @@ public function parseCommand(FlagsParser $fs, Output $output): void /** * decode query string and print data. * + * @options + * --full bool;The input query argument is full url + * * @arguments * query The URI query string. */ public function dequeryCommand(FlagsParser $fs, Output $output): void { $str = $fs->getArg('query'); + $str = rawurlencode($str); + + // if (!$fs->getOpt('full')) { + // $str = 'http://abc.com?' . $str; + // } parse_str($str, $ret); diff --git a/app/Lib/Generate/AbstractGenCode.php b/app/Lib/Generate/AbstractGenCode.php new file mode 100644 index 0000000..7406bba --- /dev/null +++ b/app/Lib/Generate/AbstractGenCode.php @@ -0,0 +1,230 @@ + + */ + protected array $fields = []; + + /** + * @return string + */ + public function getLang(): string + { + return 'java'; + } + + /** + * @return string + */ + public function generate(): string + { + // defaults + $this->contexts['className'] = $this->className; + + return $this->renderTplText(); + } + + /** + * @return string + */ + protected function renderTplText(): string + { + $tplText = $this->readSourceFromFile(); + $settings = array_merge([ + 'lang' => $this->getLang(), + 'user' => OS::getUserName(), + 'date' => date('Y-m-d'), + ], $this->contexts); + + $settings['fields'] = $this->fields; + + return KiteUtil::newTplEngine([ + 'tplDir' => $this->tplDir, + ])->renderString($tplText, $settings); + } + + /** + * @param string $outFile + * + * @return bool + */ + public function generateTo(string $outFile): bool + { + $results = $this->generate(); + $outFile = $this->resolvePath($outFile); + + File::mkdir(dirname($outFile)); + return File::write($results, $outFile); + } + + /** + * @param array $config + * + * @return self + */ + public function configThis(array $config): self + { + Obj::init($this, $config); + + return $this; + } + + /** + * @return string + */ + protected function readSourceFromFile(): string + { + $tplFile = $this->tplFile; + if (!$tplFile) { + return ''; + } + + $tplFile = $this->resolvePath($tplFile); + + // check from tplDir + if ($this->tplDir && !is_file($tplFile)) { + $tplDir = $this->resolvePath($this->tplDir); + $dirFile = File::joinPath($tplDir, $tplFile); + + if (!is_file($dirFile)) { + throw new InvalidArgumentException("No such file: $tplFile"); + } + + $tplFile = $dirFile; + } + + return File::readAll($tplFile); + } + + /** + * @param string $filePath + * + * @return string + */ + public function resolvePath(string $filePath): string + { + if ($fn = $this->pathResolver) { + return $fn($filePath); + } + + // return Kite::alias($filePath); + return $filePath; + } + + /** + * @param string $name + * @param mixed $value + * + * @return $this + */ + public function addTplVar(string $name, mixed $value): self + { + $this->contexts[$name] = $value; + return $this; + } + + /** + * @param array $contexts + * + * @return AbstractJsonToCode + */ + public function setContexts(array $contexts): self + { + if ($contexts) { + $this->contexts = array_merge($this->contexts, $contexts); + } + + return $this; + } + + /** + * @return array + */ + public function getFields(): array + { + return $this->fields; + } + + /** + * @param JsonField[] $fields + * + * @return AbstractGenCode + */ + public function setFields(array $fields): self + { + $this->fields = $fields; + return $this; + } + + /** + * @param callable $pathResolver + * + * @return AbstractJsonToCode + */ + public function setPathResolver(callable $pathResolver): self + { + $this->pathResolver = $pathResolver; + return $this; + } + + /** + * @param string $className + * + * @return AbstractJsonToCode + */ + public function setClassName(string $className): self + { + if ($className) { + $this->className = $className; + } + + return $this; + } +} diff --git a/app/Lib/Generate/AbstractJsonToCode.php b/app/Lib/Generate/AbstractJsonToCode.php index 9594111..a6e5cbc 100644 --- a/app/Lib/Generate/AbstractJsonToCode.php +++ b/app/Lib/Generate/AbstractJsonToCode.php @@ -2,21 +2,14 @@ namespace Inhere\Kite\Lib\Generate; -use Inhere\Kite\Helper\KiteUtil; +use Inhere\Kite\Lib\Generate\Json\JsonField; use InvalidArgumentException; -use Toolkit\FsUtil\File; -use Toolkit\Stdlib\Obj; -use Toolkit\Stdlib\OS; -use function array_merge; -use function date; -use function dirname; -use function is_file; use function trim; /** * class AbstractJsonToCode */ -abstract class AbstractJsonToCode +abstract class AbstractJsonToCode extends AbstractGenCode { /** * @var bool @@ -30,27 +23,6 @@ abstract class AbstractJsonToCode */ protected string $source = ''; - /** - * @var string - */ - public string $tplDir = ''; - - /** - * @var string - */ - public string $tplFile = ''; - - /** - * @var callable - */ - protected $pathResolver; - - /** - * contexts vars for render template - * - * @var array - */ - protected array $contexts = []; /** * @var array @@ -58,22 +30,9 @@ abstract class AbstractJsonToCode // private array $jsonData = []; /** - * @var string - */ - public string $className = 'YourClass'; - - /** - * @var array + * @var array */ - private array $fields = []; - - /** - * @return string - */ - public function getLang(): string - { - return 'java'; - } + // protected array $fields = []; /** * @return string @@ -112,107 +71,6 @@ public function prepare(): self return $this; } - /** - * @return string - */ - protected function renderTplText(): string - { - $tplText = $this->readSourceFromFile(); - $settings = array_merge([ - 'lang' => $this->getLang(), - 'user' => OS::getUserName(), - 'date' => date('Y-m-d'), - ], $this->contexts); - - $settings['fields'] = $this->fields; - - return KiteUtil::newTplEngine([ - 'tplDir' => $this->tplDir, - ])->renderString($tplText, $settings); - } - - /** - * @param string $outFile - * - * @return bool - */ - public function generateTo(string $outFile): bool - { - $results = $this->generate(); - $outFile = $this->resolvePath($outFile); - - File::mkdir(dirname($outFile)); - return File::write($results, $outFile); - } - - /** - * @param array $config - * - * @return self - */ - public function configThis(array $config): self - { - Obj::init($this, $config); - - return $this; - } - - /** - * @return string - */ - protected function readSourceFromFile(): string - { - $tplFile = $this->tplFile; - if (!$tplFile) { - return ''; - } - - $tplFile = $this->resolvePath($tplFile); - - // check from tplDir - if ($this->tplDir && !is_file($tplFile)) { - $tplDir = $this->resolvePath($this->tplDir); - $dirFile = File::joinPath($tplDir, $tplFile); - - if (!is_file($dirFile)) { - throw new InvalidArgumentException("No such file: $tplFile"); - } - - $tplFile = $dirFile; - } - - return File::readAll($tplFile); - } - - /** - * @param string $filePath - * - * @return string - */ - public function resolvePath(string $filePath): string - { - if ($fn = $this->pathResolver) { - return $fn($filePath); - } - - // return Kite::alias($filePath); - return $filePath; - } - - /** - * @param array $contexts - * - * @return AbstractJsonToCode - */ - public function setContexts(array $contexts): self - { - if ($contexts) { - $this->contexts = array_merge($this->contexts, $contexts); - } - - return $this; - } - /** * @param string $source * @@ -224,33 +82,4 @@ public function setSource(string $source): self return $this; } - /** - * @return array - */ - public function getFields(): array - { - return $this->fields; - } - - /** - * @param callable $pathResolver - * - * @return AbstractJsonToCode - */ - public function setPathResolver(callable $pathResolver): self - { - $this->pathResolver = $pathResolver; - return $this; - } - - /** - * @param string $className - * - * @return AbstractJsonToCode - */ - public function setClassName(string $className): self - { - $this->className = $className; - return $this; -} } diff --git a/app/Lib/Generate/GenCodeFactory.php b/app/Lib/Generate/GenCodeFactory.php new file mode 100644 index 0000000..0d16701 --- /dev/null +++ b/app/Lib/Generate/GenCodeFactory.php @@ -0,0 +1,42 @@ + GenPhpClass::class, + self::LANG_JAVA => GenJavaClass::class, + self::LANG_GO => GenGoStruct::class, + ]; + + /** + * @param string $lang + * + * @return AbstractGenCode + */ + public static function create(string $lang = self::LANG_PHP): AbstractGenCode + { + if (!isset(self::LANG2HANDLER_CLASS[$lang])) { + throw new InvalidArgumentException('invalid lang: ' . $lang); + } + + $class = self::LANG2HANDLER_CLASS[$lang]; + + return new $class; + } +} diff --git a/app/Lib/Generate/Handler/GenGoStruct.php b/app/Lib/Generate/Handler/GenGoStruct.php new file mode 100644 index 0000000..8c5f409 --- /dev/null +++ b/app/Lib/Generate/Handler/GenGoStruct.php @@ -0,0 +1,21 @@ +phpType(); } - return $this->javaType(); + if ($lang === LangName::JAVA) { + return $this->javaType(); + } + + if ($lang === LangName::GO) { + return $this->golangType(); + } + + return $this->type; + } + + /** + * @return string + */ + public function golangType(): string + { + if ($this->type === 'long') { + return 'int64'; + } + + return $this->type; } /** diff --git a/app/Lib/Parser/Text/Json5ItemParser.php b/app/Lib/Parser/Text/Json5ItemParser.php index 6f46b1b..c9adb3d 100644 --- a/app/Lib/Parser/Text/Json5ItemParser.php +++ b/app/Lib/Parser/Text/Json5ItemParser.php @@ -19,10 +19,23 @@ class Json5ItemParser /** * exclude fields * - * @var array + * @var array */ public array $exclude = []; + /** + * @param array $exclude + * + * @return static + */ + public static function new(array $exclude = []): self + { + $self = new self(); + + $self->exclude = $exclude; + return $self; + } + /** * @param string $line * diff --git a/app/Lib/Parser/Text/TextItemParser.php b/app/Lib/Parser/Text/TextItemParser.php new file mode 100644 index 0000000..3340e11 --- /dev/null +++ b/app/Lib/Parser/Text/TextItemParser.php @@ -0,0 +1,81 @@ + + */ + public array $indexes = []; + + /** + * Field names. + * + * @var array + */ + public array $fields = []; + + /** + * @param string $valSep + * @param array $indexes + * @param array $fields + * + * @return static + */ + public static function new(string $valSep = ' ', array $indexes = [], array $fields = []): self + { + $self = new self(); + + $self->valSep = TextParser::resolveSep($valSep); + $self->indexes = $indexes; + $self->fields = $fields; + return $self; + } + + /** + * @param string $str + * @param int $fieldNum + * + * @return array + */ + public function __invoke(string $str, int $fieldNum): array + { + $wants = $values = Str::toNoEmptyArray($str, $this->valSep, $fieldNum); + + // only collect given indexes cols. + if ($this->indexes) { + $wants = []; + foreach ($values as $i => $line) { + if (in_array($i, $this->indexes, true)) { + $wants[] = $line; + } + } + } + + $nameNum = count($this->fields); + if ($nameNum > 0) { + // vdump($this->fields, $wants); + $wants = array_combine($this->fields, $wants); + } + + return $wants; + } +} diff --git a/app/Lib/Parser/Text/TextParser.php b/app/Lib/Parser/Text/TextParser.php index 7632bbc..2b81f07 100644 --- a/app/Lib/Parser/Text/TextParser.php +++ b/app/Lib/Parser/Text/TextParser.php @@ -117,7 +117,7 @@ class TextParser * parse one item text to data item * - default item text parser {@see spaceSplitParser} * - * @var callable(string): array + * @var callable(string, int): array */ private $itemParser; @@ -255,6 +255,12 @@ public function prepare(): self } $this->textBody = $text; + + // fallback: init field number from fields list. + if ($this->fieldNum < 1 && $this->fields) { + $this->fieldNum = count($this->fields); + } + return $this; } @@ -333,10 +339,6 @@ protected function parseHeaderSettings(string $header): void break; } } - - if ($this->fields) { - $this->fieldNum = count($this->fields); - } } /** @@ -471,7 +473,7 @@ public function getData(bool $indexToField = false): array } /** - * @param int|string $keyIdxOrName + * @param int|string $keyIdxOrName only collect given index. * @param bool $indexToField replace item value index to field name, require the {@see $fields} * * @return array diff --git a/app/Model/Logic/GitBranchLogic.php b/app/Model/Logic/GitBranchLogic.php index ab2b208..46db618 100644 --- a/app/Model/Logic/GitBranchLogic.php +++ b/app/Model/Logic/GitBranchLogic.php @@ -13,4 +13,9 @@ public function deleteBranches(): array { return []; } + + public function create(): void + { + + } }