### Install Clypi Source: https://github.com/danimelchor/clypi/blob/master/README.md Install Clypi using uv or pip. This is the initial step to start building your CLI application. ```console uv add clypi # or `pip install clypi` ``` -------------------------------- ### Autocomplete Installation Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md Details the built-in `--install-autocomplete` option for setting up shell completions. ```APIDOC ## Autocomplete Clypi provides a built-in `--install-autocomplete` option to automatically configure shell completions for your CLI. > [!WARNING] > This feature is brand new and might contain some bugs. Please file a ticket > if you run into any! ``` -------------------------------- ### Install Package Locally and Test Source: https://github.com/danimelchor/clypi/blob/master/docs/packaging.md Install your CLI package in editable mode and test its functionality, including the verbose option. ```bash $ uv pip install -e . $ zit --verbose ``` -------------------------------- ### Install Clypi Dependency Source: https://github.com/danimelchor/clypi/blob/master/docs/packaging.md Add the clypi library as a dependency to your project using uv. ```bash $ uv add clypi ``` -------------------------------- ### Install Clypi with uv Source: https://github.com/danimelchor/clypi/blob/master/docs/learn/install.md Use this command to add Clypi to your project with the 'uv' package manager. Ensure 'uv' is installed and configured. ```bash $ uv add clypi ---> 100% Successfully installed clypi ``` -------------------------------- ### Implementing Intuitive Subcommands Source: https://github.com/danimelchor/clypi/blob/master/README.md Create and compose multiple Clypi commands to build intuitive subcommands for your CLI. This example demonstrates a main CLI with 'lint' and 'run' subcommands. ```python from clypi import Command, arg class Lint(Command): """Lint a set of files""" verbose: bool = arg(inherited=True) # Inherits the argument def from `MyCli` class Run(Command): """Run a set of files""" class MyCli(Command): """A simple CLI to lint and run files""" subcommand: Lint | Run verbose: bool = arg(False, help="Whether to show more output") cli = MyCli.parse() cli.start() ``` -------------------------------- ### Spinner Pipe Example Source: https://github.com/danimelchor/clypi/blob/master/docs/api/components.md Shows how to pipe the output of an async subprocess into a Spinner, displaying stdout and stderr with specified colors and prefixes. ```python import asyncio async def main(): async with Spinner("Doing something") as s: proc = await asyncio.create_subprocess_shell( "for i in $(seq 1 10); do date && sleep 0.4; done;", stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, ) await asyncio.gather( s.pipe(proc.stdout, color="blue", prefix="(stdout)"), s.pipe(proc.stderr, color="red", prefix="(stdout)"), ) ``` -------------------------------- ### Install Clypi with pip Source: https://github.com/danimelchor/clypi/blob/master/docs/learn/install.md Use this command to install Clypi using the standard 'pip' package manager. This is a common method for Python package installation. ```bash $ pip install clypi ---> 100% Successfully installed clypi ``` -------------------------------- ### Default Clypi Configuration Object Source: https://github.com/danimelchor/clypi/blob/master/docs/api/config.md This example shows the structure of a default `ClypiConfig` object, illustrating various customization options for help formatting, error handling, and theming. It's useful for understanding the full range of configurable parameters. ```python ClypiConfig( help_formatter=ClypiFormatter( boxed=True, show_option_types=True, ), help_on_fail=True, nice_errors=(ClypiException,), theme=Theme( usage=Styler(fg="yellow"), usage_command=Styler(bold=True), usage_args=Styler(), section_title=Styler(), subcommand=Styler(fg="blue", bold=True), long_option=Styler(fg="blue", bold=True), short_option=Styler(fg="green", bold=True), positional=Styler(fg="blue", bold=True), placeholder=Styler(fg="blue"), type_str=Styler(fg="yellow", bold=True), prompts=Styler(fg="blue", bold=True), ), overflow_style="wrap", disable_colors=False, fallback_term_width=100, ) ``` -------------------------------- ### Documenting CLIs with Docstrings Source: https://github.com/danimelchor/clypi/blob/master/README.md Automatically apply docstrings to your CLI's `--help` page by including them in your command classes. This example shows how to document an argument. ```python from clypi import Command, arg class MyCli(Command): """A simple CLI""" threads: int = arg( default=4, help="The number of threads to run the tool with", ) cli = MyCli.parse() cli.start() ``` -------------------------------- ### Configure Clypi Global Styling Source: https://github.com/danimelchor/clypi/blob/master/docs/learn/configuration.md Use this snippet to set up a global theme and formatter for Clypi. This ensures consistent styling across your application. Ensure Clypi is installed before use. ```python from clypi import ClypiConfig, ClypiFormatter, Styler, Theme, configure theme: Theme = Theme( usage=Styler(fg="green", bold=True), usage_command=Styler(fg="cyan", bold=True), usage_args=Styler(fg="cyan"), section_title=Styler(fg="green", bold=True), subcommand=Styler(fg="cyan", bold=True), long_option=Styler(fg="cyan", bold=True), short_option=Styler(fg="cyan", bold=True), positional=Styler(fg="cyan"), placeholder=Styler(fg="cyan"), prompts=Styler(fg="green", bold=True), ) config = ClypiConfig( theme=theme, help_formatter=ClypiFormatter( boxed=False, show_option_types=False, ), ) configure(config) ``` -------------------------------- ### Configure Clypi App Globally Source: https://github.com/danimelchor/clypi/blob/master/README.md Configure Clypi's theme and help formatter globally for consistent styling across your application. This setup is useful for achieving a specific UI look and feel. ```python from clypi import ClypiConfig, ClypiFormatter, Styler, Theme, configure configure( ClypiConfig( theme=Theme( usage=Styler(fg="green", bold=True), usage_command=Styler(fg="cyan", bold=True), usage_args=Styler(fg="cyan"), section_title=Styler(fg="green", bold=True), subcommand=Styler(fg="cyan", bold=True), long_option=Styler(fg="cyan", bold=True), short_option=Styler(fg="cyan", bold=True), positional=Styler(fg="cyan"), placeholder=Styler(fg="cyan"), prompts=Styler(fg="green", bold=True), ), help_formatter=ClypiFormatter( boxed=False, show_option_types=False, ), ) ) ``` -------------------------------- ### Advanced Argument Control with `arg` Helper Source: https://github.com/danimelchor/clypi/blob/master/README.md Use the `arg` helper and built-in parsers for more control over arguments, including defaults, validation rules, and custom parsers. This example restricts an integer argument to a specific range. ```python from clypi import Command, arg import clypi.parsers as cp class MyCli(Command): threads: int = arg( default=4, parser=cp.Int(min=1, max=10), # Restrict to values 1-10 ) cli = MyCli.parse() cli.start() ``` -------------------------------- ### Clypi Optional Parser (Union with None) Source: https://github.com/danimelchor/clypi/blob/master/docs/api/parsers.md Use cp.Union(, cp.NoneParser()) for optional types, equivalent to Python's Optional[]. For example, cp.Union(cp.Str(), cp.NoneParser()) handles an optional string. ```python cp.Union(, cp.NoneParser()) ``` ```python cp.Union(cp.Str(), cp.NoneParser()) ``` -------------------------------- ### Type-Checking with Clypi Prompts Source: https://github.com/danimelchor/clypi/blob/master/docs/index.md Clypi supports type-checking, ensuring that arguments passed to prompts are correctly inferred. This example demonstrates how a custom parser can result in a union type for the prompt's return value. ```python import clypi hours = clypi.prompt( "How many hours are there in a year?", parser=lambda x: float(x) if isinstance(x, str) else timedelta(days=len(x)) # noqa ) reveal_type(hours) # Type of "res" is "float | timedelta" ``` -------------------------------- ### Initialize Project with uv Source: https://github.com/danimelchor/clypi/blob/master/docs/packaging.md Initialize a new project using the uv tool. This sets up the basic project structure. ```bash $ uv init ``` -------------------------------- ### Build and Publish CLI with uv Source: https://github.com/danimelchor/clypi/blob/master/docs/packaging.md Use uv commands to build your package and publish it. Refer to uv documentation for detailed publishing steps. ```bash $ uv build $ uv publish ``` -------------------------------- ### Create Project Directory and Navigate Source: https://github.com/danimelchor/clypi/blob/master/docs/packaging.md Use these commands to create a new directory for your CLI project and navigate into it. ```bash $ mkdir zit $ cd zit ``` -------------------------------- ### Clypi List Parser Source: https://github.com/danimelchor/clypi/blob/master/docs/api/parsers.md Use cp.List() to parse lists of a specific type. For example, cp.List(cp.Str()) parses a list of strings. ```python cp.List() ``` ```python cp.List(cp.Str()) ``` -------------------------------- ### Create a Basic Clypi CLI Source: https://github.com/danimelchor/clypi/blob/master/docs/learn/getting_started.md This snippet shows the minimal code required to create a functional CLI application using Clypi. It defines a simple command that prints 'Hello, world!' when executed. ```python from clypi import Command from typing_extensions import override class Cli(Command): @override async def run(self): print(f"Hello, world!") if __name__ == '__main__': cmd = Cli.parse() cmd.start() ``` -------------------------------- ### Type Inference with Clypi Prompts Source: https://github.com/danimelchor/clypi/blob/master/README.md Clypi supports type checking, allowing your editor to infer types correctly for arguments passed to prompts. This example demonstrates how a parser can result in a union type. ```python import clypi hours = clypi.prompt( "How many hours are there in a year?", parser=lambda x: float(x) if isinstance(x, str) else timedelta(days=len(x)), ) reveal_type(hours) # Type of "res" is "float | timedelta" ``` -------------------------------- ### Instantiate ClypiFormatter with all options enabled Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md Create a ClypiFormatter instance with boxed sections and option types displayed. This provides a detailed and visually structured help output. ```python ClypiFormatter(boxed=True, show_option_types=True) ``` -------------------------------- ### Running Commands Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md Explains the requirement to implement the `run` method for command logic and demonstrates its asynchronous nature. ```APIDOC ## Running the Command The `run` method must be implemented to contain the business logic of your command. It must be an `async` function. ### Example: Implementing the `run` Method ```python from clypi import Command from typing_extensions import override class MyCommand(Command): verbose: bool = False @override async def run(self): print(f"Running with verbose: {self.verbose}") main = MyCommand.parse() main.start() ``` This snippet shows a `MyCommand` with a `verbose` flag. The `run` method is overridden to print a message indicating whether verbose mode is enabled. Arguments are accessed as instance properties within the `run` method. ``` -------------------------------- ### Defining Options Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md Illustrates how to define options, which are key/value pairs, and how to set them as required by omitting a default value. ```APIDOC ## Options Options are similar to flags but accept specific values. They can be made required by not providing a default value. ### Example: Option with Default Value ```python from clypi import Command class MyCommand(Command): my_attr: str | int = "some-default-here" main = MyCommand.parse() main.start() ``` This example defines an option `my_attr` with a default string value. If the user provides `--my-attr foo`, `my_attr` will be set to `foo`. Otherwise, it will retain its default value. ``` -------------------------------- ### Define a Formatter for help pages Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md Implement the Formatter protocol to customize how help pages are rendered. The implementation should consider the provided configuration theme. ```python class Formatter(t.Protocol): def format_help( self, full_command: list[str], description: str | None, epilog: str | None, options: list[Argument], positionals: list[Argument], subcommands: list[type[Command]], exception: Exception | None, ) -> str: ... ``` -------------------------------- ### Clypi Union Parser Source: https://github.com/danimelchor/clypi/blob/master/docs/api/parsers.md Use cp.Union(*) to parse values that can be one of several types. For example, cp.Union(cp.Str(), cp.NoneParser()) handles strings or None, and cp.Union(cp.Str(), cp.Bool(), cp.Int()) handles strings, booleans, or integers. ```python cp.Union(*) ``` ```python cp.Union(cp.Str(), cp.NoneParser()) ``` ```python cp.Union(cp.Str(), cp.Bool(), cp.Int()) ``` -------------------------------- ### Configure Build System in pyproject.toml Source: https://github.com/danimelchor/clypi/blob/master/docs/packaging.md Add this section to your `pyproject.toml` file to specify the build system requirements, using hatchling as the build backend. ```toml [build-system] requires = ["hatchling"] build-backend = "hatchling.build" ``` -------------------------------- ### Access and Change Clypi Configuration Source: https://github.com/danimelchor/clypi/blob/master/docs/api/config.md Use `get_config` to retrieve the current configuration or a default. Apply a new configuration by creating a `ClypiConfig` object and passing it to `configure`. Ensure `help_on_fail` is set appropriately for your needs. ```python from clypi import ClypiConfig, configure, get_config # Gets the current config (or a default) conf = get_config() # Change the configuration config = ClypiConfig(help_on_fail=False) configure(config) ``` -------------------------------- ### Clypi Literal Parser Source: https://github.com/danimelchor/clypi/blob/master/docs/api/parsers.md Use cp.Literal(*) to parse values that must be one of the specified literal values. For example, cp.Literal(1, "foo") parses either the integer 1 or the string "foo". ```python cp.Literal(*) ``` ```python cp.Literal(1, "foo") ``` -------------------------------- ### Build Shiv Binary Source: https://github.com/danimelchor/clypi/blob/master/docs/packaging.md Create a self-contained executable binary (Shiv) for your CLI using `uvx shiv`. This bundles your Python code into a single file for easy distribution. ```bash $ uvx shiv -c zit -o zit-bin . $ ./zit-bin --verbose ``` -------------------------------- ### Clypi Tuple Parser Source: https://github.com/danimelchor/clypi/blob/master/docs/api/parsers.md Use cp.Tuple(, ) to parse tuples. Specify the type and optionally the length. For example, cp.Tuple(cp.Str()) parses a tuple of strings, and cp.Tuple(cp.Str(), cp.Int()) parses a tuple of a string and an integer. Use num=None for variable length tuples like cp.Tuple(cp.Str(), num=None). ```python cp.Tuple(, ) ``` ```python cp.Tuple(cp.Str()) ``` ```python cp.Tuple(cp.Str(), cp.Int()) ``` ```python cp.Tuple(cp.Str(), num=None) ``` -------------------------------- ### Add Documentation to Clypi CLI Arguments and Command Source: https://github.com/danimelchor/clypi/blob/master/docs/learn/getting_started.md Shows how to add documentation to a Clypi CLI using Python docstrings for the command and the `arg` helper for arguments and options. This improves usability by providing help messages. ```python from clypi import Command, Positional, arg from typing_extensions import override class Cli(Command): """A very simple CLI""" name: Positional[str] = arg(help="Your name") age: int | None = arg(None, help="Your age in years") @override async def run(self): print(f"Hello, {self.name}.") if self.age is not None: print(f"You are {self.age}!") if __name__ == '__main__': cmd = Cli.parse() cmd.start() ``` -------------------------------- ### Core Command Methods Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md Details the essential methods for command execution and help display. ```APIDOC ## Core Command Methods ### `help` ```python @t.final @classmethod def help(cls) ``` The help displayed for the command when the user passes in `-h` or `--help`. Defaults to the docstring for the class extending `Command`. ### `run` ```python async def run(self: Command) -> None: ``` The main function you **must** override. This function is where the business logic of your command should live. `self` contains the arguments for this command you can access as you would do with any other instance property. ### `astart` and `start` ```python async def astart(self: Command | None = None) -> None: ``` ```python def start(self) -> None: ``` These commands are the entry point for your program. You can either call `YourCommand.start()` on your class or, if already in an async loop, `await YourCommand.astart()`. ### `print_help` ```python @classmethod def print_help(cls, exception: Exception | None = None) ``` Prints the help page for a particular command. Parameters: - `exception`: an exception neatly showed to the user as a traceback. Automatically passed in during runtime. ``` -------------------------------- ### Implement the Async Run Method Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md Implement the `run` method to contain the command's business logic. This method must be asynchronous. ```python from clypi import Command from typing_extensions import override class MyCommand(Command): verbose: bool = False @override async def run(self): print(f"Running with verbose: {self.verbose}") main = MyCommand.parse() main.start() ``` -------------------------------- ### Prompting for Input Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md Demonstrates how to prompt the user for input when an argument is not provided, with an option to set a default value. ```APIDOC ## Prompting If an argument is not provided, you can prompt the user for input. ### Example: Prompting for a Required String ```python from clypi import Command, arg class MyCommand(Command): name: str = arg(prompt="What's your name?") main = MyCommand.parse() main.start() ``` When `MyCommand` is run without the `--name` argument, it will prompt the user with "What's your name?". The program will continue to ask until a value is provided. A `default` value can also be passed to `arg` to allow the user to press Enter to accept it. ``` -------------------------------- ### Run CLI Locally with uv Source: https://github.com/danimelchor/clypi/blob/master/docs/packaging.md Execute your CLI application locally using uv. This command runs the main script directly. ```bash $ uv run ./zit/main.py ``` -------------------------------- ### Custom Help Messages Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md Shows how to define custom help messages for arguments using `arg` and for the command itself using a class docstring. ```APIDOC ## Help Page Custom help messages can be provided for arguments and commands. ### Example: Custom Help for an Argument ```python from clypi import Command, arg class MyCommand(Command): verbose: bool = arg( True, help="Whether to show all of the output" ) main = MyCommand.parse() main.start() ``` This example uses the `arg` helper to attach a custom help string to the `verbose` flag. This message will appear when the user requests help for the command. ### Example: Custom Help for a Command ```python from clypi import Command class MyCommand(Command): """ This text will show up when someone does `my-command --help` and can contain any info you'd like """ main = MyCommand.parse() main.start() ``` The docstring of the `Command` subclass serves as the help message for the command itself. ``` -------------------------------- ### Spinner Context Manager Usage Source: https://github.com/danimelchor/clypi/blob/master/docs/api/components.md Demonstrates using the Spinner as an async context manager to indicate progress with customizable titles and capture output. ```python import asyncio from clypi import Spinner async def main(): async with Spinner("Doing something", capture=True) as s: await asyncio.sleep(1) s.title = "Slept for a bit" print("I slept for a bit, will sleep a bit more") await asyncio.sleep(1) asyncio.run(main()) ``` -------------------------------- ### Add Entrypoint to pyproject.toml Source: https://github.com/danimelchor/clypi/blob/master/docs/packaging.md Define the script entrypoint for your Python package in `pyproject.toml`. This allows the package to be executed as a command. ```toml [project.scripts] zit = "zit.main:main" ``` -------------------------------- ### Instantiate ClypiFormatter with all options disabled Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md Create a ClypiFormatter instance with boxes and option types disabled. This results in a simpler, indented help output. ```python ClypiFormatter(boxed=False, show_option_types=False) ``` -------------------------------- ### Create Reusable Text Stylers with Clypi Source: https://github.com/danimelchor/clypi/blob/master/docs/learn/beautiful_uis.md Define a `clypi.Styler` object to apply consistent styling (e.g., color, strikethrough) to multiple text outputs. This is useful for repetitive styling tasks. ```python import clypi wrong = clypi.Styler(fg="red", strikethrough=True) print("The old version said", wrong("Pluto was a planet")) print("The old version said", wrong("the Earth was flat")) ``` -------------------------------- ### Print Colorful Text with Clypi Source: https://github.com/danimelchor/clypi/blob/master/docs/learn/beautiful_uis.md Use `cprint` to easily print text with foreground colors and styles like bold or strikethrough. Ensure `clypi` is imported. ```python from clypi import cprint cprint("Some colorful text", fg="green", bold=True) cprint("Some more colorful text", fg="red", strikethrough=True) ``` -------------------------------- ### Import Clypi Parsers Source: https://github.com/danimelchor/clypi/blob/master/docs/api/parsers.md Import the necessary parsers from the clypi.parsers module. ```python import clypi.parsers as cp ``` -------------------------------- ### Zit CLI Implementation Source: https://github.com/danimelchor/clypi/blob/master/docs/packaging.md This Python code defines a basic CLI application named 'Zit' using the Clypi library. It includes a verbose flag and a simple message output. Ensure this code is placed in `zit/main.py`. ```python # zit/main.py import clypi from clypi import Command, arg class Zit(Command): """ A git clone, but much slower ;) """ verbose: bool = arg(False, short="v") async def run(self): clypi.cprint("Sorry I don't know how to use git, it's too hard!", fg="yellow") if self.verbose: clypi.cprint("asdkjnbsvaeusbvkajhfnuehfvousadhvuashfqei" * 100) ``` ```python def main(): """ This will be the entrypoint for our CLI """ zit = Zit.parse() zit.start() if __name__ == "__main__": main() ``` -------------------------------- ### Defining Flags Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md Demonstrates how to define boolean flags with default values and prompt for input if no value is provided. ```APIDOC ## Flags Flags are boolean arguments that can be set to true or false. They are defined by assigning a boolean value to a class attribute. ### Example: Boolean Flag with Prompt ```python from clypi import Command, arg class MyCommand(Command): my_flag: bool = arg(False, prompt="Value for my-flag?", negative="no_my_flag") main = MyCommand.parse() main.start() ``` In this example, `my_flag` is a boolean flag. If not provided on the command line, it defaults to `False`. The `prompt` argument specifies a message to ask the user if the flag is not provided, and `negative` defines a keyword to explicitly set the flag to `False`. ``` -------------------------------- ### Styler Class Source: https://github.com/danimelchor/clypi/blob/master/docs/api/colors.md A class to create reusable text styling configurations. ```APIDOC ## Styler Class ### Description Returns a reusable function to style text. It allows configuring foreground color, background color, and various text styles. ### Class Definition ```python class Styler( fg: ColorType | None = None, bg: ColorType | None = None, bold: bool = False, italic: bool = False, dim: bool = False, underline: bool = False, blink: bool = False, reverse: bool = False, strikethrough: bool = False, reset: bool = False, hide: bool = False, ) ``` ### Parameters - **fg** (ColorType | None) - Optional - Foreground color. - **bg** (ColorType | None) - Optional - Background color. - **bold** (bool) - Optional - Apply bold style. Defaults to False. - **italic** (bool) - Optional - Apply italic style. Defaults to False. - **dim** (bool) - Optional - Apply dim style. Defaults to False. - **underline** (bool) - Optional - Apply underline style. Defaults to False. - **blink** (bool) - Optional - Apply blink style. Defaults to False. - **reverse** (bool) - Optional - Apply reverse style. Defaults to False. - **strikethrough** (bool) - Optional - Apply strikethrough style. Defaults to False. - **reset** (bool) - Optional - Reset all styles. Defaults to False. - **hide** (bool) - Optional - Apply hide style. Defaults to False. ``` -------------------------------- ### Argument Configuration (`arg`) Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md The `arg` utility function is used to configure various aspects of an argument's behavior, such as its default value, parsing logic, help text, and prompting. ```APIDOC ## `arg` Utility function to configure how a specific argument should behave when displayed and parsed. ### Parameters - `default` (T | Unset | EllipsisType) - The default value to return if the user doesn't pass in the argument or hits enter during the prompt. - `parser` (Parser[T] | None) - A function that takes in a string and returns the parsed type. - `default_factory` (Callable[[], T] | Unset) - A function that returns a default value. Useful to defer computation or to avoid default mutable values. - `help` (str | None) - A brief description to show the user when they pass in `-h` or `--help`. - `short` (str | None) - Defines a short way to pass in a value for options (e.g., `short="v"` allows users to pass in `-v `). - `prompt` (str | None) - If defined, it will ask the user to provide input if not already defined in the command line args. - `hide_input` (bool) - Whether the input shouldn't be displayed as the user types (for passwords, API keys, etc.). Defaults to `False`. - `max_attempts` (int) - How many times to ask the user before giving up and raising. Defaults to `MAX_ATTEMPTS`. - `group` (str | None) - Optionally define the name of a group to display the option in. - `env` (str | None) - Optionally define an environment variable to read the value from. - `negative` (str | None) - Defines the negative argument to set a flag as False. Useful for flags that have prompts so that they can be programmatically set to False. ``` -------------------------------- ### View Grouped Arguments in CLI Help Source: https://github.com/danimelchor/clypi/blob/master/docs/learn/getting_started.md This terminal output demonstrates how arguments defined with the 'group' parameter are displayed under distinct sections in the CLI's help message, improving readability. ```bash $ python cli.py --help A very simple CLI Usage: cli [OPTIONS] ┏━ Options ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃ --format The output format to use {JSON|RAW} ┃ ┃ --verbose Whether to show verbose output ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┏━ Environment options ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃ --env The environment to run in {QA|PROD} ┃ ┃ --cluster The cluster to run in {DEFAULT|SECONDARY} ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ``` -------------------------------- ### Run mdtest CLI Source: https://github.com/danimelchor/clypi/blob/master/mdtest/README.md Execute the mdtest CLI using uv to run tests defined in Markdown files. ```bash uv run mdtest ``` -------------------------------- ### Formatter Protocol Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md Defines the protocol for classes that render help pages for Clypi commands. ```APIDOC ## `Formatter` Protocol ### Description A formatter is any class conforming to the following protocol. It is called on several occasions to render the help page. The `Formatter` implementation should try to use the provided configuration theme when possible. ### Protocol Definition ```python class Formatter(t.Protocol): def format_help( self, full_command: list[str], description: str | None, epilog: str | None, options: list[Argument], positionals: list[Argument], subcommands: list[type[Command]], exception: Exception | None, ) -> str: ... ``` ``` -------------------------------- ### Command Properties Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md Describes various properties available on a Clypi Command class. ```APIDOC ## Command Properties ### `name` ```python @t.final @classmethod def prog(cls) ``` The name of the command. Can be overridden to provide a custom name or will default to the class name extending `Command`. ### `epilog` ```python @t.final @classmethod def epilog(cls) ``` Optionally define text to display after the help message. ### `full_command` ```python @t.final @classmethod def full_command(cls) ``` The full path of commands to the current command being ran. ### `parents` ```python @t.final @classmethod def parents(cls) ``` A list of parent commands for this command. ### `get_unparsed` ```python @t.final @classmethod def get_unparsed(cls) ``` The list of unparsed arguments for this command. If a user passes in `--`, anything after the double dash will be left unparsed for the command to process as they wish. ``` -------------------------------- ### Define a pre_run_hook for a Command Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md Implement this method to execute code before a command or subcommand runs. Useful for logging or emitting metrics. ```python async def pre_run_hook(self: Command) -> None: ``` ```python import logging from typing_extensions import override from clypi import Command class MyCommand(Command): @override async def pre_run_hook(self): cmd_str = " ".join(self.full_command()) logging.debug("Running %s", cmd_str) @override async def run(self): print("Hey") main = MyCommand.parse() main.start() ``` -------------------------------- ### Use Clypi Spinner as a Context Manager Source: https://github.com/danimelchor/clypi/blob/master/docs/learn/beautiful_uis.md Manage a spinner's visibility within an `async with` block using `clypi.Spinner`. This approach is suitable for controlling the spinner's display around specific asynchronous operations. Requires `asyncio` and `clypi` imports. ```python import asyncio from clypi import Spinner async def main(): async with Spinner("Doing something", capture=True): await asyncio.sleep(2) asyncio.run(main()) ``` -------------------------------- ### ClypiFormatter Class Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md A pre-made formatter for Clypi that allows customization of help page appearance, including boxing and option type display. ```APIDOC ## `ClypiFormatter` ### Description Clypi ships with a pre-made formatter that can display help pages with either boxes or with indented sections, and hide or show the option types. You can disable both the boxes and type of each option and display just a placeholder. ### Initialization Parameters - `boxed` (bool): whether to wrap each section in a box made with ASCII characters. - `show_option_types` (bool): whether to display the expected type for each argument or just a placeholder. E.g.: `--foo TEXT` vs `--foo `. - `show_inherited_options` (bool): whether to show inherited arguments in child commands or only in parent commands. - `normalize_dots` (str | None): either `"."`, `""`, or `None`. If a dot, or empty, it will add or remove trailing dots from all help messages to keep a more consistent formatting across the application. ### Example Usage (with everything enabled) ```python ClypiFormatter(boxed=True, show_option_types=True) ``` ### Example Usage (with everything disabled) ```python ClypiFormatter(boxed=False, show_option_types=False) ``` ``` -------------------------------- ### Prompt User for Input Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md Prompt the user for input for a specific argument if it's not provided on the command line. The `prompt` parameter in `arg` specifies the question to ask. ```python from clypi import Command, arg class MyCommand(Command): name: str = arg(prompt="What's your name?") main = MyCommand.parse() main.start() ``` -------------------------------- ### Stack Boxed Elements with Clypi Source: https://github.com/danimelchor/clypi/blob/master/docs/learn/beautiful_uis.md Combine multiple boxed elements side-by-side using `clypi.stack`. This is useful for presenting related information in a structured, visually distinct manner. Ensure `clypi` is imported. ```python import clypi names = clypi.boxed(["Daniel", "Pedro", "Paul"], title="Names", width=15) colors = clypi.boxed(["Blue", "Red", "Green"], title="Colors", width=15) print(clypi.stack(names, colors)) ``` -------------------------------- ### Define Custom Help Message for a Command Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md Define a custom help message for the entire command by adding a docstring to the `Command` subclass. This text is displayed when the user runs the command with `--help`. ```python from clypi import Command class MyCommand(Command): """ This text will show up when someone does `my-command --help` and can contain any info you'd like """ main = MyCommand.parse() main.start() ``` -------------------------------- ### Use Built-in Parsers with Customization Source: https://github.com/danimelchor/clypi/blob/master/docs/learn/getting_started.md Leverage Clypi's built-in parsers for common Python types. You can customize parser behavior, like ensuring a path exists, by passing a parser instance to `arg()`. ```python from clypi import Command, arg import clypi.parsers as cp class MyCommand(Command): file: Path = arg( parser=cp.Path(exists=True), ) ``` -------------------------------- ### Define Custom Help for a Flag Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md Provide a custom help message for a flag using the `help` parameter in the `arg` helper. This message appears when the user requests help. ```python from clypi import Command, arg class MyCommand(Command): verbose: bool = arg( True, help="Whether to show all of the output" ) main = MyCommand.parse() main.start() ``` -------------------------------- ### style Function Source: https://github.com/danimelchor/clypi/blob/master/docs/api/colors.md Styles text and returns the styled string. ```APIDOC ## style Function ### Description Styles text with specified colors and formatting and returns the styled string. ### Function Signature ```python def style( *messages: t.Any, fg: ColorType | None = None, bg: ColorType | None = None, bold: bool = False, italic: bool = False, dim: bool = False, underline: bool = False, blink: bool = False, reverse: bool = False, strikethrough: bool = False, reset: bool = False, hide: bool = False, ) -> str ``` ### Parameters - **messages** (*t.Any) - Variable number of arguments to be styled. - **fg** (ColorType | None) - Optional - Foreground color. - **bg** (ColorType | None) - Optional - Background color. - **bold** (bool) - Optional - Apply bold style. Defaults to False. - **italic** (bool) - Optional - Apply italic style. Defaults to False. - **dim** (bool) - Optional - Apply dim style. Defaults to False. - **underline** (bool) - Optional - Apply underline style. Defaults to False. - **blink** (bool) - Optional - Apply blink style. Defaults to False. - **reverse** (bool) - Optional - Apply reverse style. Defaults to False. - **strikethrough** (bool) - Optional - Apply strikethrough style. Defaults to False. - **reset** (bool) - Optional - Reset all styles. Defaults to False. - **hide** (bool) - Optional - Apply hide style. Defaults to False. ### Returns - **str** - The styled string. ``` -------------------------------- ### Define Negative Flags with `arg` and `negative` Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md Configure negative flag names using the `arg` helper with the `negative` parameter. This allows users to explicitly set a boolean flag to `False` via the command line. ```python from clypi import Command, arg # With the flag ON: my-command --my-flag # With the flag OFF: my-command --no-my-flag ``` -------------------------------- ### Add Positional Arguments to Clypi CLI Source: https://github.com/danimelchor/clypi/blob/master/docs/learn/getting_started.md Demonstrates how to add positional arguments to a Clypi CLI. These arguments are required and their order matters. The snippet defines 'name' and 'age' as positional arguments. ```python from clypi import Command, Positional from typing_extensions import override class Cli(Command): name: Positional[str] age: Positional[int] @override async def run(self): print(f"Hello, {self.name}. You are {self.age}!") if __name__ == '__main__': cmd = Cli.parse() cmd.start() ``` -------------------------------- ### Clypi Path Parser Source: https://github.com/danimelchor/clypi/blob/master/docs/api/parsers.md Use cp.Path() to parse path-like objects. ```python cp.Path() ``` -------------------------------- ### Configure Argument Behavior with `arg` Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md Use the `arg` utility function to customize how a specific command-line argument is displayed and parsed. It allows setting defaults, parsers, help text, and prompting behavior. ```python def arg( default: T | Unset | EllipsisType = UNSET, parser: Parser[T] | None = None, default_factory: t.Callable[[], T] | Unset = UNSET, help: str | None = None, short: str | None = None, prompt: str | None = None, hide_input: bool = False, max_attempts: int = MAX_ATTEMPTS, negative: str | None = None, group: str | None = None, env: str | None = None, ) -> T ``` -------------------------------- ### Supported Built-in Types Source: https://github.com/danimelchor/clypi/blob/master/docs/api/parsers.md List of supported built-in types and their parser mappings. ```APIDOC ## Supported built-in types ### None - **Parser**: `cp.NoneParser()` ### Boolean - **Parser**: `cp.Bool()` ### Integer - **Parser**: `cp.Int()` ### Float - **Parser**: `cp.Float()` ### String - **Parser**: `cp.Str()` ### Path - **Parser**: `cp.Path()` ### Datetime - **Parser**: `cp.DateTime()` ### Timedelta - **Parser**: `cp.TimeDelta()` ### Enum - **Parser**: `cp.Enum()` ### List - **Description**: Represents a list of a specific type. - **Parser**: `cp.List()` - **Example**: `list[str]` maps to `cp.List(cp.Str())` ### Tuple - **Description**: Represents a tuple with specified types and optional length. - **Parser**: `cp.Tuple(, ) - **Examples**: - `tuple[str]` maps to `cp.Tuple(cp.Str())` - `tuple[str, int]` maps to `cp.Tuple(cp.Str(), cp.Int())` - `tuple[str, ...]` maps to `cp.Tuple(cp.Str(), num=None)` ### Union - **Description**: Represents a union of multiple types. - **Parser**: `cp.Union(*)` - **Examples**: - `str | None` maps to `cp.Union(cp.Str(), cp.NoneParser())` - `str | bool | int` maps to `cp.Union(cp.Str(), cp.Bool(), cp.Int())` ### Optional - **Description**: Represents an optional type, equivalent to a Union with None. - **Parser**: `cp.Union(, cp.NoneParser())` - **Example**: `Optional[str]` maps to `cp.Union(cp.Str(), cp.NoneParser())` ### Literal - **Description**: Represents a literal value or a set of literal values. - **Parser**: `cp.Literal(*)` - **Example**: `Literal[1, "foo"]` maps to `cp.Literal(1, "foo")` ``` -------------------------------- ### pre_run_hook Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md A function that runs before every parent command and subcommand execution. Useful for logging, metrics, etc. ```APIDOC ## `pre_run_hook` ### Description A function that will run on every parent command and subcommand right before it's execution. Useful to print before commands, emit metrics, and more! ### Method Signature ```python async def pre_run_hook(self: Command) -> None: ``` ### Example Usage ```python import logging from typing_extensions import override from clypi import Command class MyCommand(Command): @override async def pre_run_hook(self): cmd_str = " ".join(self.full_command()) logging.debug("Running %s", cmd_str) @override async def run(self): print("Hey") main = MyCommand.parse() main.start() ``` ``` -------------------------------- ### Define a post_run_hook for a Command Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md Implement this method to execute code after a command or subcommand finishes. Useful for processing exceptions or emitting metrics. ```python async def post_run_hook(self: Command, exception: Exception | None) -> None: ``` -------------------------------- ### Style Individual Text Pieces with Clypi Source: https://github.com/danimelchor/clypi/blob/master/docs/learn/beautiful_uis.md Style specific parts of a printed string using `clypi.style`. This allows for mixed colors within a single print statement. Import `clypi` to use this function. ```python import clypi print(clypi.style("This is blue", fg="blue"), "and", clypi.style("this is red", fg="red")) ``` -------------------------------- ### Add Optional Arguments (Options) to Clypi CLI Source: https://github.com/danimelchor/clypi/blob/master/docs/learn/getting_started.md Illustrates how to add optional named arguments (options) to a Clypi CLI. The 'age' argument is made optional and can be provided using the '--age' flag. ```python from clypi import Command, Positional from typing_extensions import override class Cli(Command): name: Positional[str] age: int | None = None @override async def run(self): print(f"Hello, {self.name}.") if self.age is not None: print(f"You are {self.age}!") if __name__ == '__main__': cmd = Cli.parse() cmd.start() ``` -------------------------------- ### Print Colorful Formatted Output Source: https://github.com/danimelchor/clypi/blob/master/README.md Use Clypi to print text with various color and style combinations directly or by creating reusable styler objects. This is useful for enhancing the readability and visual appeal of CLI output. ```python # demo.py import clypi # Print with colors directly clypi.cprint("Some colorful text", fg="green", reverse=True, bold=True, italic=True) # Style text print(clypi.style("This is blue", fg="blue"), "and", clypi.style("this is red", fg="red")) # Store a styler and reuse it wrong = clypi.Styler(fg="red", strikethrough=True) print("The old version said", wrong("Pluto was a planet")) print("The old version said", wrong("the Earth was flat")) ``` -------------------------------- ### User Input Markdown Test Source: https://github.com/danimelchor/clypi/blob/master/mdtest/README.md A Python code block annotated for mdtest that simulates user input. It asserts that the input received matches 'hello world'. ```python import sys assert input() == 'hello world', f"Expected the stdin to be 'hello world'" ``` -------------------------------- ### Prompt Function Source: https://github.com/danimelchor/clypi/blob/master/docs/api/prompts.md Prompts the user for a value, validates, and parses it using a specified parser. ```APIDOC ## `prompt` ```python def prompt( text: str, default: T | Unset = UNSET, parser: Parser[T] = str, hide_input: bool = False, max_attempts: int = MAX_ATTEMPTS, ) -> T: ``` ### Description Prompts the user for a value and uses the provided parser to validate and parse the input. ### Parameters #### Query Parameters - **text** (str) - Required - The text to display to the user when asking for input - **default** (T | Unset) - Optional - Optionally set a default value that the user can immediately accept - **parser** (Parser[T]) - Optional - A function that parses in the user input as a string and returns the parsed value or raises - **hide_input** (bool) - Optional - Whether the input shouldn't be displayed as the user types (for passwords, API keys, etc.) - **max_attempts** (int) - Optional - How many times to ask the user before giving up and raising ``` -------------------------------- ### post_run_hook Source: https://github.com/danimelchor/clypi/blob/master/docs/api/cli.md A function that runs after every parent command and subcommand execution. Useful for post-execution tasks and exception handling. ```APIDOC ## `post_run_hook` ### Description A function that will run on every parent command and subcommand right after it's execution. Useful to print after commands, process exceptions, emit metrics, and more! ### Method Signature ```python async def post_run_hook(self: Command, exception: Exception | None) -> None: ``` ``` -------------------------------- ### Clypi NoneParser Source: https://github.com/danimelchor/clypi/blob/master/docs/api/parsers.md Use cp.NoneParser() to handle None types. ```python cp.NoneParser() ``` -------------------------------- ### Define CLI Arguments with Type Annotations Source: https://github.com/danimelchor/clypi/blob/master/README.md Define CLI arguments using class-level type annotations, similar to Python dataclasses. Clypi automatically parses and validates these arguments. ```python from clypi import Command from typing_extensions import override class MyCli(Command): name: str # Automatically parsed as `--name `. @override async def run(self): print(f"Hi {self.name}!") cli = MyCli.parse() cli.start() ```