# 36. Command Line Interfaces (CLI)

Creating Command Line Interfaces (CLIs) in Python is a common task, and libraries like `argparse` and `click` make it easy to build powerful and flexible command-line tools. Here are several code snippets that demonstrate how to use these libraries for building robust CLI tools.

***

**1. Basic CLI with argparse**

This is a basic example of how to use `argparse` to create a command-line tool that accepts arguments.

```python
import argparse

def main():
    parser = argparse.ArgumentParser(description="A simple CLI tool.")
    parser.add_argument('name', type=str, help="Your name")
    parser.add_argument('age', type=int, help="Your age")

    args = parser.parse_args()
    
    print(f"Hello {args.name}, you are {args.age} years old!")

if __name__ == "__main__":
    main()
```

***

**2. CLI with Optional Arguments (argparse)**

This example demonstrates how to add optional arguments to your CLI tool.

```python
import argparse

def main():
    parser = argparse.ArgumentParser(description="CLI with optional arguments.")
    parser.add_argument('name', type=str, help="Your name")
    parser.add_argument('--greet', action='store_true', help="Whether to greet you or not")

    args = parser.parse_args()
    
    if args.greet:
        print(f"Hello {args.name}!")
    else:
        print(f"Goodbye {args.name}!")

if __name__ == "__main__":
    main()
```

***

**3. CLI with Default Values (argparse)**

You can set default values for your arguments in `argparse`.

```python
import argparse

def main():
    parser = argparse.ArgumentParser(description="CLI with default values.")
    parser.add_argument('--name', type=str, default="John", help="Your name")
    
    args = parser.parse_args()
    
    print(f"Hello {args.name}!")

if __name__ == "__main__":
    main()
```

***

**4. CLI with Subcommands (argparse)**

`argparse` allows you to implement subcommands in your CLI tool.

```python
import argparse

def hello():
    print("Hello from the 'hello' command!")

def goodbye():
    print("Goodbye from the 'goodbye' command!")

def main():
    parser = argparse.ArgumentParser(description="CLI with subcommands.")
    subparsers = parser.add_subparsers()

    hello_parser = subparsers.add_parser('hello', help="Say hello")
    hello_parser.set_defaults(func=hello)

    goodbye_parser = subparsers.add_parser('goodbye', help="Say goodbye")
    goodbye_parser.set_defaults(func=goodbye)

    args = parser.parse_args()
    args.func()

if __name__ == "__main__":
    main()
```

***

**5. CLI with Arguments Validation (argparse)**

You can add custom validation to your arguments using `argparse`.

```python
import argparse

def check_age(value):
    ivalue = int(value)
    if ivalue < 0:
        raise argparse.ArgumentTypeError("%s is not a valid age" % value)
    return ivalue

def main():
    parser = argparse.ArgumentParser(description="CLI with argument validation.")
    parser.add_argument('age', type=check_age, help="Your age")

    args = parser.parse_args()
    print(f"Your age is {args.age}!")

if __name__ == "__main__":
    main()
```

***

**6. Basic CLI with Click**

This is a basic example using the `click` library to create a CLI tool.

```python
import click

@click.command()
@click.argument('name')
@click.argument('age', type=int)
def greet(name, age):
    click.echo(f"Hello {name}, you are {age} years old!")

if __name__ == '__main__':
    greet()
```

***

**7. CLI with Options (Click)**

This example demonstrates how to add options to your CLI tool with `click`.

```python
import click

@click.command()
@click.argument('name')
@click.option('--greet', is_flag=True, help="Whether to greet you or not")
def greet(name, greet):
    if greet:
        click.echo(f"Hello {name}!")
    else:
        click.echo(f"Goodbye {name}!")

if __name__ == '__main__':
    greet()
```

***

**8. CLI with Default Values and Click**

You can also set default values for options in `click`.

```python
import click

@click.command()
@click.option('--name', default='John', help="Your name")
def greet(name):
    click.echo(f"Hello {name}!")

if __name__ == '__main__':
    greet()
```

***

**9. CLI with Complex Subcommands (Click)**

`click` also supports subcommands for more complex CLI tools.

```python
import click

@click.group()
def cli():
    pass

@click.command()
def hello():
    click.echo("Hello from the 'hello' command!")

@click.command()
def goodbye():
    click.echo("Goodbye from the 'goodbye' command!")

cli.add_command(hello)
cli.add_command(goodbye)

if __name__ == '__main__':
    cli()
```

***

**10. CLI with Custom Validation and Click**

Here’s how to implement custom validation logic using `click`.

```python
import click

def validate_age(ctx, param, value):
    if value < 0:
        raise click.BadParameter("Age cannot be negative.")
    return value

@click.command()
@click.argument('name')
@click.option('--age', type=int, help="Your age", default=0, callback=validate_age)
def greet(name, age):
    click.echo(f"Hello {name}, you are {age} years old!")

if __name__ == '__main__':
    greet()
```

***

These snippets cover basic and advanced usage of both `argparse` and `click` for building command-line tools, providing the flexibility to handle simple to complex arguments, subcommands, validations, and options. You can choose between `argparse` for a built-in solution or `click` for a more user-friendly approach with additional features.
