https://github.com/leafsphp/sprout
🌱 Fast, lightweight and minimal CLI framework for PHP
https://github.com/leafsphp/sprout
Last synced: 4 months ago
JSON representation
🌱 Fast, lightweight and minimal CLI framework for PHP
- Host: GitHub
- URL: https://github.com/leafsphp/sprout
- Owner: leafsphp
- License: mit
- Created: 2025-01-30T10:19:10.000Z (12 months ago)
- Default Branch: main
- Last Pushed: 2025-04-28T21:53:51.000Z (9 months ago)
- Last Synced: 2025-06-17T01:28:12.648Z (7 months ago)
- Language: PHP
- Size: 57.6 KB
- Stars: 2
- Watchers: 0
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Leaf Sprout (WIP)
🌱 Fast, lightweight and minimal CLI framework for PHP. It provides a type-safe, feature-rich environment to build CLI apps of all sizes, plus a ton of helpers for building amazing experiences for users interacting with your CLI app.
- Not based on any Laravel or Symfony console components
- First-class support for Leaf & Leaf modules
- Comes with built in styling, input handling, output handling, and more
- Support for PHP 7.4 and above
- Easy to use, easy to extend
## Installation
You can install Leaf Sprout using the Leaf CLI or Composer:
```sh
leaf install sprout
# or with composer
composer require leafs/sprout
```
## Usage
To get started, you need to create a file which will be the entry point for your CLI app. This file should be executable and should have a shebang at the top of the file. Here's an example of a simple CLI app:
```php
#!/usr/bin/env php
createApp([
'name' => 'My CLI App',
'version' => '1.0.0'
]);
$app->command('greet', function (Command $app) {
$command->write('Hello, world!');
});
$app->register(\MyCliApp\Commands\GreetCommand::class);
$app->run();
```
You can then run your CLI app using the PHP CLI:
```sh
php my-cli-app greet
```
## Writing Commands
You can write your commands in a functional way using the `command()` method on the app instance, or you can create a class that extends the `Leaf\Sprout\Command` class. Here's an example of a command written as a class:
```php
write("Hello, {$this->argument('name')}!");
}
}
```
You can then register this command with the app instance:
```php
$app->register(\MyCliApp\Commands\GreetCommand::class);
```
## Styling Output
Leaf Sprout comes with a built-in output styling system that allows you to style your output using a simple API adapted from TermWind. Here's an example of how you can style your output:
```php
$app->command('greet', function (Command $command) {
$command->write(
style()->apply('p-4 bg-green-300 text-white')->to('Hello') . ', world!'
);
});
```
You can also use pre-configured styles like `success()`, `error()`, `warning()`, and `info()`:
```php
style()->success('Operation successful');
style()->error('Operation failed');
...
style()->pill('Operation successful');
style()->pill('Operation failed')->apply('bg-red-500 text-white');
...
style()->italic('This is italic text');
style()->bold('This is bold text');
style()->underline('This is underlined text');
style()->dim('This is dim text');
style()->strikethrough('This is strikethrough text');
```
Most of the styling options are chainable, so you can chain multiple styles together:
```php
style()->bold()->underline()->apply('text-red-500')->to('Hello, world!');
```
## Input Handling
Leaf Sprout comes with a built-in input handling system that allows you to easily get input from the user. The easiest way is to use the `prompt()` method:
```php
$name = sprout()->prompt([
'type' => 'text', // 'select', 'confirm', 'password', 'number', 'text'
'initial' => 'John Doe',
'message' => 'What is your name?',
'validate' => function ($value) {
if (empty($value)) {
return 'Name cannot be empty';
}
return true;
}
]);
$command->write("Hello, $name!"); // Hello, John Doe!
```
You can also have multiple prompts in a single command for more complex interactions like setting up a project via your CLI:
```php
$possiblySetValue = $something ?? null;
$results = sprout()->prompt([
[
'type' => 'text',
'name' => 'name',
'message' => 'What is your project name?',
'initial' => 'my-project',
'validate' => function ($value) {
if (empty($value)) {
return 'Name cannot be empty';
}
return true;
}
],
[
'type' => $possiblySetValue ? null : 'select',
'name' => 'type',
'message' => 'What type of project do you want?',
'initial' => 0,
'choices' => [
['title' => 'Web', 'value' => 'web'],
['title' => 'API', 'value' => 'api'],
['title' => 'CLI', 'value' => 'cli'],
],
],
[
'type' => 'confirm',
'name' => 'install',
'message' => 'Do you want to install dependencies?',
'initial' => true,
],
]);
$results; // ['name' => 'my-project', 'type' => 'web', 'install' => true]
```
When the user runs the command, they will be prompted for the project name, type, and whether they want to install dependencies. The results will be stored in the `$results` variable. The prompt type can be `text`, `select`, `confirm`, `password`, `number`, or `text`, when set to `null`, the prompt will be skipped.
Besides prompts, you can also use the `arguments()` and `options()` methods to get arguments and options passed to the command:
```php
$app->command('greet', function (Command $command) {
$name = $command->argument('name');
$uppercase = $command->option('uppercase');
$greeting = "Hello, $name!";
if ($uppercase) {
$greeting = strtoupper($greeting);
}
$command->write($greeting);
});
```
## Output Handling
## Process Handling
Sprout comes with a built-in process handling system that allows you to run processes on the system. You can use the `process()` method to run a process:
```php
$process = sprout()->createProcess('ls -la');
$process->onError(function ($error) use ($command) {
$command->write("An error occurred: $error");
});
$process->run(function ($output) use ($command) {
$command->write($output);
});
$process->isSuccessful(); // true
$process->getExitCode(); // 0
```
You can also use the `run()` method to run a process and get the output:
```php
$output = sprout()->run('ls -la');
$command->write($output);
```
## Composer & Npm Scripts
A lot of console applications allow you to install composer or npm dependencies, and sprout makes it a whole lot easier to do so:
```php
sprout()->composer()->hasDependency('leafs/fs'); // true
sprout()->composer()->run('composer-script');
sprout()->composer()->install(); // install all dependencies
sprout()->composer()->install('leafs/fs'); // install a package
sprout()->composer()->remove('leafs/fs'); // remove a package
sprout()->npm()->hasDependency('@leafphp/vite'); // true
sprout()->npm()->run('npm-script');
sprout()->npm()->install(); // install all dependencies
sprout()->npm()->install('vite'); // install a package
sprout()->npm()->remove('vite'); // remove a package
```
For npm, you can also specify the package manager you want to use:
```php
sprout()->npm('yarn')->install(); // install all dependencies using yarn
sprout()->npm('pnpm')->install('vite'); // install a package using pnpm
sprout()->npm('bun')->install('vite'); // install a package using bun
```
All the composer and npm commands log the output to the console in real-time. If you want to change the output, you can pass a callback as the second argument:
```php
sprout()->composer()->install(function ($output) {
$command->write($output);
});
sprout()->npm()->install('vite @leafphp/vite', function ($output) {
$command->write("NPM -> $output");
});
```
The also return a process instance which you can use to get the output, check if the process was successful, and get the exit code:
```php
$process = sprout()->composer()->install();
$process->isSuccessful(); // true
```