diff --git a/app/Component/ScriptRunner.php b/app/Component/ScriptRunner.php index 923c2ef..3a908c1 100644 --- a/app/Component/ScriptRunner.php +++ b/app/Component/ScriptRunner.php @@ -41,6 +41,16 @@ class ScriptRunner extends AbstractObj public const TYPE_CMD = 'cmd'; public const TYPE_FILE = 'file'; + private const LOAD_KITE_CODE = <<<'TXT' +function load_kite() { + if ($kiteDir = (string)getenv('KITE_PATH')) { + require $kiteDir. '/app/boot.php'; + } +} + +TXT; + + /** * @var bool */ diff --git a/app/Console/Command/CatCommand.php b/app/Console/Command/CatCommand.php new file mode 100644 index 0000000..95e67be --- /dev/null +++ b/app/Console/Command/CatCommand.php @@ -0,0 +1,67 @@ +flags + ->addOpt('type', 't', 'content type. allow: raw, txt, json', 'string', false, 'raw') + ->addArg('source', <<<'TXT' +The source contents. +Special input: + input '@c' or '@cb' or '@clipboard' - will read from Clipboard + input empty or '@i' or '@stdin' - will read from STDIN + input '@FILEPATH' - will read from the filepath +TXT +); + } + + /** + * @param Input $input + * @param Output $output + */ + protected function execute(Input $input, Output $output) + { + $txt = ContentsAutoReader::readFrom($this->flags->getArg('source'), [ + 'throwOnEmpty' => false + ]); + if (!$txt) { + return; + } + + switch ($this->flags->getArg('type')) { + case 'yml': + case 'yaml': + ConfigUtil::readFromString(ConfigBox::FORMAT_YAML, $txt); + break; + case 'raw': + case 'txt': + case 'text': + default: + $output->writeln($txt); + } + } +} diff --git a/app/Console/Component/ContentsAutoReader.php b/app/Console/Component/ContentsAutoReader.php index 0b390d2..67902bb 100644 --- a/app/Console/Component/ContentsAutoReader.php +++ b/app/Console/Component/ContentsAutoReader.php @@ -34,7 +34,7 @@ class ContentsAutoReader extends AbstractObj /** * @param string $source - * @param array $opts + * @param array{print: bool, loadedFile: string, throwOnEmpty: bool} $opts * * @return string */ @@ -52,7 +52,7 @@ public static function readFrom(string $source, array $opts = []): string * - input '@FILEPATH' or FILEPATH - will read from the filepath. * * @param string $source the input text - * @param array{print: bool, loadedFile: string, throwOnEmpty: true} $opts + * @param array{print: bool, loadedFile: string, throwOnEmpty: bool} $opts * * @return string */ diff --git a/app/Console/Component/ContentsAutoWriter.php b/app/Console/Component/ContentsAutoWriter.php index 0a8c6d4..bef3fb5 100644 --- a/app/Console/Component/ContentsAutoWriter.php +++ b/app/Console/Component/ContentsAutoWriter.php @@ -27,12 +27,18 @@ class ContentsAutoWriter /** * @param string $output * @param string $contents + * @param array{printTips: bool} $opts * * @return bool */ - public static function writeTo(string $output, string $contents): bool + public static function writeTo(string $output, string $contents, array $opts = []): bool { - return (new self)->setOutput($output)->write($contents); + return (new self) + ->setOutput($output) + ->withConfig(function (self $writer) use ($opts) { + $writer->setPrintTips($opts['printTips'] ?? true); + }) + ->write($contents); } /** @@ -45,6 +51,17 @@ public function __construct(string $output = '') $this->output = $output; } + /** + * @param callable $fn + * + * @return $this + */ + public function withConfig(callable $fn): self + { + $fn($this); + return $this; + } + /** * @param string $contents * @@ -66,7 +83,7 @@ public function write(string $contents): bool Kite::cliApp()->getOutput()->colored('RESULT:'); } - Kite::cliApp()->getOutput()->writeRaw($contents); + Kite::cliApp()->getOutput()->write($contents); } else { // write to file if ($this->printTips) { @@ -85,7 +102,7 @@ public function write(string $contents): bool /** * @return bool */ - public function IsToStdout(): bool + public function isToStdout(): bool { return !$this->output || in_array($this->output, ['@o', '@stdout'], true); } @@ -100,4 +117,15 @@ public function setOutput(string $output): self $this->output = $output; return $this; } + + /** + * @param bool $printTips + * + * @return ContentsAutoWriter + */ + public function setPrintTips(bool $printTips): self + { + $this->printTips = $printTips; + return $this; +} } diff --git a/app/Console/Controller/ConvertController.php b/app/Console/Controller/ConvertController.php index e0e8c19..54c10df 100644 --- a/app/Console/Controller/ConvertController.php +++ b/app/Console/Controller/ConvertController.php @@ -9,33 +9,26 @@ namespace Inhere\Kite\Console\Controller; +use Inhere\Console\Component\Formatter\JSONPretty; use Inhere\Console\Controller; use Inhere\Console\Exception\PromptException; use Inhere\Console\IO\Output; use Inhere\Kite\Console\Component\Clipboard; use Inhere\Kite\Console\Component\ContentsAutoReader; use Inhere\Kite\Console\Component\ContentsAutoWriter; +use Inhere\Kite\Helper\KiteUtil; use Inhere\Kite\Lib\Convert\JavaProperties; use Inhere\Kite\Lib\Parser\DBTable; -use Inhere\Kite\Lib\Parser\Text\TextParser; -use Inhere\Kite\Lib\Stream\ListStream; use InvalidArgumentException; +use PhpPkg\Config\ConfigUtil; use Symfony\Component\Yaml\Dumper; -use Symfony\Component\Yaml\Parser; use Symfony\Component\Yaml\Yaml; -use Toolkit\FsUtil\File; use Toolkit\PFlag\FlagsParser; use Toolkit\Stdlib\Json; -use function array_pad; -use function array_shift; use function base_convert; use function date; -use function file_get_contents; -use function implode; -use function is_file; use function strlen; use function substr; -use function trim; /** * Class ConvertController @@ -66,6 +59,7 @@ protected static function commandAliases(): array 'tc', 'td', ], + 'yaml2json' => ['yml2json', 'y2j'], 'yaml2prop' => ['yml2prop', 'y2p'], 'prop2yaml' => ['prop2yml', 'p2y'], ]; @@ -115,74 +109,44 @@ public function sql2mdCommand(FlagsParser $fs, Output $output): void $md = DBTable::fromSchemeSQL($source)->toMDTable(); $output->writeRaw($md); - // $cm = new CliMarkdown(); - // $output->println($cm->parse($md)); } /** - * convert formatted text to markdown table - * - * @arguments - * type The target text doc type, allow: raw, md-table, + * convert YAML to JSON contents. * * @options - * -s,--source string;The source code for convert. allow: FILEPATH, @clipboard;true - * -o,--output The output target. default is stdout. - * --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. default is SPACE + * -s,--source The source code. allow: @i,@c,filepath. if is empty, will try read from STDIN + * -o,--output string;The output target, allow: filepath, clipboard, stdout;;stdout * * @param FlagsParser $fs * @param Output $output - * - * @example - * {binWithCmd} -s @c --vn */ - public function textCommand(FlagsParser $fs, Output $output): void + public function yaml2jsonCommand(FlagsParser $fs, Output $output): void { - $text = $fs->getOpt('source'); - $text = ContentsAutoReader::readFrom($text); - - $p = TextParser::new($text); - $p->setItemSep($fs->getOpt('item-sep')); - $p->setFieldNum($fs->getOpt('value-num')); - - if ($vSep = $fs->getOpt('value-sep')) { - $p->setItemParser(TextParser::charSplitParser($vSep)); + $str = ContentsAutoReader::readFrom($fs->getOpt('source')); + $data = ConfigUtil::parseYamlString($str); + if (!$data) { + $output->warning('empty data for convert'); + return; } - $p->parse(); - - switch ($fs->getArg('type')) { - case 'mdtable': - case 'mdTable': - case 'md-table': - $rows = ListStream::new($p->getData()) - ->eachToArray(function (array $item) { - return implode(' | ', $item); - }); - $head = array_shift($rows); - $line = implode('|', array_pad(['-----'], $p->fieldNum, '-----')); - - $result = $head . "\n" . $line . "\n". implode("\n", $rows); - break; - case 'raw': - $result = $text; - break; - default: - $result = Json::pretty($p->getData()); - break; + $echoTip = true; + $outFile = $fs->getOpt('output'); + if (KiteUtil::isStdoutAlias($outFile)) { + $echoTip = false; + $result = JSONPretty::pretty($data); + } else { + $result = Json::pretty($data); } - $outFile = $fs->getOpt('output'); - ContentsAutoWriter::writeTo($outFile, $result); + ContentsAutoWriter::writeTo($outFile, $result, ['printTips' => $echoTip]); } /** * convert YAML to java properties contents. * * @options - * -f,--file The source code file. if is empty, will try read from clipboard + * -s,--source The source code. allow: @i,@c,filepath. if is empty, will try read from STDIN * -o,--output string;The output target, allow: filepath, clipboard, stdout;;stdout * * @param FlagsParser $fs @@ -190,16 +154,8 @@ public function textCommand(FlagsParser $fs, Output $output): void */ public function yaml2propCommand(FlagsParser $fs, Output $output): void { - $file = $fs->getOpt('file'); - - $str = ContentsAutoReader::readFrom($file); - if (!$str) { - throw new InvalidArgumentException('the source yaml contents is empty'); - } - - $parser = new Parser(); - /** @var array $data */ - $data = $parser->parse(trim($str)); + $str = ContentsAutoReader::readFrom($fs->getOpt('source')); + $data = ConfigUtil::parseYamlString($str); if (!$data) { $output->warning('empty data for convert'); return; @@ -209,16 +165,16 @@ public function yaml2propCommand(FlagsParser $fs, Output $output): void $result = $jp->encode($data); $outFile = $fs->getOpt('output'); + $echoTip = !KiteUtil::isStdoutAlias($outFile); - ContentsAutoWriter::writeTo($outFile, $result); - $output->success('Complete'); + ContentsAutoWriter::writeTo($outFile, $result, ['printTips' => $echoTip]); } /** * convert java properties to YAML contents. * * @options - * -f,--file The source code file. if is empty, will try read from clipboard + * -s,--source The source code. allow: @i,@c,filepath. if is empty, will try read from STDIN * -o,--output string;The output target, allow: filepath, clipboard, stdout;;stdout * * @param FlagsParser $fs @@ -226,23 +182,10 @@ public function yaml2propCommand(FlagsParser $fs, Output $output): void */ public function prop2yamlCommand(FlagsParser $fs, Output $output): void { - $file = $fs->getOpt('file'); - if (!$file) { - $str = Clipboard::readAll(); - } else { - if (!is_file($file)) { - throw new PromptException("input source file not exists, file: $file"); - } - - $str = file_get_contents($file); - } - - if (!$str) { - throw new InvalidArgumentException('the source properties contents is empty'); - } - + $str = ContentsAutoReader::readFrom($fs->getOpt('source')); $prop = new JavaProperties(); $data = $prop->decode($str); + if (!$data) { $output->warning('empty data for convert'); return; @@ -252,17 +195,9 @@ public function prop2yamlCommand(FlagsParser $fs, Output $output): void $result = $dumper->dump($data, 1, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK); $outFile = $fs->getOpt('output'); - if (!$outFile || $outFile === 'stdout') { - $output->println($result); - } elseif ($outFile === 'clipboard') { - $output->info('will send result to Clipboard'); - Clipboard::writeString($result); - } else { - $output->info("will write result to $outFile"); - File::putContents($outFile, $result); - } + $echoTip = !KiteUtil::isStdoutAlias($outFile); - $output->success('Complete'); + ContentsAutoWriter::writeTo($outFile, $result, ['printTips' => $echoTip]); } /** diff --git a/app/Console/Controller/GitController.php b/app/Console/Controller/GitController.php index 3e31773..7c7e49a 100644 --- a/app/Console/Controller/GitController.php +++ b/app/Console/Controller/GitController.php @@ -29,6 +29,7 @@ use PhpGit\Repo; use Throwable; use Toolkit\Cli\Cli; +use Toolkit\Cli\Util\Clog; use Toolkit\FsUtil\FS; use Toolkit\PFlag\FlagsParser; use Toolkit\Stdlib\Helper\Assert; @@ -142,15 +143,14 @@ protected function onNotFound(string $action, array $args): bool $this->output->info("input command '$action' is not found, will exec git command: `git $action`"); $c = Cmd::git($action); + $c->withIf(fn() => $c->addArgs(...$args), $args); - if ($args) { - $c->addArgs(...$args); - } + // if ($args) { + // $c->addArgs(...$args); + // } $c->runAndPrint(); - // $run = CmdRunner::new($this->input->getFullScript()); - // $run->do(true); return true; } @@ -417,13 +417,10 @@ public function cloneCommand(FlagsParser $fs, Output $output): void { $repo = $fs->getArg('repo'); $name = $fs->getArg('name'); - $args = $fs->getRawArgs(); - // $dir = $this->flags->getOpt('workdir'); - - $c = Cmd::git('clone'); - // $c->setWorkDir($dir); - $c->setDryRun($this->flags->getOpt('dry-run')); + $c = Cmd::git('clone') + ->setWorkDir($this->flags->getOpt('workdir')) + ->setDryRun($this->flags->getOpt('dry-run')); if ($fs->getOpt('gh')) { $gh = GitHub::new($output); @@ -437,15 +434,14 @@ public function cloneCommand(FlagsParser $fs, Output $output): void $repoUrl = $repo; } - $c->add($repoUrl); - $c->addIf($name, $name); - if ($args) { - $c->addArgs(...$args); - } + $args = $fs->getRemainArgs(); + $c->add($repoUrl) + ->addIf($name, $name) + ->withIf(fn() => $c->addArgs(...$args), $args); $c->runAndPrint(); - $output->success('Complete'); + Clog::info('Complete'); } /** diff --git a/app/Console/routes.php b/app/Console/routes.php index 3765d82..e6b9d2b 100644 --- a/app/Console/routes.php +++ b/app/Console/routes.php @@ -1,4 +1,5 @@ addController(PharController::class); -$app->addAliases('self:update', [ - 'selfupdate', 'self-update', 'updateself', 'update-self', 'upself', 'selfup' -]); +// load simple commands. +require __DIR__ . '/simple-cmds.php'; diff --git a/app/Console/simple-cmds.php b/app/Console/simple-cmds.php new file mode 100644 index 0000000..30f756b --- /dev/null +++ b/app/Console/simple-cmds.php @@ -0,0 +1,40 @@ +addCommand('ln', function ($fs) { + vdump($fs); +}, [ + 'desc' => 'run ln command', + 'options' => [ + 's, src, source' => 'the source file path', + 't, dst, target' => 'the target link file path', + ], +]); + +$app->addCommand('which', function (FlagsParser $fs, Output $output) { + $name = $fs->getArg('binName'); + $path = Sys::findExecutable($name); + if (!$path) { + $output->println('Not found'); + return; + } + + $clean = $fs->getOpt('clean'); + $output->colored($clean ? $path : "Path: $path"); +}, [ + 'desc' => 'find bin file path, like system `which`', + 'aliases' => ['where', 'whereis'], + 'options' => [ + '--clean' => 'bool;clean output, only output path.' + ], + 'arguments' => [ + 'binName' => 'string;the target bin file name for find;true', + ], +]); diff --git a/app/Kite.php b/app/Kite.php index 72a46f2..a3d9bd8 100644 --- a/app/Kite.php +++ b/app/Kite.php @@ -37,13 +37,13 @@ * @method static Dispatcher dispatcher() * @method static ScriptRunner scriptRunner() * - * @see Kite::__callStatic() for quick get object + * @see Kite::__callStatic() for quick get object */ class Kite { use StaticPathAliasTrait; - public const VERSION = '2.0.0'; + public const VERSION = '2.0.1'; public const HOMEPAGE = 'https://github.com/inhere/kite'; public const MODE_CLI = 'cli'; diff --git a/app/func.php b/app/func.php index bb49c1f..7767240 100644 --- a/app/func.php +++ b/app/func.php @@ -11,4 +11,10 @@ function env(string $key, string $default = ''): string { return Toolkit\Stdlib\OS::getEnvStrVal($key, $default); } -} \ No newline at end of file +} + +function load_kite() { + if ($kiteDir = (string)getenv('KITE_PATH')) { + require $kiteDir. '/app/boot.php'; + } +} diff --git a/bin/kite b/bin/kite index 1475f7e..4617af8 100755 --- a/bin/kite +++ b/bin/kite @@ -19,5 +19,14 @@ $app = new CliApplication([ // register routes require dirname(__DIR__) . '/app/Console/routes.php'; +$app->addAliases('self:update', [ + 'selfupdate', + 'self-update', + 'updateself', + 'update-self', + 'upself', + 'selfup' +]); + // start application $app->run(); diff --git a/resource/templates/kite-cmd.tpl b/resource/templates/kite-cmd.tpl new file mode 100644 index 0000000..4c3bc2e --- /dev/null +++ b/resource/templates/kite-cmd.tpl @@ -0,0 +1,41 @@ +<\?php declare(strict_types=1); +/** + * This file is part of Kite. + * + * @link https://github.com/inhere + * @author https://github.com/inhere + * @license MIT + */ + +namespace Inhere\Kite\Console\Command; + +use Inhere\Console\Command; +use Inhere\Console\IO\Input; +use Inhere\Console\IO\Output; + +/** + * Class CatCommand + */ +class CatCommand extends Command +{ + protected static string $name = 'cat'; + + protected static string $desc = 'read and show contents'; + + protected function configure(): void + { + $this->flags + ->addOptsByRules([]); + } + + /** + * @param Input $input + * @param Output $output + */ + protected function execute(Input $input, Output $output) + { + // do something + + $output->write('hello, this in ' . __METHOD__); + } +} diff --git a/script/ls.php b/script/ls.php index b207a2a..26057bd 100644 --- a/script/ls.php +++ b/script/ls.php @@ -4,9 +4,7 @@ use Toolkit\FsUtil\FileFinder; -if ($kiteDir = getenv('KITE_PATH')) { - require $kiteDir. '/app/boot.php'; -} +load_kite(); $args = $_SERVER['argv']; diff --git a/script/update-kite-deps.sh b/script/update-kite-deps.sh index 1c23e17..301175d 100644 --- a/script/update-kite-deps.sh +++ b/script/update-kite-deps.sh @@ -2,7 +2,8 @@ set -ex -#openproxy +# run: kite run update-kite-deps.sh --proxy +# run: sh script/update-kite-deps.sh kite env prox tmpKiteDir=~/Workspace/my-github/inhere/kite diff --git a/script/update-kite-dev.sh b/script/update-kite-dev.sh index 3bd26d0..d5535be 100644 --- a/script/update-kite-dev.sh +++ b/script/update-kite-dev.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash -# run: kite run dev-update-kite-deps.sh --proxy +# run: kite run update-kite-dev.sh --proxy +# run: bash script/update-kite-dev.sh set -ex