{"id":13532723,"url":"https://github.com/adhocore/php-cli","last_synced_at":"2025-05-14T01:11:28.454Z","repository":{"id":41284448,"uuid":"139012552","full_name":"adhocore/php-cli","owner":"adhocore","description":"PHP Console Application made easy- build great console apps with ease. Comes with Zero Dependency and Autocompletion support. Think of it as extremely flexible and customizable PHP cli application framework.","archived":false,"fork":false,"pushed_at":"2025-05-11T13:23:59.000Z","size":595,"stargazers_count":343,"open_issues_count":5,"forks_count":37,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-05-11T14:25:17.637Z","etag":null,"topics":["adhocore","argv","argv-parser","cli-app","cli-args","cli-color","cli-options","cli-writer","console-app","php-cli","php-cli-library"],"latest_commit_sha":null,"homepage":"https://github.com/adhocore/php-cli","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/adhocore.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"adhocore","custom":["https://paypal.me/ji10"]}},"created_at":"2018-06-28T12:03:18.000Z","updated_at":"2025-05-11T13:23:58.000Z","dependencies_parsed_at":"2023-09-24T12:52:05.169Z","dependency_job_id":"e0eae4ee-ad5d-4c9d-b7f8-1a397da579c8","html_url":"https://github.com/adhocore/php-cli","commit_stats":{"total_commits":434,"total_committers":17,"mean_commits":"25.529411764705884","dds":"0.29723502304147464","last_synced_commit":"57834cbaa4fb68cda849417ab86577fba2b15298"},"previous_names":[],"tags_count":54,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adhocore%2Fphp-cli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adhocore%2Fphp-cli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adhocore%2Fphp-cli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adhocore%2Fphp-cli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adhocore","download_url":"https://codeload.github.com/adhocore/php-cli/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254049432,"owners_count":22006058,"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":["adhocore","argv","argv-parser","cli-app","cli-args","cli-color","cli-options","cli-writer","console-app","php-cli","php-cli-library"],"created_at":"2024-08-01T07:01:13.221Z","updated_at":"2025-05-14T01:11:23.439Z","avatar_url":"https://github.com/adhocore.png","language":"PHP","readme":"## adhocore/cli\n\nFramework agnostic Command Line Interface utilities and helpers for PHP. Build Console App with ease, fun and love.\n\n[![Latest Version](https://img.shields.io/github/release/adhocore/php-cli.svg?style=flat-square)](https://github.com/adhocore/php-cli/releases)\n[![Build](https://github.com/adhocore/php-cli/actions/workflows/build.yml/badge.svg)](https://github.com/adhocore/php-cli/actions/workflows/build.yml)\n[![Scrutinizer CI](https://img.shields.io/scrutinizer/g/adhocore/php-cli.svg?style=flat-square)](https://scrutinizer-ci.com/g/adhocore/php-cli/?branch=main)\n[![Codecov branch](https://img.shields.io/codecov/c/github/adhocore/php-cli/main.svg?style=flat-square)](https://codecov.io/gh/adhocore/php-cli)\n[![StyleCI](https://styleci.io/repos/139012552/shield)](https://styleci.io/repos/139012552)\n[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE)\n[![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Framework+agnostic+Command+Line+Interface+utilities+and+helpers+for+PHP\u0026url=https://github.com/adhocore/php-cli\u0026hashtags=php,cli,cliapp,console)\n[![Support](https://img.shields.io/static/v1?label=Support\u0026message=%E2%9D%A4\u0026logo=GitHub)](https://github.com/sponsors/adhocore)\n\u003c!-- [![Donate 15](https://img.shields.io/badge/donate-paypal-blue.svg?style=flat-square\u0026label=donate+15)](https://www.paypal.me/ji10/15usd)\n[![Donate 25](https://img.shields.io/badge/donate-paypal-blue.svg?style=flat-square\u0026label=donate+25)](https://www.paypal.me/ji10/25usd)\n[![Donate 50](https://img.shields.io/badge/donate-paypal-blue.svg?style=flat-square\u0026label=donate+50)](https://www.paypal.me/ji10/50usd) --\u003e\n\n\n- Command line application made easy\n- Inspired by nodejs [commander](https://github.com/tj/commander.js) (thanks tj)\n- Zero dependency.\n- For PHP7, PHP8 and for good\n\n[![Screen Preview](https://i.imgur.com/qIYg9Zn.gif \"Preview from adhocore/phalcon-ext which uses this cli package\")](https://github.com/adhocore/phalcon-ext/tree/master/example/cli)\n\n#### What's included\n\n**Core:** [Argv parser](#argv-parser) \u0026middot; [Cli application](#console-app) \u0026middot; [Shell](#shell)\n\n**IO:** [Colorizer](#color) \u0026middot; [Cursor manipulator](#cursor) \u0026middot; [Progress bar](#progress-bar) \u0026middot; [Stream writer](#writer) \u0026middot; [Stream reader](#reader)\n\n**Other:** [Autocompletion](#autocompletion)\n\n## Installation\n```bash\n# PHP8.0 and above v1.0.0\ncomposer require adhocore/cli:^v1.0.0\n\n# PHP 7.x\ncomposer require adhocore/cli:^v0.9.0\n```\n\n## Usage\n\n### Argv parser\n\n```php\n$command = new Ahc\\Cli\\Input\\Command('rmdir', 'Remove dirs');\n\n$command\n    -\u003eversion('0.0.1-dev')\n    // Arguments are separated by space\n    // Format: `\u003cname\u003e` for required, `[name]` for optional\n    //  `[name:default]` for default value, `[name...]` for variadic (last argument)\n    -\u003earguments('\u003cdir\u003e [dirs...]')\n    // `-h --help`, `-V --version`, `-v --verbosity` options are already added by default.\n    // Format: `\u003cname\u003e` for required, `[name]` for optional\n    -\u003eoption('-s --with-subdir', 'Also delete subdirs (`with` means false by default)')\n    -\u003eoption('-e,--no-empty', 'Delete empty (`no` means true by default)')\n    // Specify santitizer/callback as 3rd param, default value as 4th param\n    -\u003eoption('-d|--depth [nestlevel]', 'How deep to process subdirs', 'intval', 5)\n    -\u003eparse(['thisfile.php', '-sev', 'dir', 'dir1', 'dir2', '-vv']) // `$_SERVER['argv']`\n;\n\n// Print all values:\nprint_r($command-\u003evalues());\n\n/*Array\n(\n    [help] =\u003e\n    [version] =\u003e 0.0.1\n    [verbosity] =\u003e 3\n    [dir] =\u003e dir\n    [dirs] =\u003e Array\n        (\n            [0] =\u003e dir1\n            [1] =\u003e dir2\n        )\n\n    [subdir] =\u003e true\n    [empty] =\u003e false\n    [depth] =\u003e 5\n)*/\n\n// To get values for options except the default ones (help, version, verbosity)\nprint_r($command-\u003evalues(false));\n\n// Pick a value by name\n$command-\u003edir;   // dir\n$command-\u003edirs;  // [dir1, dir2]\n$command-\u003edepth; // 5\n```\n\n#### Command help\n\nIt can be triggered manually with `$command-\u003eshowHelp()` or automatic when `-h` or `--help` option is passed to `$command-\u003eparse()`.\n\nFor above example, the output would be:\n![Command Help](https://i.imgur.com/TDAQrN3.png \"Command Help\")\n\n#### Command version\n\nIt can be triggered manually with `$command-\u003eshowVersion()` or automatic when `-V` or `--version` option is passed to `$command-\u003eparse()`.\n\nFor above example, the output would be:\n```\n0.0.1-dev\n```\n\n### Console app\n\nDefinitely check [adhocore/phint](https://github.com/adhocore/phint) - a real world console application made using `adhocore/cli`.\n\nHere we simulate a `git` app with limited functionality of `add`, and `checkout`.\nYou will see how intuitive, fluent and cheese building a console app is!\n\n#### Git app\n\n```php\n$app = new Ahc\\Cli\\Application('git', '0.0.1');\n\n$app\n    // Register `add` command\n    -\u003ecommand('add', 'Stage changed files', 'a') // alias a\n        // Set options and arguments for this command\n        -\u003earguments('\u003cpath\u003e [paths...]')\n        -\u003eoption('-f --force', 'Force add ignored file', 'boolval', false)\n        -\u003eoption('-N --intent-to-add', 'Add content later but index now', 'boolval', false)\n        // Handler for this command: param names should match but order can be anything :)\n        -\u003eaction(function ($path, $paths, $force, $intentToAdd) {\n            array_unshift($paths, $path);\n\n            echo ($intentToAdd ? 'Intent to add ' : 'Add ')\n                . implode(', ', $paths)\n                . ($force ? ' with force' : '');\n\n            // If you return integer from here, that will be taken as exit error code\n        })\n        // Done setting up this command for now, tap() to retreat back so we can add another command\n        -\u003etap()\n    -\u003ecommand('checkout', 'Switch branches', 'co') // alias co\n        -\u003earguments('\u003cbranch\u003e')\n        -\u003eoption('-b --new-branch', 'Create a new branch and switch to it', false)\n        -\u003eoption('-f --force', 'Checkout even if index differs', 'boolval', false)\n        -\u003eaction(function ($branch, $newBranch, $force) {\n            echo 'Checkout to '\n                . ($newBranch ? 'new ' . $branch : $branch)\n                . ($force ? ' with force' : '');\n        })\n;\n\n// Parse only parses input but doesnt invoke action\n$app-\u003eparse(['git', 'add', 'path1', 'path2', 'path3', '-f']);\n\n// Handle will do both parse and invoke action.\n$app-\u003ehandle(['git', 'add', 'path1', 'path2', 'path3', '-f']);\n// Will produce: Add path1, path2, path3 with force\n\n$app-\u003ehandle(['git', 'co', '-b', 'master-2', '-f']);\n// Will produce: Checkout to new master-2 with force\n```\n\n### Organized app\n\nInstead of inline commands/actions, we define and add our own commands (having `interact()` and `execute()`) to the app:\n\n```php\nclass InitCommand extends Ahc\\Cli\\Input\\Command\n{\n    public function __construct()\n    {\n        parent::__construct('init', 'Init something');\n\n        $help = '\u003ccyan\u003eCustom help screen\u003c/end\u003e';\n        $writer = new Ahc\\Cli\\Output\\Writer();\n\n        $this\n            -\u003eargument('\u003carrg\u003e', 'The Arrg')\n            -\u003eargument('[arg2]', 'The Arg2')\n            -\u003eoption('-a --apple', 'The Apple')\n            -\u003eoption('-b --ball', 'The ball')\n            -\u003ehelp($writer-\u003ecolorizer()-\u003ecolors($help))\n            // Usage examples:\n            -\u003eusage(\n                // append details or explanation of given example with ` ## ` so they will be uniformly aligned when shown\n                '\u003cbold\u003e  init\u003c/end\u003e \u003ccomment\u003e--apple applet --ball ballon \u003carggg\u003e\u003c/end\u003e ## details 1\u003ceol/\u003e' .\n                // $0 will be interpolated to actual command name\n                '\u003cbold\u003e  $0\u003c/end\u003e \u003ccomment\u003e-a applet -b ballon \u003carggg\u003e [arg2]\u003c/end\u003e ## details 2\u003ceol/\u003e'\n            )\n            -\u003elogo('Ascii art logo of your command');\n    }\n\n    // This method is auto called before `self::execute()` and receives `Interactor $io` instance\n    public function interact(Ahc\\Cli\\IO\\Interactor $io) : void\n    {\n        // Collect missing opts/args\n        if (!$this-\u003eapple) {\n            $this-\u003eset('apple', $io-\u003eprompt('Enter apple'));\n        }\n\n        if (!$this-\u003eball) {\n            $this-\u003eset('ball', $io-\u003eprompt('Enter ball'));\n        }\n\n        // ...\n    }\n\n    // When app-\u003ehandle() locates `init` command it automatically calls `execute()`\n    // with correct $ball and $apple values\n    public function execute($ball, $apple)\n    {\n        $io = $this-\u003eapp()-\u003eio();\n\n        $io-\u003ewrite('Apple ' . $apple, true);\n        $io-\u003ewrite('Ball ' . $ball, true);\n\n        // more codes ...\n\n        // If you return integer from here, that will be taken as exit error code\n    }\n}\n\nclass OtherCommand extends Ahc\\Cli\\Input\\Command\n{\n    public function __construct()\n    {\n        parent::__construct('other', 'Other something');\n    }\n\n    public function execute()\n    {\n        $io = $this-\u003eapp()-\u003eio();\n\n        $io-\u003ewrite('Other command');\n\n        // more codes ...\n\n        // If you return integer from here, that will be taken as exit error code\n    }\n}\n\n// Init App with name and version\n$app = new Ahc\\Cli\\Application('App', 'v0.0.1');\n\n// Add commands with optional aliases`\n$app-\u003eadd(new InitCommand, 'i');\n$app-\u003eadd(new OtherCommand, 'o');\n\n// Set logo\n$app-\u003elogo('Ascii art logo of your app');\n\n// Custom help screen\n$app-\u003ehelp('Custom help screen (if omitted one will be generated)');\n\n$app-\u003ehandle($_SERVER['argv']); // if argv[1] is `i` or `init` it executes InitCommand\n```\n\n#### Grouping commands\n\nGrouped commands are listed together in commands list. Explicit grouping a command is optional.\nBy default if a command name has a colon `:` then the part before it is taken as a group,\nelse `*` is taken as a group.\n\n\u003e Example: command name `app:env` has a default group `app`, command name `appenv` has group `*`.\n\n```php\n// Add grouped commands:\n$app-\u003egroup('Configuration', function ($app) {\n    $app-\u003eadd(new ConfigSetCommand);\n    $app-\u003eadd(new ConfigListCommand);\n});\n\n// Alternatively, set group one by one in each commands:\n$app-\u003eadd((new ConfigSetCommand)-\u003einGroup('Config'));\n$app-\u003eadd((new ConfigListCommand)-\u003einGroup('Config'));\n...\n```\n\n#### Default command\n\nBy default, running your CLI app without any arguments will show the help screen. However you can set the default action to run one of your commands either by setting the third parameter of the `add` function to `true` or by using the `defaultCommand` function.\n\n```php\n$app-\u003eadd(new InitCommand, 'i', true);\n\n// Alternatively\n$app-\u003ecommand('init', 'Init something', 'i');\n$app-\u003edefaultCommand('init');\n\n// Retrieve the name of the default command\n$default_command = $app-\u003egetDefaultCommand();\n```\n\n#### Exception handler\n\nSet a custom exception handler as callback. The callback receives exception \u0026 exit code. The callback may rethrow exception or may exit the program or just log exception and do nothing else.\n\n```php\n$app = new Ahc\\Cli\\Application('App', 'v0.0.1');\n$app-\u003eadd(...);\n$app-\u003eonException(function (Throwable $e, int $exitCode) {\n    // send to sentry\n    // write to logs\n\n    // optionally, exit with exit code:\n    exit($exitCode);\n\n    // or optionally rethrow, a rethrown exception is propagated to top layer caller.\n    throw $e;\n})-\u003ehandle($argv);\n```\n\n#### App help\n\nIt can be triggered manually with `$app-\u003eshowHelp()` or automatic when `-h` or `--help` option is passed to `$app-\u003eparse()`.\n**Note** If you pass something like `['app', cmd', '-h']` to `$app-\u003eparse()` it will automatically and instantly show you help of that `cmd` and not the `$app`.\n\nFor above example, the output would be:\n![App Help](https://i.imgur.com/NpzpsS0.png \"App Help\")\n\n#### App version\n\nSame version number is passed to all attached Commands. So you can trigger version on any of the commands.\n\n### Shell\n\nVery thin shell wrapper that provides convenience methods around `proc_open()`.\n\n#### Basic usage\n\n```php\n$shell = new Ahc\\Cli\\Helper\\Shell($command = 'php -v', $rawInput = null);\n\n// Waits until proc finishes\n$shell-\u003eexecute($async = false); // default false\n\necho $shell-\u003egetOutput(); // PHP version string (often with zend/opcache info)\n```\n\n#### Advanced usage\n\n```php\n$shell = new Ahc\\Cli\\Helper\\Shell('php /some/long/running/scipt.php');\n\n// With async flag, doesnt wait for proc to finish!\n$shell-\u003esetOptions($workDir = '/home', $envVars = [])\n    -\u003eexecute($async = true)\n    -\u003eisRunning(); // true\n\n// Force stop anytime (please check php.net/proc_close)\n$shell-\u003estop(); // also closes pipes\n\n// Force kill anytime (please check php.net/proc_terminate)\n$shell-\u003ekill();\n```\n\n#### Timeout\n\n```php\n$shell = new Ahc\\Cli\\Helper\\Shell('php /some/long/running/scipt.php');\n\n// Wait for at most 10.5 seconds for proc to finish!\n// If it doesnt complete by then, throws exception\n$shell-\u003esetOptions($workDir, $envVars, $timeout = 10.5)-\u003eexecute();\n\n// And if it completes within timeout, you can access the stdout/stderr\necho $shell-\u003egetOutput();\necho $shell-\u003egetErrorOutput();\n```\n\n### Cli Interaction\n\nYou can perform user interaction like printing colored output, reading user input programatically and  moving the cursors around with provided `Ahc\\Cli\\IO\\Interactor`.\n\n```php\n$interactor = new Ahc\\Cli\\IO\\Interactor;\n\n// For mocking io:\n$interactor = new Ahc\\Cli\\IO\\Interactor($inputPath, $outputPath);\n```\n\n#### Confirm\n```php\n$confirm = $interactor-\u003econfirm('Are you happy?', 'n'); // Default: n (no)\n$confirm // is a boolean\n    ? $interactor-\u003egreenBold('You are happy :)', true)  // Output green bold text\n    : $interactor-\u003eredBold('You are sad :(', true);     // Output red bold text\n```\n\n#### Single choice\n```php\n$fruits = ['a' =\u003e 'apple', 'b' =\u003e 'banana'];\n$choice = $interactor-\u003echoice('Select a fruit', $fruits, 'b');\n$interactor-\u003egreenBold(\"You selected: {$fruits[$choice]}\", true);\n```\n\n#### Multiple choices\n```php\n$fruits  = ['a' =\u003e 'apple', 'b' =\u003e 'banana', 'c' =\u003e 'cherry'];\n$choices = $interactor-\u003echoices('Select fruit(s)', $fruits, ['b', 'c']);\n$choices = \\array_map(function ($c) use ($fruits) { return $fruits[$c]; }, $choices);\n$interactor-\u003egreenBold('You selected: ' . implode(', ', $choices), true);\n```\n\n#### Prompt free input\n```php\n$any = $interactor-\u003eprompt('Anything', rand(1, 100)); // Random default\n$interactor-\u003egreenBold(\"Anything is: $any\", true);\n```\n\n#### Prompt with validation\n```php\n$nameValidator = function ($value) {\n    if (\\strlen($value) \u003c 5) {\n        throw new \\InvalidArgumentException('Name should be atleast 5 chars');\n    }\n\n    return $value;\n};\n\n// No default, Retry 5 more times\n$name = $interactor-\u003eprompt('Name', null, $nameValidator, 5);\n$interactor-\u003egreenBold(\"The name is: $name\", true);\n```\n\n#### Prompt hidden\n\n\u003e On windows platform, it may change the fontface which can be [fixed](https://superuser.com/a/757591).\n\n```php\n$passValidator = function ($pass) {\n    if (\\strlen($pass) \u003c 6) {\n        throw new \\InvalidArgumentException('Password too short');\n    }\n\n    return $pass;\n};\n\n$pass = $interactor-\u003epromptHidden('Password', $passValidator, 2);\n```\n\n![Interactive Preview](https://i.imgur.com/qYBNd29.gif \"Interactive Preview\")\n\n## IO Components\n\nThe interactor is composed of `Ahc\\Cli\\Input\\Reader` and `Ahc\\Cli\\Output\\Writer` while the `Writer` itself is composed of `Ahc\\Cli\\Output\\Color`. All these components can be used standalone.\n\n### Color\n\nColor looks cool!\n\n```php\n$color = new Ahc\\Cli\\Output\\Color;\n```\n\n#### Simple usage\n\n```php\necho $color-\u003ewarn('This is warning');\necho $color-\u003einfo('This is info');\necho $color-\u003eerror('This is error');\necho $color-\u003ecomment('This is comment');\necho $color-\u003eok('This is ok msg');\n```\n\n#### Custom style\n```php\nAhc\\Cli\\Output\\Color::style('mystyle', [\n    'bg' =\u003e Ahc\\Cli\\Output\\Color::CYAN,\n    'fg' =\u003e Ahc\\Cli\\Output\\Color::fg256(57), // 256 colors can be used as well\n    'bold' =\u003e 1, // You can experiment with 0, 1, 2, 3 ... as well\n]);\n\necho $color-\u003emystyle('My text');\n```\n\n#### Built-in styles\n\nThere are a number of pre-defined built-in styles that allows you granular customization to different output conditions such as help and prompts:\n\n - answer\n - choice\n - comment\n - error\n - help_category\n - help_description_even\n - help_description_odd\n - help_example\n - help_footer\n - help_group\n - help_header\n - help_item_even\n - help_item_odd\n - help_summary\n - help_text\n - info\n - logo\n - ok\n - question\n - version\n - warn\n\nOverriding a built-in style works the same way as defining a new style:\n\n```php\nAhc\\Cli\\Output\\Color::style('error', [\n    'fg' =\u003e Ahc\\Cli\\Output\\Color::RED,\n    'bold' =\u003e 1,\n]);\n```\n\n#### Disable colors\n\n```php\nAhc\\Cli\\Output\\Color::$enabled = false;\n```\n\nColors will be automatically disabled if the `NO_COLOR` environment variable is set to true.\n\n### Cursor\n\nMove cursor around, erase line up or down, clear screen.\n\n```php\n$cursor = new Ahc\\Cli\\Output\\Cursor;\n\necho  $cursor-\u003eup(1)\n    . $cursor-\u003edown(2)\n    . $cursor-\u003eright(3)\n    . $cursor-\u003eleft(4)\n    . $cursor-\u003enext(0)\n    . $cursor-\u003eprev(2);\n    . $cursor-\u003eeraseLine()\n    . $cursor-\u003eclear()\n    . $cursor-\u003eclearUp()\n    . $cursor-\u003eclearDown()\n    . $cursor-\u003emoveTo(5, 8); // x, y\n```\n\n### Progress Bar\n\nEasily add a progress bar to your output:\n\n```php\n$progress = new Ahc\\Cli\\Output\\ProgressBar(100);\nfor ($i = 0; $i \u003c= 100; $i++) {\n    $progress-\u003ecurrent($i);\n\n    // Simulate something happening\n    usleep(80000);\n}\n```\n\nYou can also manually advance the bar:\n\n```php\n$progress = new Ahc\\Cli\\Output\\ProgressBar(100);\n\n// Do something\n\n$progress-\u003eadvance(); // Adds 1 to the current progress\n\n// Do something\n\n$progress-\u003eadvance(10); // Adds 10 to the current progress\n\n// Do something\n\n$progress-\u003eadvance(5, 'Still going.'); // Adds 5, displays a label\n```\n\nYou can override the progress bar options to customize it to your liking:\n\n```php\n$progress = new Ahc\\Cli\\Output\\ProgressBar(100);\n$progress-\u003eoption('pointer', '\u003e\u003e');\n$progress-\u003eoption('loader', '▩');\n\n// You can set the progress fluently\n$progress-\u003eoption('pointer', '\u003e\u003e')-\u003eoption('loader', '▩');\n\n// You can also use an associative array to set many options in one time\n$progress-\u003eoption([\n    'pointer' =\u003e '\u003e\u003e',\n    'loader'  =\u003e '▩'\n]);\n\n// Available options\n+---------------+------------------------------------------------------+---------------+\n| Option        | Description                                          | Default value |\n+===============+======================================================+===============+\n| pointer       | The progress bar head symbol                         | \u003e             |\n| loader        | The loader symbol                                    | =             |\n| color         | The color of progress bar                            | white         |\n| labelColor    | The text color of the label                          | white         |\n| labelPosition | The position of the label (top, bottom, left, right) | bottom        |\n+---------------+------------------------------------------------------+---------------+\n\n```\n\n### Writer\n\nWrite anything in style.\n\n```php\n$writer = new Ahc\\Cli\\Output\\Writer;\n\n// All writes are forwarded to STDOUT\n// But if you specify error, then to STDERR\n$writer-\u003eerrorBold('This is error');\n```\n\n#### Output formatting\n\nYou can call methods composed of any combinations:\n`'\u003ccolorName\u003e', 'bold', 'bg', 'fg', 'warn', 'info', 'error', 'ok', 'comment'`\n... in any order (eg: `bgRedFgBlaock`, `boldRed`, `greenBold`, `commentBgPurple` and so on ...)\n\n```php\n$writer-\u003ebold-\u003egreen-\u003ewrite('It is bold green');\n$writer-\u003eboldGreen('It is bold green'); // Same as above\n$writer-\u003ecomment('This is grayish comment', true); // True indicates append EOL character.\n$writer-\u003ebgPurpleBold('This is white on purple background');\n```\n\n#### Free style\n\nMany colors with one single call: wrap text with tags `\u003cmethod\u003e` and `\u003c/end\u003e`\nFor NL/EOL just use `\u003ceol\u003e` or `\u003c/eol\u003e` or `\u003ceol/\u003e`.\n\nGreat for writing long colorful texts for example command usage info.\n\n```php\n$writer-\u003ecolors('\u003cred\u003eThis is red\u003c/end\u003e\u003ceol\u003e\u003cbgGreen\u003eThis has bg Green\u003c/end\u003e');\n```\n\n#### Raw output\n\n```php\n$writer-\u003eraw('Enter name: ');\n```\n\n#### Tables\n\nJust pass array of assoc arrays. The keys of first array will be taken as heading.\nHeading is auto inflected to human readable capitalized words (ucwords).\n\n```php\n$writer-\u003etable([\n    ['a' =\u003e 'apple', 'b-c' =\u003e 'ball', 'c_d' =\u003e 'cat'],\n    ['a' =\u003e 'applet', 'b-c' =\u003e 'bee', 'c_d' =\u003e 'cute'],\n]);\n```\n\nGives something like:\n\n```\n+--------+------+------+\n| A      | B C  | C D  |\n+--------+------+------+\n| apple  | ball | cat  |\n| applet | bee  | cute |\n+--------+------+------+\n```\n\n\u003e Designing table look and feel\n\nJust pass 2nd param `$styles`:\n\n```php\n$writer-\u003etable([\n    ['a' =\u003e 'apple', 'b-c' =\u003e 'ball', 'c_d' =\u003e 'cat'],\n    ['a' =\u003e 'applet', 'b-c' =\u003e 'bee', 'c_d' =\u003e 'cute'],\n], [\n    // for =\u003e styleName (anything that you would call in $writer instance)\n    'head' =\u003e 'boldGreen', // For the table heading\n    'odd'  =\u003e 'bold',      // For the odd rows (1st row is odd, then 3, 5 etc)\n    'even' =\u003e 'comment',   // For the even rows (2nd row is even, then 4, 6 etc)\n    '1:1'  =\u003e 'red',       // For cell in row 1 col 1 (1 based count, 'apple' in this example)\n    '2:*'  =\u003e '',          // For all cells in row 2 (1 based count)\n    '*:2'  =\u003e '',          // For all cells in col 2 (1 based count)\n    'b-c'  =\u003e '',          // For all columns named 'b-c' (same as '*:2' in this example)\n    '*:*'  =\u003e 'blue',      // For all cells in table (Set all cells to blue)\n]);\n```\n\nYou can define the style of a cell dynamically using a callback. You could then apply one style or another depending on a value.\n\n```php\n$rows = [\n    ['name' =\u003e 'John Doe', 'age' =\u003e '30'],\n    ['name' =\u003e 'Jane Smith', 'age' =\u003e '25'],\n    ['name' =\u003e 'Bob Johnson', 'age' =\u003e '40'],\n];\n\n$styles = [\n    '*:2' =\u003e function ($val, $row) {\n        return $row['age'] \u003e= 30 ? 'boldRed' : '';\n    },\n];\n\n$writer-\u003etable($rows, $styles);\n```\n\nThe example above only processes the cells in the second column of the table. If you want to process any cell, you can use the `*:*` key. You could then customise each cell in the table\n\n```php\n$rows = [\n    ['name' =\u003e 'John Doe', 'age' =\u003e '30'],\n    ['name' =\u003e 'Jane Smith', 'age' =\u003e '25'],\n    ['name' =\u003e 'Alice Bob', 'age' =\u003e '10'],\n    ['name' =\u003e 'Big Johnson', 'age' =\u003e '40'],\n    ['name' =\u003e 'Jane X', 'age' =\u003e '50'],\n    ['name' =\u003e 'John Smith', 'age' =\u003e '20'],\n    ['name' =\u003e 'Bob John', 'age' =\u003e '28'],\n];\n\n$styles = [\n    '*:*' =\u003e function ($val, $row) {\n        if ($val === 'Jane X') {\n            return 'yellow';\n        }\n        if ($val == 10 || $val == 20) {\n            return 'boldPurple';\n        }\n        if (str_contains($val, 'Bob')) {\n            return 'blue';\n        }\n        return $row['age'] \u003e= 30 ? 'boldRed' : '';\n    },\n];\n\n$writer-\u003etable($rows, $styles);\n```\n\n\u003e **Note: Priority in increasing order:**\n\u003e - `odd` or `even`\n\u003e - `2:*` (row)\n\u003e - `*:2` or `b-c \u003c-\u003e column name` (col)\n\u003e - `*:*` any cell in table\n\u003e - `1:1` (cell) = **highest priority**\n\n#### Justify content (Display setting)\n\nIf you want to display certain configurations (from your .env file for example) a bit like Laravel does (via the `php artisan about` command) you can use the `justify` method.\n\n```php\n$writer-\u003ejustify('Environment');\n$writer-\u003ejustify('PHP Version', PHP_VERSION);\n$writer-\u003ejustify('App Version', '1.0.0');\n$writer-\u003ejustify('Locale', 'en');\n```\n\nGives something like:\n\n```\nEnvironment ........................................\nPHP Version .................................. 8.1.4\nApp Version .................................. 1.0.0\nLocale .......................................... en\n```\n\nYou can use the `sep` parameter to define the separator to use.\n\n```php\n$writer-\u003ejustify('Environment', '', ['sep' =\u003e '-']);\n$writer-\u003ejustify('PHP Version', PHP_VERSION);\n```\n\nGives something like:\n\n```\nEnvironment ----------------------------------------\nPHP Version .................................. 8.1.4\n```\n\nIn addition, the text color, the background color and the thickness of the two texts can be defined via the 3rd argument of this method.\n\n```php\n$writer-\u003ejustify('Cache Enable', 'true', [\n    'first' =\u003e ['fg' =\u003e Ahc\\Cli\\Output\\Color::CYAN], // style of the key\n    'second' =\u003e ['fg' =\u003e Ahc\\Cli\\Output\\Color::GREEN], // style of the value\n]);\n$writer-\u003ejustify('Debug Mode', 'false', [\n    'first' =\u003e ['fg' =\u003e Ahc\\Cli\\Output\\Color::CYAN], // style of the key\n    'second' =\u003e ['fg' =\u003e Ahc\\Cli\\Output\\Color::RED], // style of the value\n]);\n```\n\nFor more details regarding the different color options, see [Custom style](#custom-style)\n\n#### Reader\n\nRead and pre process user input.\n\n```php\n$reader = new Ahc\\Cli\\Input\\Reader;\n\n// No default, callback fn `ucwords()`\n$reader-\u003eread(null, 'ucwords');\n\n// Default 'abc', callback `trim()`\n$reader-\u003eread('abc', 'trim');\n\n// Read at most first 5 chars\n// (if ENTER is pressed before 5 chars then further read is aborted)\n$reader-\u003eread('', 'trim', 5);\n\n// Read but dont echo back the input\n$reader-\u003ereadHidden($default, $callback);\n\n// Read from piped stream (or STDIN) if available without waiting\n$reader-\u003ereadPiped();\n\n// Pass in a callback for if STDIN is empty\n// The callback recieves $reader instance and MUST return string\n$reader-\u003ereadPiped(function ($reader) {\n    // Wait to read a line!\n    return $reader-\u003eread();\n\n    // Wait to read multi lines (until Ctrl+D pressed)\n    return $reader-\u003ereadAll();\n});\n```\n\n#### Exceptions\n\nWhenever an exception is caught by `Application::handle()`, it will show a beautiful stack trace and exit with non 0 status code.\n\n![Exception Preview](https://user-images.githubusercontent.com/2908547/44401057-8b350880-a577-11e8-8ca6-20508d593d98.png \"Exception trace\")\n\n## I18n Support\n\n**adhocore/cli** also supports internationalisation. This is particularly useful if you are not very comfortable with English or if you are creating a framework or CLI application that could be used by people from a variety of backgrounds.\n\nBy default, all the texts generated by our system are in English. But you can easily modify them by defining your translations as follows\n\n```php\n\\Ahc\\Application::addLocale('fr', [\n    'Only last argument can be variadic' =\u003e 'Seul le dernier argument peut être variadique',\n], true);\n```\n\nYou can also change the default English text to make the description more explicit if you wish.\n\n```php\n\\Ahc\\Application::addLocale('en', [\n    'Show help' =\u003e 'Shows helpful information about a command',\n]);\n```\n\nyou can find all the translation keys supported by the package in this gist : https://gist.github.com/dimtrovich/1597c16d5c74334e68eef15a4e7ba3fd\n\n## Autocompletion\n\nAny console applications that are built on top of **adhocore/cli** can entertain autocomplete of commands and options in zsh shell with oh-my-zsh.\n\nAll you have to do is add one line to the end of `~/.oh-my-zsh/custom/plugins/ahccli/ahccli.plugin.zsh`:\n\n\u003e `compdef _ahccli \u003cappname\u003e`\n\nExample: `compdef _ahccli phint` for [phint](https://github.com/adhocore/phint).\n\nThat is cumbersome to perform manually, here's a complete command you can copy/paste/run:\n\n#### One time setup\n\n```sh\nmkdir -p ~/.oh-my-zsh/custom/plugins/ahccli \u0026\u0026 cd ~/.oh-my-zsh/custom/plugins/ahccli\n\n[ -f ./ahccli.plugin.zsh ] || curl -sSLo ./ahccli.plugin.zsh https://raw.githubusercontent.com/adhocore/php-cli/master/ahccli.plugin.zsh\n\nchmod 760 ./ahccli.plugin.zsh \u0026\u0026 cd -\n```\n\n##### Load ahccli plugin\n\n\u003e This is also one time setup.\n\n```sh\n# Open .zshrc\nnano ~/.zshrc\n\n# locate plugins=(... ...) and add ahccli\nplugins=(git ... ... ahccli)\n\n# ... then save it (Ctrl + O)\n```\n\n#### Registering app\n\n```sh\n# replace appname with real name eg: phint\necho compdef _ahccli appname \u003e\u003e ~/.oh-my-zsh/custom/plugins/ahccli/ahccli.plugin.zsh\n```\n\n\u003e Of course you can add multiple apps, just change appname in above command\n\nThen either restart the shell or source the plugin like so:\n\n```sh\nsource ~/.oh-my-zsh/custom/plugins/ahccli/ahccli.plugin.zsh\n```\n\n#### Trigger autocomplete\n\n```sh\nappname \u003ctab\u003e            # autocompletes commands               (phint \u003ctab\u003e)\nappname subcommand \u003ctab\u003e # autocompletes options for subcommand (phint init \u003ctab\u003e)\n```\n\n### Related\n\n- [adhocore/phalcon-ext](https://github.com/adhocore/phalcon-ext) \u0026middot; Phalcon extension using `adhocore/cli`\n- [adhocore/phint](https://github.com/adhocore/phint) \u0026middot; PHP project scaffolding app using `adhocore/cli`\n- [adhocore/type-hinter](https://github.com/adhocore/php-type-hinter) \u0026middot; Auto PHP7 typehinter tool using `adhocore/cli`\n\n### Contributors\n\n- [adhocore](https://github.com/adhocore)\n- [sushilgupta](https://github.com/sushilgupta)\n\n## License\n\n\u003e \u0026copy; 2017-2020, [Jitendra Adhikari](https://github.com/adhocore) | [MIT](./LICENSE)\n\n### Credits\n\nThis project is release managed by [please](https://github.com/adhocore/please).\n","funding_links":["https://github.com/sponsors/adhocore","https://paypal.me/ji10","https://www.paypal.me/ji10/15usd","https://www.paypal.me/ji10/25usd","https://www.paypal.me/ji10/50usd"],"categories":["PHP","Uncategorized","[PHP](https://www.php.net/)"],"sub_categories":["Uncategorized","Useful awesome list for Go cli"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadhocore%2Fphp-cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadhocore%2Fphp-cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadhocore%2Fphp-cli/lists"}