{"id":23002849,"url":"https://github.com/likianta/argsense-cli","last_synced_at":"2025-08-24T13:37:07.575Z","repository":{"id":37628535,"uuid":"494667607","full_name":"likianta/argsense-cli","owner":"likianta","description":"New command line interface based on Python Rich library.","archived":false,"fork":false,"pushed_at":"2025-08-08T07:31:09.000Z","size":4770,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-14T01:32:09.443Z","etag":null,"topics":["argparse","cli","click","command-line","command-line-interface","python","python-cli","python-rich","rich","rich-cli","rich-click","typer"],"latest_commit_sha":null,"homepage":"","language":"Python","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/likianta.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.zh.md","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,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-05-21T03:14:15.000Z","updated_at":"2025-08-08T07:31:12.000Z","dependencies_parsed_at":"2025-06-05T08:29:10.132Z","dependency_job_id":"c359c42a-85d6-4047-9fd0-52238b265216","html_url":"https://github.com/likianta/argsense-cli","commit_stats":null,"previous_names":[],"tags_count":32,"template":false,"template_full_name":null,"purl":"pkg:github/likianta/argsense-cli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/likianta%2Fargsense-cli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/likianta%2Fargsense-cli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/likianta%2Fargsense-cli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/likianta%2Fargsense-cli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/likianta","download_url":"https://codeload.github.com/likianta/argsense-cli/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/likianta%2Fargsense-cli/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271875839,"owners_count":24837307,"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","status":"online","status_checked_at":"2025-08-24T02:00:11.135Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["argparse","cli","click","command-line","command-line-interface","python","python-cli","python-rich","rich","rich-cli","rich-click","typer"],"created_at":"2024-12-15T07:12:27.001Z","updated_at":"2025-08-24T13:37:07.524Z","avatar_url":"https://github.com/likianta.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Argsense CLI\n\n[![PyPI version](https://badge.fury.io/py/argsense.svg)](https://badge.fury.io/py/argsense) [![Downloads](https://static.pepy.tech/badge/argsense)](https://pepy.tech/project/argsense) [![Downloads](https://static.pepy.tech/badge/argsense/month)](https://pepy.tech/project/argsense)\n\n[中文版](https://blog.csdn.net/Likianta/article/details/144585120)\n\n\u003e DISCLAIMER: This document is mainly generated by Google Cloud Translation Service. I have proofread the text and polished some of the content. Sorry if there are any incorrect grammar or descriptions.\n\n**Argsense** is a command line interface for python programmer.\n\nIt is simpler than argparse, click, typer, mush similar to [yapx](https://www.fresh2.dev/r/yapx/).\n\nScreenshots:\n\n![image-20241219110708076](.assets/image-20241219110708076.png)\n\n![image-20241218163439138](.assets/image-20241218163439138.png)\n\n![image-20241218163458876](.assets/image-20241218163458876.png)\n\nQuick glance at the code comparison:\n\n- Using `argparse`:\n\n  ```python\n  from argparse import ArgumentParser\n  \n  def hello(name: str = 'world'):\n      print(f'hello {name}')\n  \n  parser = ArgumentParser()\n  parser.add_argument('--name', default='world')\n  \n  parsed_args = parser.parse_args()\n  \n  hello(name=parsed_args.name)\n  ```\n\n- Using `argsense`:\n\n  ```python\n  from argsense import cli\n  \n  @cli.cmd()\n  def hello(name: str = 'world'):\n      print(f'hello {name}')\n  \n  cli.run(hello)\n  ```\n\n  and it prints more beautiful help interface:\n\n  ![image-20241219163816700](.assets/image-20241219163816700.png)\n\n## Install\n\nSupport Python 3.8 and above:\n\n```shell\npip install argsense\n```\n\nThe latest version is 0.6.0+.\n\n## Quick Start\n\n\u003e Note: some code examples use randomly generated words that have no actual meaning, they are only used to help you understand the overall code structure.\n\n### Decorate a function\n\n```python\n# test.py\nfrom argsense import cli\n\n@cli.cmd()\ndef main(foo, bar):\n    ...\n\nif __name__ == '__main__':\n    cli.run(main)\n```\n\n![image-20241218173627237](.assets/image-20241218173627237.png)\n\nIllustrate:\n\n- Import the `argsense` module: `from argsense import cli`.\n- Use `@cli.cmd()` to decorate the target function.\n- Run `cli.run(\u003centrance_func\u003e)`.\n\n### Decorate multiple functions\n\n```python\n# test.py\nfrom argsense import cli\n\n@cli.cmd()\ndef func1(foo, bar):\n    ...\n    \n@cli.cmd()\ndef func2(foo, bar):\n    ...\n\nif __name__ == '__main__':\n    cli.run()\n```\n\n![image-20241218174205159](.assets/image-20241218174205159.png)\n\nIllustrate:\n\n- Decorate each function with `@cli.cmd()`.\n- Run `cli.run()` instead of `cli.run(\u003centrance_func\u003e)` so that we can pass in the specific function name in the command line.\n- `python test.py -h` displays the help for all functions; `python test.py \u003cfunc\u003e -h` displays the help for a specific function.\n\n### Help interface documentation\n\n`argsense` parses the docstring of a function and extracts function description, parameter description and other information from it.\n\n```python\n# test.py\nfrom argsense import cli\n\n@cli.cmd()\ndef main(foo, bar):\n    \"\"\"\n    raise face talk traditional whom population character.\n    air surface affect or audience put professional.\n    \n    params:\n        foo: line bill network road alone customer case.\n        bar: avoid pass specific so president though. \n            everyone my red behavior sea.\n    \n    so job able far heart fund weight. family later energy -\n    community beautiful other tv.\n    \n    reference links:\n        - https://campos.com/f132eb1dbd2511efb10300155db7dfe7\n        - http://woods.com/f58e8e41bd2511efae3600155db7dfe7\n        - http://www.barry.com/f5de9271bd2511efa59600155db7dfe7\n    \"\"\"\n    ...\n\nif __name__ == '__main__':\n    cli.run(main)\n```\n\n![image-20241218174821103](.assets/image-20241218174821103.png)\n\nIllustrate:\n\n- The first few lines of text will be used as function description. When other fields appear in a line, the subsequent text will not be used as function description.\n- Parameter descriptions start with the \"param:\" field, the field name is case in-sensitive.\n\n### Optional parameters\n\n```python\n# test.py\nfrom argsense import cli\n\n@cli.cmd()\ndef main(aaa, bbb, ccc=123, ddd='good', eee=True):\n    \"\"\"\n    params:\n        aaa: allow evening fire cup next commercial.\n        bbb: develop ask decision. once start impact himself.\n        ccc: prepare really there fire support outside.\n            race chair statement citizen society power look husband.\n            though-material:\n                - ever\n                - above\n                - upon\n        ddd (-d): wall him suddenly bag however white.\n        eee (-e): \n            challenge alone without development. customer catch fund -\n            hair task buy.\n    \"\"\"\n    ...\n\nif __name__ == '__main__':\n    cli.run(main)\n```\n\n![image-20241218180506830](.assets/image-20241218180506830.png)\n\nIllustrate:\n\n- A red asterisk will be displayed on the left of the required parameter, indicating that this parameter must be given.\n- `ddd (-d): ...` will be recognized as: user can use both `--ddd` and `-d` to pass this parameters.\n- If the type of an argument is not specified, `argsense` will try to infer the type from its default value.\n  \n  Please note that only primitive types are supported, others will be treated as \"any\" types.\n- On the right, the default values of the optional parameters are shown.\n\n### Type of parameter\n\n`argsense` uses type annotations to determine the type of the parameter; if there is no type annotation, it will try to infer from its default value; if none, it will be treated as \"any\" type.\n\nWhen passing parameters, users do not need to consider type conversion. For example, when user gives `true`, if the parameter type is str, it will be translated to a string of `\"true\"` ; if it is bool, it will be translated to `True` .\n\nPlease note that passing wrong types will result in an error. That is, we cannot pass a string like \"abcd...\" to an int type parameter.\n\n### `*args` and `**kwargs`\n\n`argsense` supports `*args` and `**kwargs` parameter passing, and its usage is intuitive. Look the following example:\n\n```python\n# test.py\nfrom argsense import cli\n\n@cli.cmd()\ndef main(aaa, *bbb, ccc=123, **ddd) -\u003e None:\n    print(f'{aaa=}, {bbb=}, {ccc=}, {ddd=}')\n\nif __name__ == '__main__':\n    cli.run(main)\n```\n\n![image-20241218181643060](.assets/image-20241218181643060.png)\n\n### Passing special values\n\n`argsense` supports converting the following values to specific Python values:\n\n| User inputs | Recognized as       |\n| ----------- | ------------------- |\n| `:true`     | `True`              |\n| `:false`    | `False`             |\n| `:none`     | `None`              |\n| `:empty`    | `''` (empty string) |\n\n**Passing boolean values**\n\nThe usage of boolean values (`:true` `:false`) is rather special. Please refer to the following examples for understanding:\n\n```python\n# test.py\nfrom argsense import cli\n\n@cli.cmd()\ndef main(foo: bool, bar: bool):\n    \"\"\"\n    params:\n        foo (-f):\n        bar (-b):\n    \"\"\"\n    ...\n\nif __name__ == '__main__':\n    cli.run(main)\n```\n\nTo pass true, the following are equivalent:\n\n```shell\npython test.py :true :true\npython test.py --foo --bar\npython test.py -f -b\n```\n\nThey will be parsed as `main(foo=True, bar=True)` .\n\nNote that you cannot write `python test.py --foo :true --bar :true` , because `--foo` itself already means `foo=True` . This is `argsense` 's special understanding of boolean values.\n\nTo represent false, the following are equivalent:\n\n```shell\npython test.py :false :false\npython test.py --no-foo --no-bar\npython test.py -F -B\n```\n\nThis will be parsed as `main(foo=False, bar=False)` .\n\nNote the `-F` syntax. We require that the abbreviation in `foo (-f)` must be lowercase (otherwise `argsense` will report parsing error), so there is no mixing of uppercase and lowercase in the comment document. Uppercase is used specifically to indicate \"non\".\n\nDisadvantage: Due to the above design, `argsense` cannot handle some special parameter names. For example, `def main(no_alpha: bool)` will cause `--no-alpha` to not be parsed correctly and will raise an error.\n\n### Hidden Parameters\n\n...\n\n## In-Depth Reading\n\n### The format of function's docstring\n\n- There is no need for blank lines between multiple lines. If there are blank lines, they will be retained as is. Multiple consecutive blank lines will also be rendered as consecutive blank lines.\n- If a single line of text is too long, it can be represented by a line ends with \"-\":\n  \n  ```python\n  # test.py\n  from argsense import cli\n  \n  @cli.cmd()\n  def main(foo, bar):\n      \"\"\"\n      training speak stay try me. nothing generation side trial. seven rate -\n      worry not word family.\n      lay prepare anything piece method now work interesting. where mission move -\n      impact future. daughter remember leave. red read message talk hand.\n      similar bed capital public. former east later form people lawyer. -\n      operation true similar lose receive compare how film.\n      \n      service cold choice model finish. send ask star without huge evening.\n      next black there production space treat must often. purpose course -\n      actually whatever grow. take perform our billion receive food law.\n      result focus property yard let both. baby mind work style.\n      \"\"\"\n      ...\n  \n  if __name__ == '__main__':\n      cli.run(main)\n  ```\n  \n  ![image-20241219101538381](.assets/image-20241219101538381.png)\n  \n  ![image-20241219101628128](.assets/image-20241219101628128.png)\n- Parameter annotations must start with the \"params:\" field.\n- The format of parameter annotation is:\n  \n  ```\n  \u003cparam_name\u003e (\u003cshort_name\u003e): \u003cfirst_line_of_description\u003e\n      \u003cmore_description_lines\u003e\n  ```\n  \n  - `param_name` must be a parameter that appears in the function. If there is a non-existent parameter and nor `**kwargs` in the function signature, an error will be raised.\n  - `short_name` must start with a hyphen, followed by **a lowercase letter** and zero or more digits, for example:\n    \n    ```\n    # correct\n    -a\n    -a1\n    -a123\n    \n    # incorrect\n    -A\n    -A0\n    -Abc\n    -ABC\n    ```\n  - `first_line_of_description` is optional, if the comment text is shorter, it can be written here.\n    \n    If you leave this field blank, you can also write it in `more_description_lines`:\n    \n    ```python\n    def foo(...):\n        \"\"\"\n        params:\n            aaa: degree serve across recently. \n            bbb: \n                least support seem success word.\n        \"\"\"\n    ```\n    \n    ![image-20241219102629089](.assets/image-20241219102629089.png)\n    \n    Please note that if the text is long and `first_line_of_description` space is not enough, please write it in `more_description_lines` instead:\n    \n    ```python\n    def foo(...):\n        \"\"\"\n        params:\n            aaa: degree serve across recently. \n            bbb: \n                least support seem success word.\n            ccc:\n                scientist do war statement pay or reflect. fill -\n                get skill scene medical. side generation energy -\n                but popular. ago war act nice down.\n        \"\"\"\n    ```\n\n### Supported parameter types\n\n`argsense` supports a limited number of types. If an unsupported type is encountered, it is treated as \"any\".\n\nThe supported types are as follows:\n\n- bool\n- float\n- int\n- str\n\nIn addition, they can be wrapped with `typing.Optional[...]`, as shown in the following example:\n\n```python\nimport typing as t\nfrom argsense import cli\n\n@cli.cmd()\ndef main(\n    aaa: bool,\n    bbb: float,\n    ccc: int,\n    ddd: str,\n    eee: bool = None,\n    fff: float = None,\n    ggg: int = None,\n    hhh: str = None,\n    iii: t.Optional[bool] = None,\n    jjj: t.Optional[float] = None,\n    kkk: t.Optional[int] = 123,\n    lll: t.Optional[str] = None,\n):\n    ...\n\nif __name__ == '__main__':\n    cli.run(main)\n```\n\n![image-20241219100049669](.assets/image-20241219100049669.png)\n\n#### `bool`\n\nBoolean values are treated as `FLAG` and their usage is rather special. Taking the above code as an example, the following usage is equivalent:\n\n```shell\npython test.py :true\npython test.py --aaa\n```\n\nIt will be parsed as `main(aaa=True)`.\n\nNote that `--aaa :true` is incorrect. It will be parsed as `main(aaa=True, bbb=True)`.\n\nTo represent false, the following are equivalent:\n\n```shell\npython test.py :false\npython test.py --no-aaa\n```\n\nIt will be parsed as `main(aaa=False)`.\n\n#### `int`, `float`\n\nBoth int and float are treated as `NUMBER` .\n\n`argsense` has a flexible way of handling `NUMBER` types. You can pass a number or other number formats that conform to Python rules, such as binary \"0b1010\", \"0b1100\\_0011\" and hexadecimal \"0xAF2C\", \"0xFF36\\_A2B2\", etc.\n\nThey will all be parsed into corresponding int/float values.\n\n#### `str`\n\n...\n\n#### `Optional[...]`\n\n...\n\n#### What will be if we pass a wrong type?\n\n...\n\n## Frequently Asked Questions\n\n**Q: What are the advantages of ArgSense, compared to ArgParse, Click, Fire, Typer and other libraries?**\n\n...\n\n**Q: How to pass a complex type parameter?**\n\n...\n\n**Q: When there are too many functions, I want to group them. How can I do it?**\n\n...\n\n**Q: Why is ArgSense not designed to follow traditional command line usage?**\n\n...\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flikianta%2Fargsense-cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flikianta%2Fargsense-cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flikianta%2Fargsense-cli/lists"}