{"id":13896123,"url":"https://github.com/gustavo-hms/cli","last_synced_at":"2025-12-26T15:04:04.120Z","repository":{"id":149013600,"uuid":"192421480","full_name":"gustavo-hms/cli","owner":"gustavo-hms","description":"Lua module to make building command line programs easier","archived":false,"fork":false,"pushed_at":"2020-05-21T12:36:47.000Z","size":219,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-11-25T01:33:19.386Z","etag":null,"topics":["cli","lua","module"],"latest_commit_sha":null,"homepage":null,"language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gustavo-hms.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"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}},"created_at":"2019-06-17T21:30:43.000Z","updated_at":"2024-08-15T07:46:53.000Z","dependencies_parsed_at":"2023-06-16T09:15:51.790Z","dependency_job_id":null,"html_url":"https://github.com/gustavo-hms/cli","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/gustavo-hms/cli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavo-hms%2Fcli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavo-hms%2Fcli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavo-hms%2Fcli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavo-hms%2Fcli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gustavo-hms","download_url":"https://codeload.github.com/gustavo-hms/cli/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavo-hms%2Fcli/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265606586,"owners_count":23796967,"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":["cli","lua","module"],"created_at":"2024-08-06T18:02:40.573Z","updated_at":"2025-12-26T15:03:59.068Z","avatar_url":"https://github.com/gustavo-hms.png","language":"Lua","funding_links":[],"categories":["Lua"],"sub_categories":[],"readme":"# cli\n\nA lua module to build command line interfaces declaratively.\n\n## Some examples\n\nTo write a program with flags and positional arguments, you can do the following:\n\n```lua\nlocal cli = require \"cli\"\n\ncli.locale \"en_US\"\n\ncli.program {\n    \"A description of the program\",\n    \n    cli.flag \"o,one\" {\n        \"The first option\",\n        type = cli.string\n    },\n    \n    cli.flag \"the-other\" {\n        \"The second option\",\n        type = cli.number,\n        default = 17\n    },\n    \n    cli.positional \"file\" {\n        \"The input file\",\n        type = cli.string\n    },\n    \n    function(args)\n        print(string.format(\"One: %s.\", args.one))\n        print(string.format(\"Two plus 1: %d.\", args.the_other + 1))\n        print(string.format(\"File: %s.\", args.file))\n    end\n}\n```\n\nSupposing this is the code for a program called `test-cli`, running `test-cli -o value input.txt` will print:\n\n```\nOne: value\nTwo plus 1: 18\nFile: input.txt\n```\n\n### Automatic help messages\n\nIn the above example, running  `test-cli --help` or `test-cli -h` will print:\n\n```\nA description of the program\n\nUsage:\n\n    test-cli [options] file\n\n    Options and arguments without a default value are mandatory.\n\nOptions:\n\n    -o, --one \u003cstring\u003e\n        The first option\n\n    --the-other \u003cnumber\u003e (default: 17)\n        The second option\n\nArguments:\n\n    file\n        The input file\n\n```\n\n### Automatic data validation\n\nSticking with the previous example, calling it with `test-cli -o value --the-other=dois input.txt` will print:\n\n```\nThe following errors were found during the program execution:\n\n    ∙ the option “--the-other” expects a number, but the given value was “dois”\n\nYou can run:\n\n    teste.lua --help\n\nif you need some help.\n\n```\n\n### Subcommands\n\nYour program can be easily divided into subcommands:\n\n```lua\nlocal cli = require \"cli\"\n\ncli.locale \"en_US\"\n\nadd = cli.command {\n    \"Add all the given numbers\",\n\n    function(args)\n        local sum = 0\n\n        for _, v in ipairs(args.numbers) do\n            sum = sum + v\n        end\n\n        print(sum)\n    end\n}\n\nmax = cli.command {\n    \"Find the maximum value\",\n\n    function(args)\n        print(math.max(table.unpack(args.numbers)))\n    end\n}\n\nall_above = cli.command {\n    \"Prints all numbers above the given value\",\n\n    cli.flag \"c,cutoff\" {\n        \"The value above which all numbers are retained\",\n\n        type = cli.number\n    },\n\n    function(args)\n        for _, v in ipairs(args.numbers) do\n            if v \u003e args.cutoff then\n                print(v)\n            end\n        end\n    end\n}\n\ncli.program {\n    \"A program to compute numbers\",\n\n    cli.positional \"numbers\" {\n        \"The numbers to operate upon\",\n\n        type = cli.number,\n        many = true,\n        default = {1, 3, 17}\n    }\n}\n```\n\nSupposing this is the code for an hypothetical `compute`, running `compute --help` will print:\n\n```\nA program to compute numbers\n\nUsage:\n\n    compute add numbers...\n        Add all the given numbers\n\n    compute all-above [options] numbers...\n        Prints all numbers above the given value\n\n    compute max numbers...\n        Find the maximum value\n\nYou can run\n\n    compute \u003ccommand\u003e --help\n\nto get more details about a specific command.\n\n```\n\nAnd, then, running `compute all-above --help`:\n\n```\nPrints all numbers above the given value\n\nUsage:\n\n    compute all-above [options] numbers...\n\n    Options and arguments without a default value are mandatory.\n\nOptions:\n\n    -c, --cutoff \u003cnumber\u003e\n        The value above which all numbers are retained\n\nArguments:\n\n    numbers... (default: 1 3 17)\n        The numbers to operate upon\n\n```\n\n## Usage\n\nThe start point of the `cli` module are the functions `cli.program` and `cli.command`. Both have the same interface: a table with the following fields (all of them are optionals):\n\n```\n{\n    A string containing a description (used for help messages),\n    \n    A sequence of definitions of command line arguments,\n    \n    A function to be executed\n}\n```\n\nThe provided function receives as argument a table with all command line arguments filled with their values:\n\n```lua\ncli.program {\n    cli.flag \"a-number\" {\n        type = cli.number\n    },\n    \n    function(args)\n        print(args.a_number)\n    end\n}\n```\n\nIf an argument has hyphens in its name, they are replaced with underscores, as in the above example.\n\nAny value returned by the main function (the one present in the `cli.program` table) is passed as an additional argument to the commands' functions:\n\n```lua\na_command = cli.command {\n    cli.flag \"do-it\" {\n        type = cli.boolean\n    },\n    \n    function(args, seventeen, nineteen)\n        print(args.do_it)\n        assert(seventeen == 17)\n        assert(nineteen == 19)\n    end\n}\n\ncli.program {\n    function()\n        return 17, 19\n    end\n}\n```\n\nAll global variables assined with a `cli.command` are interpreted as subcommands of the program, and subcommands will be named after these global variables, replacing underscores with hyphens. So, for instance, the above example will generate a command called `a-command`.\n\n### Defining command line arguments\n\nThere are two kinds of arguments: flags and positional arguments.\n\n#### Flags\n\nFlags are defined with `cli.flag`, passing to it a name and a table describing it:\n\n```lua\ncli.flag \"first-flag\" {\n    \"This is the first flag\",\n    type = cli.boolean\n}\n```\n\nIf the name contains a comma, the word preceding it is interpreted as a short variant of the word after it:\n\n```lua\ncli.flag \"o,output\" {}\n```\n\nThe description table has the following fields:\n- an optional string containing a description;\n- a `type` key describing the value this flag accepts. Must be one of `cli.string`, `cli.number` or `cli.boolean`. It defaults to `cli.string`. If it is set to `cli.number`, the module will try to convert the value given at program invocation to a number and prints an error if it can not succeed;\n- an optional `default` key containing a default value for this flag. Flags without a default value are considered mandatory.\n\n#### Positional arguments\n\nPositional arguments are defined with `cli.positional`, passing to it a name and a table describing it:\n\n```lua\ncli.positional \"file\" {\n    \"The file to be read\",\n    type = cli.string\n}\n```\n\nThe description table has the following fields:\n- an optional string containing a description;\n- a `type` key describing the value this positional accepts. Must be one of `cli.string` or `cli.number`. It defaults to `cli.string`. If it is set to `cli.number`, the module will try to convert the value given at program invocation to a number and prints an error if it can not succeed;\n- an optional `default` key containing a default value for this positional. Positionals without a default value are considered mandatory;\n- an optional `many` key telling whether this positional can receive many values at once.\n\nThe `many` key is used this way:\n\n```lua\ncli.positional \"files\" {\n    \"The files to be edited\",\n    type = cli.string,\n    many = true,\n    default = { \"README.md\", \"cli.lua\" }\n}\n```\n\n### Localisation\n\nThe function `cli.locale` can be used to set the locale of help and error messages:\n\n```lua\ncli.locale \"pt_BR\"\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgustavo-hms%2Fcli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgustavo-hms%2Fcli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgustavo-hms%2Fcli/lists"}