{"id":17124609,"url":"https://github.com/asika32764/php-simple-console","last_synced_at":"2025-06-15T16:34:08.079Z","repository":{"id":62488631,"uuid":"83867656","full_name":"asika32764/php-simple-console","owner":"asika32764","description":"Single file CLI framework to help you write build scripts.","archived":false,"fork":false,"pushed_at":"2025-01-27T09:18:24.000Z","size":11,"stargazers_count":21,"open_issues_count":3,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-02T13:09:20.586Z","etag":null,"topics":["argument-parser","argv","cli","cli-app","cli-framework","console","console-application","console-framework","stdin"],"latest_commit_sha":null,"homepage":"https://packagist.org/packages/asika/simple-console","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/asika32764.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-03-04T05:29:29.000Z","updated_at":"2025-01-27T09:18:28.000Z","dependencies_parsed_at":"2022-11-02T10:01:09.859Z","dependency_job_id":null,"html_url":"https://github.com/asika32764/php-simple-console","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asika32764%2Fphp-simple-console","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asika32764%2Fphp-simple-console/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asika32764%2Fphp-simple-console/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asika32764%2Fphp-simple-console/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/asika32764","download_url":"https://codeload.github.com/asika32764/php-simple-console/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244047646,"owners_count":20389206,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["argument-parser","argv","cli","cli-app","cli-framework","console","console-application","console-framework","stdin"],"created_at":"2024-10-14T18:43:00.121Z","updated_at":"2025-06-15T16:34:08.066Z","avatar_url":"https://github.com/asika32764.png","language":"PHP","readme":"# PHP Simple Console V2.0\n\n![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/asika32764/php-simple-console/ci.yml?style=for-the-badge)\n[![Packagist Version](https://img.shields.io/packagist/v/asika/simple-console?style=for-the-badge)\n](https://packagist.org/packages/asika/simple-console)\n[![Packagist Downloads](https://img.shields.io/packagist/dt/asika/simple-console?style=for-the-badge)](https://packagist.org/packages/asika/simple-console)\n\nSingle file console framework to help you write scripts quickly, **v2.0 requires PHP 8.4 or later**.\n\n\u003e This package is highly inspired by [Symfony Console](https://symfony.com/doc/current/components/console.html) and Python [argparse](https://docs.python.org/3/library/argparse.html).\n\n\u003c!-- TOC --\u003e\n* [PHP Simple Console V2.0](#php-simple-console-v20)\n  * [Installation](#installation)\n  * [Getting Started](#getting-started)\n    * [Run Console by Closure](#run-console-by-closure)\n    * [Run Console by Custom Class](#run-console-by-custom-class)\n    * [The Return Value](#the-return-value)\n  * [Parameter Parser](#parameter-parser)\n  * [Parameter Definitions](#parameter-definitions)\n    * [Show Help](#show-help)\n    * [Override Help Information](#override-help-information)\n  * [Parameter Configurations](#parameter-configurations)\n    * [Get Parameters Value](#get-parameters-value)\n    * [Parameters Type](#parameters-type)\n      * [`ARRAY` type](#array-type)\n      * [`LEVEL` type](#level-type)\n    * [Parameters Options](#parameters-options)\n      * [`description`](#description)\n      * [`required`](#required)\n      * [`default`](#default)\n      * [`negatable`](#negatable)\n    * [Parameters Parsing](#parameters-parsing)\n  * [Error Handling](#error-handling)\n    * [Wrong Parameters](#wrong-parameters)\n    * [Verbosity](#verbosity)\n  * [The Built-In Options](#the-built-in-options)\n    * [Disable Built-In Options for Console App](#disable-built-in-options-for-console-app)\n  * [Input/Output](#inputoutput)\n    * [STDIN/STDOUT/STDERR](#stdinstdoutstderr)\n    * [Output Methods](#output-methods)\n    * [Input and Asking Questions](#input-and-asking-questions)\n  * [Run Sub-Process](#run-sub-process)\n    * [Hide Command Name](#hide-command-name)\n    * [Custom Output](#custom-output)\n    * [Disable the Output](#disable-the-output)\n    * [Override `exec()`](#override-exec)\n  * [Delegating Multiple Tasks](#delegating-multiple-tasks)\n  * [Contributing and PR is Welcome](#contributing-and-pr-is-welcome)\n\u003c!-- TOC --\u003e\n\n## Installation\n\nUse composer:\n\n``` bash\ncomposer require asika/simple-console\n```\n\nDownload single\nfile: [Download Here](https://raw.githubusercontent.com/asika32764/php-simple-console/master/src/Console.php)\n\nCLI quick download:\n\n```shell\n# WGET\nwget https://raw.githubusercontent.com/asika32764/php-simple-console/master/src/Console.php\nchmod +x Console.php\n\n# CURL\ncurl https://raw.githubusercontent.com/asika32764/php-simple-console/master/src/Console.php -o Console.php\nchmod +x Console.php\n```\n\n## Getting Started\n\n### Run Console by Closure\n\nUse closure to create a simple console script.\n\n```php\n#!/bin/sh php\n\u003c?php\n// Include single file\ninclude_once __DIR__ . '/Console.php';\n\n// Or use composer\ninclude_once __DIR__ . '/vendor/autolod.php';\n\n$app = new \\Asika\\SimpleConsole\\Console();\n\n$app-\u003eexecute(\n    $argv,\n    function () use ($app) {\n        $this-\u003ewriteln('Hello');\n        \n        // OR\n        \n        $app-\u003ewriteln('Hello');\n    \n        return $app::SUCCESS; // OR `0` as success\n    }\n);\n```\n\nThe closure can receive a `Console` object as parameter, so you can use `$this` or `$app` to access the console object.\n\n```php\n$app-\u003eexecute(\n    $argv,\n    function (Console $app) {\n        $app-\u003ewriteln('Hello');\n    \n        // ...\n    }\n);\n```\n\nThe `$argv` can be omit, Console will get it from `$_SERVER['argv']`\n\n```php\n$app-\u003eexecute(\n    main: function (Console $app) {\n        $app-\u003ewriteln('Hello');\n    \n        // ...\n    }\n);\n```\n\n### Run Console by Custom Class\n\nYou can also use class mode, extends `Asika\\SimpleConsole\\Console` class to create a console application.\n\n```php\n$app = new class () extends \\Asika\\SimpleConsole\\Console\n{\n    protected function doExecute(): int|bool\n    {\n        $this-\u003ewriteln('Hello');\n\n        return static::SUCCESS;\n    }\n}\n\n$app-\u003eexecute();\n\n// OR\n\n$app-\u003eexecute($argv);\n```\n\n### The Return Value\n\nYou can return `true` or `0` as success, `false` or any int larger than `0` as failure. Please refer to\n[GNU/Linux Exit Codes](https://slg.ddnss.de/list-of-common-exit-codes-for-gnu-linux/).\n\nSimple Console provides constants for success and failure:\n\n```php\nretrun $app::SUCCESS; // 0\nretrun $app::FAILURE; // 255\n```\n\n## Parameter Parser\n\nSimple Console supports arguments and options pre-defined. Below is a parser object to help use define parameters and\nparse `argv` variables. You can pass the parsed data to any function or entry point.\n\n```php\nuse Asika\\SimpleConsole\\Console;\n\nfunction main(array $options) {\n    // Run your code...\n}\n\n$parser = \\Asika\\SimpleConsole\\Console::createArgvParser();\n\n// Arguments\n$parser-\u003eaddParameter('name', type: Console::STRING, description: 'Your name', required: true);\n$parser-\u003eaddParameter('age', type: Console::INT, description: 'Your age');\n\n// Name starts with `-` or `--` will be treated as option\n$parser-\u003eaddParameter('--height|-h', type: Console::FLOAT, description: 'Your height', required: true);\n$parser-\u003eaddParameter('--location|-l', type: Console::STRING, description: 'Live location', required: true);\n$parser-\u003eaddParameter('--muted|-m', type: Console::BOOLEAN, description: 'Is muted');\n\nmain($parser-\u003eparse($argv));\n```\n\nSame as:\n\n```php\nuse Asika\\SimpleConsole\\ArgvParser;\nuse Asika\\SimpleConsole\\Console;\n\n$params = Console::parseArgv(\n    function (ArgvParser $parser) {\n        // Arguments\n        $parser-\u003eaddParameter('name', type: Console::STRING, description: 'Your name', required: true);\n        $parser-\u003eaddParameter('age', type: Console::INT, description: 'Your age');\n\n        // Name starts with `-` or `--` will be treated as option\n        $parser-\u003eaddParameter('--height|-h', type: Console::FLOAT, description: 'Your height', required: true);\n        $parser-\u003eaddParameter('--location|-l', type: Console::STRING, description: 'Live location', required: true);\n        $parser-\u003eaddParameter('--muted|-m', type: Console::BOOLEAN, description: 'Is muted');\n    },\n    // pass $argv or leave empty\n);\n\nmain($params);\n```\n\n## Parameter Definitions\n\nAfter upgraded to 2.0, the parameter defining is required for `Console` app, if a provided argument or option is not\nexists\nin pre-defined parameters, it will raise an error.\n\n```php\n// me.php\n\n$app = new Console();\n// Arguments\n$app-\u003eaddParameter('name', type: $app::STRING, description: 'Your name', required: true);\n$app-\u003eaddParameter('age', type: $app::INT, description: 'Your age');\n\n// Name starts with `-` or `--` will be treated as option\n$app-\u003eaddParameter('--height', type: $app::FLOAT, description: 'Your height', required: true);\n$app-\u003eaddParameter('--location|-l', type: $app::STRING, description: 'Live location', required: true);\n$app-\u003eaddParameter('--muted|-m', type: $app::BOOLEAN, description: 'Is muted');\n\n$app-\u003eexecute(\n    argv: $argv,\n    main: function () use ($app) {\n        $app-\u003ewriteln('Hello');\n        $app-\u003ewriteln('Name: ' . $app-\u003eget('name'));\n        $app-\u003ewriteln('Age: ' . $app-\u003eget('age'));\n        $app-\u003ewriteln('Height: ' . $app-\u003eget('height'));\n        $app-\u003ewriteln('Location: ' . $app-\u003eget('location'));\n        $app-\u003ewriteln('Muted: ' . $app-\u003eget('muted') ? 'Y' : 'N');\n\n        return $app::SUCCESS;\n    }\n);\n```\n\nAlso same as:\n\n```php\n// me.php\n\n$app = new class () extends Console\n{\n    protected function configure(): void\n    {\n        // Arguments\n        $this-\u003eaddParameter('name', type: $this::STRING, description: 'Your name', required: true);\n        $this-\u003eaddParameter('age', type: $this::INT, description: 'Your age');\n\n        // Name starts with `-` or `--` will be treated as option\n        $this-\u003eaddParameter('--height', type: $this::FLOAT, description: 'Your height', required: true);\n        $this-\u003eaddParameter('--location|-l', type: $this::STRING, description: 'Live location', required: true);\n        $this-\u003eaddParameter('--muted|-m', type: $this::BOOLEAN, description: 'Is muted');\n    }\n    \n    protected function doExecute(): int|bool\n    {\n        $this-\u003ewriteln('Hello');\n        $this-\u003ewriteln('Name: ' . $this-\u003eget('name'));\n        $this-\u003ewriteln('Age: ' . $this-\u003eget('age'));\n        $this-\u003ewriteln('Height: ' . $this-\u003eget('height'));\n        $this-\u003ewriteln('Location: ' . $this-\u003eget('location'));\n        $this-\u003ewriteln('Muted: ' . ($this-\u003eget('muted') ? 'Y' : 'N'));\n\n        return $this::SUCCESS;\n    }\n};\n$app-\u003eexecute();\n```\n\nNow if we enter\n\n```bash\nphp me.php --name=\"John Doe \" --age=18 --height=1.8 --location=America --muted\n```\n\nIt shows:\n\n```\nHello\nName: John Doe\nAge: 25\nHeight: 1.8\nLocation: America\nMuted: Y\n```\n\nThen, if we enter wrong parameters, Simple Console will throw errors:\n\n```bash\nphp me.php # [Warning] Required argument \"name\" is missing.\nphp me.php Simon eighteen # [Warning] Invalid value type for \"age\". Expected INT.\nphp me.php Simon 18 foo bar # [Warning] Unknown argument \"foo\".\nphp me.php Simon 18 --nonexists # [Warning] The \"-nonexists\" option does not exist.\nphp me.php Simon 18 --location # [Warning] Required value for \"location\" is missing.\nphp me.php Simon 18 --muted=ON # [Warning] Option \"muted\" does not accept value.\nphp me.php Simon 18 --height one-point-eight # [Warning] Invalid value type for \"height\". Expected FLOAT.\n```\n\n### Show Help\n\nSimple Console supports to describe arguments/options information which follows [docopt](http://docopt.org/) standards.\n\nAdd `--help` or `-h` to Console App:\n\n```bash\nphp me.php --help\n```\n\nWill print the help information:\n\n```\nUsage:\n  me.php [options] [--] \u003cname\u003e [\u003cage\u003e]\n\nArguments:\n  name    Your name\n  age     Your age\n\nOptions:\n  --height=HEIGHT            Your height\n  -l, --location=LOCATION    Live location\n  -m, --muted                Is muted\n  -h, --help                 Show description of all parameters\n  -v, --verbosity            The verbosity level of the output\n\n```\n\nAdd your heading/epilog and command name:\n\n```php\n// Use constructor\n$app = new \\Asika\\SimpleConsole\\Console(\n    heading: \u003c\u003c\u003cHEADER\n    [Console] SHOW ME - v1.0\n    \n    This command can show personal information.\n    HEADER,\n    epilog: \u003c\u003c\u003cEPILOG\n    $ show-me.php John 18 \n    $ show-me.php John 18 --location=Europe --height 1.75 \n    \n    ...more please see https://show-me.example\n    EPILOG,\n    commandName: 'show-me.php'\n);\n\n// Or set properties\n\n$app-\u003eheading = \u003c\u003c\u003cHEADER\n[Console] SHOW ME - v1.0\n\nThis command can show personal information.\nHEADER;\n\n$app-\u003ecommandName = 'show-me.php'; // If not provided, will auto use script file name\n$app-\u003eepilog = \u003c\u003c\u003cEPILOG\n$ show-me.php John 18 \n$ show-me.php John 18 --location=Europe --height 1.75 \n\n...more please see https://show-me.example\nEPILOG;\n\n$app-\u003eexecute();\n```\n\nThe result:\n\n```\n[Console] SHOW ME - v1.0\n\nThis command can show personal information.\n\nUsage:\n  show-me.php [options] [--] \u003cname\u003e [\u003cage\u003e]\n\nArguments:\n  name    Your name\n  age     Your age\n\nOptions:\n  --height=HEIGHT            Your height\n  -l, --location=LOCATION    Live location\n  -m, --muted                Is muted\n  -h, --help                 Show description of all parameters\n  -v, --verbosity            The verbosity level of the output\n\nHelp:\n$ show-me.php John 18 \n$ show-me.php John 18 --location=Europe --height 1.75 \n\n...more please see https://show-me.example\n```\n\n### Override Help Information\n\nIf your are using class extending, you may override `showHelp()` method to add your own help information.\n\n```php\n$app = new class () extends Console\n{\n    public function showHelp(): void\n    {\n        $this-\u003ewriteln(\n            \u003c\u003c\u003cHELP\n            My script v1.0\n            \n            Options:\n            -h, --help      Show this help message\n            -q, --quiet     Suppress output\n            -l, --location  Your location\n            HELP\n        );\n    }\n```\n\n## Parameter Configurations\n\nTo define parameters, you can use `addParameter()` method.\n\nThe parameter name without `-` and `--` will be treated as argument.\n\n```php\n// Function style\n$app-\u003eaddParameter('name', type: $app::STRING, description: 'Your name', required: true);\n\n// Chaining style\n$app-\u003eaddParameter('name', type: $app::STRING)\n    -\u003edescription('Your name')\n    -\u003erequired(true)\n    -\u003edefault('John Doe');\n```\n\nThe parameter name starts with `-` and `--` will be treated as options, you can use `|` to separate primary name\nand shortcuts.\n\n```php\n$app-\u003eaddParameter('--foo', type: $app::STRING, description: 'Foo description');\n$app-\u003eaddParameter('--muted|-m', type: $app::BOOLEAN, description: 'Muted description');\n```\n\nArguments' name cannot same as options' name, otherwise it will throw an error.\n\n### Get Parameters Value\n\nTo get parameters' value, you can use `get()` method, all values will cast to the type which you defined.\n\n```php\n$name = $app-\u003eget('name'); // String\n$height = $app-\u003eget('height'); // Int\n$muted = $app-\u003eget('muted'); // Bool\n```\n\nArray access also works:\n\n```php\n$name = $app['name'];\n$height = $app['height'];\n```\n\nIf a parameter is not provided, it will return `FALSE`, and if a parameter provided but has no value, it will\nreturn as `NULL`.\n\n```bash\nphp console.php # `dir` is FALSE\nphp console.php --dir # `dir` is NULL\nphp console.php --dir /path/to/dir # `dir` is `/path/to/dir`\n```\n\nSo you can easily detect the parameter existence and give a default value.\n\n```php\nif (($dir = $app['dir']) !== false) {\n    $dir ??= '/path/to/default';\n}\n```\n\n### Parameters Type\n\nYou can define the type of parameters, it will auto convert to the type you defined.\n\n| Type    | Argument                     | Option                | Description                                                             |\n|---------|------------------------------|-----------------------|-------------------------------------------------------------------------|\n| STRING  | String type                  | String type           |                                                                         |\n| INT     | Integer type                 | Integer type          |                                                                         |\n| FLOAT   | Float type                   | Flot type             | Can be int or float, will all converts to float                         |\n| NUMERIC | Int or Float                 | Int or Float          | Can be int or float, will all converts to float                         |\n| BOOLEAN | (X)                          | Add `--opt` as `TRUE` | Use `negatable` to supports `--opt` as `TRUE` and `--no-opt` as `FALSE` |\n| ARRAY   | Array, must be last argument | Array                 | Can provide multiple as `string[]`                                      |\n| LEVEL   | (X)                          | Int type              | Can provide multiple times and convert the times to int                 |\n\nAll parameter values parsed from `argv` is default as `string` type, and convert to the type you defined.\n\n#### `ARRAY` type\n\nThe `ARRAY` can be use to arguments and options.\n\nIf you set an argument as `ARRAY` type, it must be last argument, and you can add more tailing arguments.\n\n```php\n$app-\u003eaddParameter('name', $app::STRING);\n$app-\u003eaddParameter('tag', $app::ARRAY);\n\n// Run: console.php foo a b c d e\n\n$app-\u003eget('tag'); // [a, b, c ,d, e]\n```\n\nUse `--` to escape all following options, all will be treated as arguments, it is useful if you are\nwriting a proxy script.\n\n```bash\nphp listen.php --timeout 500 --wait 100 -- php flower.php hello --name=sakura --location Japan --muted\n\n// The last argument values will be:\n// ['php', 'flower.php', 'hello', '--name=sakura', '--location', 'Japan', '--muted']\n```\n\nIf you set an option as `ARRAY` type, it can be used as `--tag a --tag b --tag c`.\n\n```php\n$app-\u003eaddParameter('--tag|-t', $app::ARRAY);\n\n$app-\u003eget('tag'); // [a, b, c]\n```\n\n#### `LEVEL` type\n\nThe `LEVEL` type is a special type, it will convert the times to int. For example, a verbosity level of `-vvv` will be\nconverted to `3`,\nand `-v` will be converted to `1`. You can use this type to define the verbosity level of your argv parser.\n\n```php\n$parser-\u003eaddParameter('--verbosity|-v', type: $app::LEVEL, description: 'The verbosity level of the output');\n```\n\nIf you are using `Console` class, the verbosity is built-in option, you don't need to define it again.\n\n### Parameters Options\n\n#### `description`\n\n- **Argument**: Description for the argument, will be shown in help information.\n- **Option**: Description for the option, will be shown in help information.\n\n#### `required`\n\n- **Argument**: Required argument must be provided, otherwise it will throw an error.\n    - You should not set a required argument after an optional argument.\n- **Option**: All options are `optional`.\n    - If you set an option as `required`, it means this option requires a value, only `--option` without value is not\n      allowed.\n    - `boolean` option should not be required.\n\n#### `default`\n\n- **Argument**: Default value for the argument.\n    - If not provided, it will be `null`, `false` for boolean type, or `[]` for array type.\n- **Option**: Default value for the option.\n    - If not provided, it will be `null`, `false` for boolean type, or `[]` for array type.\n\n#### `negatable`\n\n- **Argument**: Argument cannot use this option.\n- **Option**: Negatable option. Should work with `boolean` type.\n    - If set to `true`, it will support `--xxx|--no-xxx` 2 styles to set `true|false`.\n    - If you want to set a boolean option's default as `TRUE` and use `--no-xxx` to set it as `FALSE`, you can do this:\n    ```php\n    $app-\u003eaddParameter('--muted|-m', $app::BOOLEAN, default: true, negatable: true);\n    ```\n\n### Parameters Parsing\n\nSimple Console follows [docopt](http://docopt.org/) style to parse parameters.\n\n- Long options starts with `--`\n- Option shortcut starts with `-`\n- If an option `-a` requires value, `-abc` will parse as `$a = bc`\n- If option `-a` dose not require value, `-abc` will parse as `$a = true, $b = true, $c = true`\n- Long options supports `=` while shortcuts are not. The `--foo=bar` is valid and `-f=bar` is invalid, you should use\n  `-f bar`.\n- Add `--` to escape all following options, all will be treated as arguments.\n\n## Error Handling\n\nJust throw Exception in `doExecute()`, Console will auto catch error.\n\n``` php\nthrow new \\RuntimeException('An error occurred');\n```\n\nIf Console app receive an Throwable or Exception, it will render an `[ERROR]` message:\n\n```bash\n[Error] An error occurred.\n```\n\nAdd `-v` to show backtrace if error.\n\n```\n[Error] An error occurred.\n[Backtrace]:\n#0 /path/to/Console.php(145): Asika\\SimpleConsole\\Console@anonymous-\u003edoExecute()\n#1 /path/to/test.php(36): Asika\\SimpleConsole\\Console-\u003eexecute()\n#2 {main}\n```\n\n### Wrong Parameters\n\nIf you provide wrong parameters, Console will render a `[WARNING]` message with synopsis:\n\n```\n[Warning] Invalid value type for \"age\". Expected INT.\n\ntest.php [-h|--help] [-v|--verbosity] [--height HEIGHT] [-l|--location LOCATION] [-m|--muted] [--] \u003cname\u003e [\u003cage\u003e]\n```\n\nYou can manually raise this `[WARNING]` by throwing `InvalidParameterException`:\n\n```php\nif ($app-\u003eget('age') \u003c 18) {\n    throw new \\Asika\\SimpleConsole\\InvalidParameterException('Age must greater than 18.');\n}\n```\n\n### Verbosity\n\nYou can set verbosity by option `-v`\n\n```bash\nphp console.php # verbosity: 0\nphp console.php -v # verbosity: 1\nphp console.php -vv # verbosity: 2\nphp console.php -vvv # verbosity: 3\n```\n\nor ser it manually in PHP:\n\n```php\n$app-\u003everbosity = 3;\n```\n\nIf `verbosity` is larger than `0`, it will show backtrace in exception output.\n\nYou can show your own debug information on different verbosity:\n\n```php\nif ($app-\u003everbosity \u003e 2) {\n    $app-\u003ewriteln($debugInfo);\n}\n```\n\n## The Built-In Options\n\nThe `--help|-h` and `--verbosity|-v` options are built-in options if you use `Console` app.\n\n```php\n$app = new \\Asika\\SimpleConsole\\Console();\n// add parameters...\n$app-\u003eexecute(); // You can use built-in `-h` and `-v` options\n```\n\nIf you parse `argv` by `ArgvParser`, you must add it manually. To avoid the required parameters error,\nyou can set `validate` to `false` when parsing. Then validate and cast parameters after parsing and help\ncontent display.\n\n```php\n$parser-\u003eaddParameter(\n    '--help|-h',\n    static::BOOLEAN,\n    'Show description of all parameters',\n    default: false\n);\n\n$parser-\u003eaddParameter(\n    '--verbosity|-v',\n    static::LEVEL,\n    'The verbosity level of the output',\n);\n\n// Add other parameters...\n\n/** @var \\Asika\\SimpleConsole\\ArgvParser $parser */\n$params = $parser-\u003eparse($argv, validate: false);\n\nif ($params['help'] !== false) {\n    echo \\Asika\\SimpleConsole\\ParameterDescriptor::describe($parser, 'command.php');\n    exit(0);\n}\n\n// Now we can validate and cast params\n$params = $parser-\u003evalidateAndCastParams($params);\n\nmain($params);\n```\n\n### Disable Built-In Options for Console App\n\nIf you don't want to use built-in options for Console App, you can set `disableDefaultParameters` to `true`:\n\n```php\n$app = new \\Asika\\SimpleConsole\\Console();\n$app-\u003edisableDefaultParameters = true;\n\n// Add it manually\n$app-\u003eaddParameter('--help|-h', $app::BOOLEAN, default: false);\n\n// Set verbosity\n$app-\u003everbosity = (int) env('DEBUG_LEVEL');\n\n$app-\u003eexecute(\n    main: function (\\Asika\\SimpleConsole\\Console $app) {\n        if ($app-\u003eget('help')) {\n            $this-\u003eshowHelp();\n            return 0;\n        }\n        \n        // ...\n    }\n);\n```\n\n## Input/Output\n\n### STDIN/STDOUT/STDERR\n\nSimple Console supports to read from STDIN and write to STDOUT/STDERR. The default stream can be set at constructor.\n\n```php\nnew Console(\n    stdout: STDOUT,\n    stderr: STDERR,\n    stdin: STDIN\n);\n```\n\nIf you want to catch the output, you can set `stdout` to a file pointer or a stream.\n\n```php\n$fp = fopen('php://memory', 'r+');\n\n$app = new Console(stdout: $fp);\n$app-\u003eexecute();\n\nrewind($fp);\necho stream_get_contents($fp);\n```\n\n### Output Methods\n\nTo output messages, you can use these methods:\n\n- `write(string $message, bool $err = false)`: Write to STDOUT or STDERR\n- `writeln(string $message, bool $err = false)`: Write to STDOUT or STDERR with a new line\n- `newLine(int $lines, bool $err = false)`: Write empty new lines to STDOUT or STDERR\n\n### Input and Asking Questions\n\nTo input data, you can use `in()` methods:\n\n```php\n// This will wait user enter text...\n$app-\u003ewrite('Please enter something: ');\n$ans = $app-\u003ein();\n```\n\nUse `ask()` to ask a question, if return empty string, the default value will instead.\n\n```php\n$ans = $app-\u003eask('What is your name: ', [$default]);\n```\n\nUse `askConfirm()` to ask a question with `Y/n`:\n\n```php\n$ans = $app-\u003easkConfirm('Are you sure you want to do this? [y/N]: '); // Return BOOL\n\n// Set default as Yes\n$ans = $app-\u003easkConfirm('Are you sure you want to do this? [Y/n]: ', 'y');\n```\n\n- The `'n', 'no', 'false', 0, '0'` will be `FALSE`.\n- The `'y', 'yes', 'true', 1, '1'` will be `TRUE`.\n\nTo add your boolean mapping, set values to `boolMapping`\n\n```php\n$app-\u003eboolMapping[0] = [...]; // Falsy values\n$app-\u003eboolMapping[1] = [...]; // Truly values\n```\n\n## Run Sub-Process\n\nUse `exec()` to run a sub-process, it will instantly print the output and return the result code of the command.\n\n```php\n$app-\u003eexec('ls');\n$app-\u003eexec('git status');\n$app-\u003eexec('git commit ...');\n$result = $app-\u003eexec('git push');\n\n// All output will instantly print to STDOUT\n\nif ($result-\u003ecode !== 0) {\n    // Failure\n}\n\n$result-\u003ecode; // 0 is success\n$result-\u003esuccess; // BOOL\n```\n\nUse `mustExec()` to make sure a sub-process should run success, otherwise it will throw an exception.\n\n```php\ntry {\n    $this-\u003emustExec('...');\n} catch (\\RuntimeException $e) {\n    // \n}\n```\n\n### Hide Command Name\n\nBt default, `exec()` and `mustExec()` will show the command name before executing, for example.\n\n```basg\n\u003e\u003e git show\n...\n\n\u003e\u003e git commit -am \"\"\n...\n\n\u003e\u003e git push\n...\n```\n\nif you want to hide it, set the arg: `showCmd` to `false`.\n\n```php\n$app-\u003eexec('cmd...', showCmd: false);\n```\n\n### Custom Output\n\nSimple Console use `proc_open()` to run sub-process, so you can set your own output stream by callback.\n\n```php\n$log = '';\n\n$app-\u003eexec(\n    'cmd ...',\n    output: function (string $data, bool $err) use ($app, \u0026$log) {\n        $app-\u003ewrite($data, $err);\n        \n        $log .= $data;\n    }\n);\n```\n\n### Disable the Output\n\nUse `false` to disable the output, you can get full output from result object after sub-process finished.\n\nNote, the output will only write to result object if `output` set to `false`. If you set `output` as closure or\nkeep default `NULL`, the output will be empty in result object.\n\n```php\n$result = $app-\u003eexec('cmd ...', output: false);\n\n$result-\u003eoutput; // StdOutput of sub-process\n$result-\u003eerrOutput; // StdErr Output of sub-process\n\n\n// Below will not write to the result object\n$result = $app-\u003eexec('cmd ...');\n// OR\n$result = $app-\u003eexec('cmd ...', output: function () { ... });\n\n$result-\u003eoutput; // Empty\n$result-\u003eerrOutput; // Empty\n```\n\n### Override `exec()`\n\nBy now, running sub-process by `prop_open()` is in BETA, if `prop_open()` not work for your environment, simply override\n`exec()` to use PHP `system()` instead.\n\n```php\npublic function exec(string $cmd, \\Closure|null $output = null, bool $showCmd = true): ExecResult\n{\n    !$showCmd || $this-\u003ewriteln('\u003e\u003e ' . $cmd);\n    \n    $returnLine = system($cmd, $code);\n\n    return new \\Asika\\SimpleConsole\\ExecResult($code, $returnLine, $returnLine);\n}\n```\n\n## Delegating Multiple Tasks\n\nIf your script has multiple tasks, for example, the build script contains `configure|make|clear` etc...\n\nHere is an example to show how to delegate multiple tasks and pass the necessary params to method interface.\n\n```php\n$app = new class () extends Console\n{\n    protected function configure(): void\n    {\n        $this-\u003eaddParameter('task', type: $this::STRING, description: 'Task (configure|build|make|move|clear)', required: true);\n        $this-\u003eaddParameter('--lib-path', type: $this::STRING);\n        $this-\u003eaddParameter('--temp-path', type: $this::STRING);\n        $this-\u003eaddParameter('--nested', type: $this::STRING);\n        $this-\u003eaddParameter('--all', type: $this::STRING);\n    }\n\n    protected function doExecute(): int|bool\n    {\n        $params = [];\n\n        foreach ($this-\u003eparams as $k =\u003e $v) {\n            // Use any camel case convert library\n            $params[Str::toCamelCase($k)] = $v;\n        }\n\n        return $this-\u003e{$this['task']}(...$params);\n    }\n\n    // `...$args` is required, otherwise the redundant params will make method calling error\n    protected function build(string $libPath, string $tempPath, ...$args): int\n    {\n        $this-\u003ewriteln(\"Building: $libPath | $tempPath\");\n        return 0;\n    }\n\n    protected function clear(string $nested, string $dir, ...$args): int\n    {\n        $this-\u003ewriteln(\"Clearing: $nested | $dir\");\n        return 0;\n    }\n};\n$app-\u003eexecute();\n```\n\nNow run:\n\n```bash\nphp make.php build --lib-path foo --temp-path bar\n\n# Building foo | bar\n```\n\n\n## Contributing and PR is Welcome\n\nI'm apologize that I'm too busy to fix or handle all issues and reports, but pull-request is very welcome \nand will speed up the fixing process.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasika32764%2Fphp-simple-console","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fasika32764%2Fphp-simple-console","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasika32764%2Fphp-simple-console/lists"}