refactor(cli): migrate 64 legacy scripts to CliFramework (#235)
Platform: moko-platform CI / Gate 2: Unit Tests (8.1) (push) Blocked by required conditions
Platform: moko-platform CI / Gate 2: Unit Tests (8.2) (push) Blocked by required conditions
Platform: moko-platform CI / Gate 2: Unit Tests (8.3) (push) Blocked by required conditions
Platform: moko-platform CI / Gate 3: Self-Health Check (push) Blocked by required conditions
Platform: moko-platform CI / Gate 4: Governance (push) Blocked by required conditions
Platform: moko-platform CI / Gate 5: Template Integrity (push) Blocked by required conditions
Platform: moko-platform CI / CI Summary (push) Blocked by required conditions
Generic: Repo Health / Release configuration (push) Blocked by required conditions
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Platform: moko-platform CI / Gate 1: Code Quality (push) Failing after 36s
Platform: moko-platform CI / Gate 2: Unit Tests (8.1) (push) Blocked by required conditions
Platform: moko-platform CI / Gate 2: Unit Tests (8.2) (push) Blocked by required conditions
Platform: moko-platform CI / Gate 2: Unit Tests (8.3) (push) Blocked by required conditions
Platform: moko-platform CI / Gate 3: Self-Health Check (push) Blocked by required conditions
Platform: moko-platform CI / Gate 4: Governance (push) Blocked by required conditions
Platform: moko-platform CI / Gate 5: Template Integrity (push) Blocked by required conditions
Platform: moko-platform CI / CI Summary (push) Blocked by required conditions
Generic: Repo Health / Release configuration (push) Blocked by required conditions
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Platform: moko-platform CI / Gate 1: Code Quality (push) Failing after 36s
Wrap all CLI tools in cli/, automation/, maintenance/, deploy/, and release/ in classes extending CliFramework. Replaces manual $argv parsing with configure()/addArgument(), moves logic into run(): int, and converts fwrite(STDERR,...) to $this->log(). Two CLIApp subclasses (generate_dolibarr_version_txt, generate_joomla_update_xml) converted to extend CliFramework directly. Every script now gets free --help, --verbose, --quiet, --dry-run, --json, --no-color, banners, coloured logging, and progress bars. Authored-by: Moko Consulting Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* FILE INFORMATION
|
||||
* DEFGROUP: moko-platform.CLI
|
||||
* INGROUP: moko-platform
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
|
||||
* PATH: /cli/completion.php
|
||||
* BRIEF: Generate bash/zsh tab completion scripts for bin/moko
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/../lib/Enterprise/CliFramework.php';
|
||||
|
||||
use MokoEnterprise\CliFramework;
|
||||
|
||||
class CompletionCli extends CliFramework
|
||||
{
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('Generate bash/zsh tab completion scripts for bin/moko');
|
||||
$this->addArgument('--shell', 'Shell type: bash or zsh', 'bash');
|
||||
}
|
||||
|
||||
protected function run(): int
|
||||
{
|
||||
$shell = $this->getArgument('--shell');
|
||||
|
||||
// Also accept positional-style: check raw argv for bash/zsh
|
||||
global $argv;
|
||||
foreach ($argv as $arg) {
|
||||
if (in_array($arg, ['bash', 'zsh'], true)) {
|
||||
$shell = $arg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract command names from bin/moko COMMAND_MAP using regex (no eval).
|
||||
$mokoFile = dirname(__DIR__) . '/bin/moko';
|
||||
$content = file_get_contents($mokoFile);
|
||||
|
||||
// Isolate the COMMAND_MAP block, then extract keys.
|
||||
if (!preg_match('/const COMMAND_MAP\s*=\s*\[(.+?)\];/s', $content, $block)) {
|
||||
$this->log('ERROR', 'Could not find COMMAND_MAP in bin/moko');
|
||||
return 1;
|
||||
}
|
||||
// Match 'command-name' => 'path' entries within the block.
|
||||
if (!preg_match_all("/'([a-z][a-z0-9:_-]*)'\s*=>/m", $block[1], $matches)) {
|
||||
$this->log('ERROR', 'Could not parse command names from COMMAND_MAP');
|
||||
return 1;
|
||||
}
|
||||
|
||||
$commandNames = array_unique($matches[1]);
|
||||
sort($commandNames);
|
||||
|
||||
// Common flags supported by CliFramework.
|
||||
$commonFlags = ['--help', '--verbose', '--quiet', '--dry-run', '--json', '--no-color', '--path'];
|
||||
|
||||
if ($shell === 'zsh') {
|
||||
$this->generateZsh($commandNames, $commonFlags);
|
||||
} else {
|
||||
$this->generateBash($commandNames, $commonFlags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// -- Generators --
|
||||
|
||||
private function generateBash(array $commands, array $flags): void
|
||||
{
|
||||
$cmdList = implode(' ', $commands);
|
||||
$flagList = implode(' ', $flags);
|
||||
|
||||
echo <<<BASH
|
||||
# moko bash completion — generated by: php bin/moko completion bash
|
||||
_moko_complete() {
|
||||
local cur prev commands flags
|
||||
COMPREPLY=()
|
||||
cur="\${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
||||
|
||||
commands="{$cmdList}"
|
||||
flags="{$flagList}"
|
||||
|
||||
# Complete commands (first argument after 'moko')
|
||||
if [[ \$COMP_CWORD -eq 1 ]] || [[ \$COMP_CWORD -eq 2 && "\${COMP_WORDS[1]}" == "php" ]]; then
|
||||
COMPREPLY=( \$(compgen -W "\$commands list help" -- "\$cur") )
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Complete flags
|
||||
if [[ "\$cur" == -* ]]; then
|
||||
COMPREPLY=( \$(compgen -W "\$flags" -- "\$cur") )
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Complete --path with directories
|
||||
if [[ "\$prev" == "--path" ]]; then
|
||||
COMPREPLY=( \$(compgen -d -- "\$cur") )
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# Register for both direct and php invocation
|
||||
complete -F _moko_complete moko
|
||||
complete -F _moko_complete ./bin/moko
|
||||
complete -F _moko_complete bin/moko
|
||||
|
||||
BASH;
|
||||
}
|
||||
|
||||
private function generateZsh(array $commands, array $flags): void
|
||||
{
|
||||
$cmdLines = '';
|
||||
foreach ($commands as $cmd) {
|
||||
$cmdLines .= " '{$cmd}'\n";
|
||||
}
|
||||
$flagLines = '';
|
||||
foreach ($flags as $flag) {
|
||||
$desc = match ($flag) {
|
||||
'--help' => 'Show help for the command',
|
||||
'--verbose' => 'Show detailed output',
|
||||
'--quiet' => 'Suppress non-error output',
|
||||
'--dry-run' => 'Preview changes without writing',
|
||||
'--json' => 'Machine-readable JSON output',
|
||||
'--no-color' => 'Disable ANSI colour output',
|
||||
'--path' => 'Repository root path',
|
||||
default => $flag,
|
||||
};
|
||||
$flagLines .= " '{$flag}[{$desc}]'\n";
|
||||
}
|
||||
|
||||
echo <<<ZSH
|
||||
#compdef moko bin/moko
|
||||
# moko zsh completion — generated by: php bin/moko completion zsh
|
||||
|
||||
_moko() {
|
||||
local -a commands flags
|
||||
|
||||
commands=(
|
||||
{$cmdLines} 'list'
|
||||
'help'
|
||||
)
|
||||
|
||||
flags=(
|
||||
{$flagLines} )
|
||||
|
||||
if (( CURRENT == 2 )); then
|
||||
_describe 'command' commands
|
||||
else
|
||||
_arguments '*:flags:_values "flag" \${flags[@]}'
|
||||
fi
|
||||
}
|
||||
|
||||
compdef _moko moko
|
||||
compdef _moko bin/moko
|
||||
|
||||
ZSH;
|
||||
}
|
||||
}
|
||||
|
||||
$app = new CompletionCli();
|
||||
exit($app->execute());
|
||||
Reference in New Issue
Block a user