diff --git a/src/Concerns/RunsCommands.php b/src/Concerns/RunsCommands.php index 73dce94..e08d033 100644 --- a/src/Concerns/RunsCommands.php +++ b/src/Concerns/RunsCommands.php @@ -2,8 +2,12 @@ namespace Statamic\Cli\Concerns; +use Laravel\Prompts\Support\Logger; +use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Process\Process; +use function Laravel\Prompts\task; + trait RunsCommands { /** @@ -11,9 +15,9 @@ trait RunsCommands * * @return Process */ - protected function runCommand(string $command, ?string $workingPath = null, bool $disableOutput = false) + protected function runCommand(string $command, ?string $workingPath = null, bool $disableOutput = false, ?string $taskLabel = null) { - return $this->runCommands([$command], $workingPath, $disableOutput); + return $this->runCommands([$command], $workingPath, $disableOutput, $taskLabel); } /** @@ -21,7 +25,7 @@ protected function runCommand(string $command, ?string $workingPath = null, bool * * @return Process */ - protected function runCommands(array $commands, ?string $workingPath = null, bool $disableOutput = false) + protected function runCommands(array $commands, ?string $workingPath = null, bool $disableOutput = false, ?string $taskLabel = null) { if (! $this->output->isDecorated()) { $commands = array_map(function ($value) { @@ -53,6 +57,10 @@ protected function runCommands(array $commands, ?string $workingPath = null, boo $process = Process::fromShellCommandline(implode(' && ', $commands), $workingPath, timeout: null); + if ($taskLabel && ! $disableOutput && $this->shouldRunAsTask()) { + return $this->runProcessAsTask($process, $taskLabel); + } + if ('\\' !== DIRECTORY_SEPARATOR && file_exists('/dev/tty') && is_readable('/dev/tty')) { try { if ($this->input->hasOption('no-interaction') && $this->input->getOption('no-interaction')) { @@ -75,4 +83,37 @@ protected function runCommands(array $commands, ?string $workingPath = null, boo return $process; } + + /** + * Determine if the process should be rendered as a collapsible Prompts task. + */ + private function shouldRunAsTask(): bool + { + return $this->output->getVerbosity() === OutputInterface::VERBOSITY_NORMAL + && $this->output->isDecorated() + && function_exists('Laravel\Prompts\task') + && function_exists('pcntl_fork'); + } + + /** + * Run the given process within a Laravel Prompts task, streaming its output into the task's log. + */ + private function runProcessAsTask(Process $process, string $taskLabel): Process + { + task( + label: $taskLabel, + keepSummary: true, + callback: function (Logger $logger) use ($process) { + $process->run(function ($type, $line) use ($logger) { + $logger->line($line); + }); + + if (! $process->isSuccessful()) { + $logger->error(trim($process->getErrorOutput())); + } + }, + ); + + return $process; + } } diff --git a/src/NewCommand.php b/src/NewCommand.php index 478b52d..033df03 100644 --- a/src/NewCommand.php +++ b/src/NewCommand.php @@ -90,7 +90,8 @@ protected function configure() ->addOption('repo', null, InputOption::VALUE_REQUIRED, 'Optionally specify the name of the GitHub repository') ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force install even if the directory already exists') ->addOption('email', null, InputOption::VALUE_OPTIONAL, 'Creates a super user with this email address') - ->addOption('password', null, InputOption::VALUE_OPTIONAL, 'Password for the super user'); + ->addOption('password', null, InputOption::VALUE_OPTIONAL, 'Password for the super user') + ->addOption('no-ascii-art', null, InputOption::VALUE_NONE, "Don't show the ASCII art title"); } protected function initialize(InputInterface $input, OutputInterface $output) @@ -327,6 +328,10 @@ protected function validateArguments() */ protected function showStatamicTitleArt() { + if ($this->input->getOption('no-ascii-art')) { + return $this; + } + $this->output->write(PHP_EOL.' █▀ ▀█▀ ▄▀█ ▀█▀ ▄▀█ █▀▄▀█ █ █▀▀ ▄█ ░█░ █▀█ ░█░ █▀█ █░▀░█ █ █▄▄'.PHP_EOL.PHP_EOL); @@ -502,7 +507,7 @@ protected function installBaseProject() $commands[] = "chmod 755 \"$this->absolutePath/please\""; } - $this->runCommands($commands); + $this->runCommands($commands, taskLabel: 'Installing Statamic'); if (! $this->wasBaseInstallSuccessful()) { throw new RuntimeException('There was a problem installing Statamic!'); @@ -830,7 +835,7 @@ protected function initializeGitRepository() "git branch -M {$branch}", ]; - $this->runCommands($commands, workingPath: $this->absolutePath); + $this->runCommands($commands, workingPath: $this->absolutePath, taskLabel: 'Initializing Git repository'); return $this; }