An open API service indexing awesome lists of open source software.

https://github.com/likianta/argsense-cli

New command line interface based on Python Rich library.
https://github.com/likianta/argsense-cli

argparse cli click command-line command-line-interface python python-cli python-rich rich rich-cli rich-click typer

Last synced: 6 months ago
JSON representation

New command line interface based on Python Rich library.

Awesome Lists containing this project

README

        

# Argsense CLI

**argsense** is a command line interface made with Python.

![group help](.assets/examples/classic/20220615143658.jpg)

![minimal help](.assets/examples/classic/20220615143730.jpg)

![command help](.assets/examples/classic/20220615143751.jpg)

![group help (ex)](.assets/examples/classic/20220615143817.jpg)

## Usage

> Currently this section is under construction.
>
> Please check the folder ./examples for your reference.

## Comparison to other CLIs

> I picked several official examples from [Typer](https://typer.tiangolo.com/) project to show differences by code to code.

### Hello world

**typer**

```python
import typer

def main(name: str):
typer.echo(f"Hello {name}")

if __name__ == "__main__":
typer.run(main)
```

**argsense**

```python
from argsense import cli

@cli.cmd()
def main(name: str):
print(f'Hello {name}')

if __name__ == '__main__':
cli.run(main)
```

![](.assets/20220618124348.png)

### Multiple subcommands

**typer**

```python
import typer

app = typer.Typer()

@app.command()
def hello(name: str):
typer.echo(f"Hello {name}")

@app.command()
def goodbye(name: str, formal: bool = False):
if formal:
typer.echo(f"Goodbye Ms. {name}. Have a good day.")
else:
typer.echo(f"Bye {name}!")

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

**argsense**

```python
from argsense import cli

@cli.cmd()
def hello(name: str):
print(f'Hello {name}')

@cli.cmd()
def goodbye(name: str, formal: bool = False):
if formal:
print(f'Goodbye Ms. {name}. Have a good day.')
else:
print(f'Bye {name}!')

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

![](.assets/snip-20220618-124911.png)

![](.assets/snip-20220618-125016.png)

### Making an optional argument

**typer**

```python
import typer
from typing import Optional

def main(name: Optional[str] = typer.Argument(None)):
if name is None:
typer.echo("Hello World!")
else:
typer.echo(f"Hello {name}")

if __name__ == "__main__":
typer.run(main)
```

**argsense**

```python
"""
Argsense (v0.3.0) doesn't have a conception of 'optional' argument, an argument
must be required, or it is considered as an `option`.
We will bring the support in next version (v0.4.0+).
"""
from argsense import cli

@cli.cmd()
def main(name: str = None):
if name is None:
print('Hello World!')
else:
print(f'Hello {name}')

if __name__ == '__main__':
cli.run(main)
```

*You have to use `--name` to pass the 'optional argument', otherwise it raises an error.*

![](.assets/snip-20220618-130345.png)

### An argument with a default value

**typer**

```python
import typer

def main(name: str = typer.Argument("Wade Wilson")):
typer.echo(f"Hello {name}")

if __name__ == "__main__":
typer.run(main)
```

**argsense**

```python
"""
Argsense (v0.3.0) doesn't have a conception of 'optional' argument, an argument
must be required, or it is considered as an `option`.
We will bring the support in next version (v0.4.0+).
"""
from argsense import cli

@cli.cmd()
def main(name='Wade Wilson'):
print(f'Hello {name}')

if __name__ == '__main__':
cli.run(main)
```

![](.assets/snip-20220618-131756.png)

### Dynamic choices for argument

**typer**

```python
import random
import typer

def get_name():
return random.choice(["Deadpool", "Rick", "Morty", "Hiro"])

def main(name: str = typer.Argument(get_name)):
typer.echo(f"Hello {name}")

if __name__ == "__main__":
typer.run(main)
```

**argsense**

```python
"""
Argsense doesn't have built in support for choices.
Here is a workaround but not so good.
"""
from argsense import cli

@cli.cmd()
def main(name: str):
"""
args:
name: The name should be one of the choices:
- [red]Deadpool[/]
- [green]Rick[/]
- [yellow]Morty[/]
- [cyan]Hiro[/]
"""
if name not in ('Deadpool', 'Rick', 'Morty', 'Hiro'):
print(f'The given name ({name}) is not on the list!')
exit(1)
print(f'Hello {name}')

if __name__ == '__main__':
cli.run(main)
```

![](.assets/snip-20220618-132948.png)

### Help information / Command description

The example shows:

- Command description.
- Long description that exceeds 80 characters one line (let's see how do we do line breaks).
- Multiple lines of description.

**typer**

```python
import typer

def main(
name: str = typer.Argument(..., help="The name of the user to greet"),
lastname: str = typer.Option(
"", "--lastname", "-l",
help="Last name of person to greet."
),
formal: bool = typer.Option(False, help="Say hi formally."),
):
"""
Say hi to NAME very gently, like Dirk. Optionally with a --lastname/-l, like
Wilson.

If --formal is used, say hi very formally.
"""
if formal:
typer.echo(f"Good day Ms. {name} {lastname}.")
else:
typer.echo(f"Hello {name} {lastname}")

if __name__ == "__main__":
typer.run(main)
```

**argsense**

```python
from argsense import cli

@cli.cmd()
def main(name: str, lastname='', formal=False):
"""
Say hi to [blue]NAME[/] very gently, like Dirk. Optionally with a -
[dim]--lastname/-l[/], like Wilson.
If [dim]--formal[/] is used, say hi very formally.

args:
name: The name of the user to greet.

kwargs:
lastname (-l): Last name of person to greet.
formal: Say hi formally.
"""
if formal:
print(f'Good day Ms. {name} {lastname}.')
else:
print(f'Hello {name} {lastname}')

if __name__ == '__main__':
cli.run(main)
```

![](.assets/snip-20220618-135437.png)

### Confirmation Prompt

**typer**

```python
import typer

def main(
name: str,
email: str = typer.Option(..., prompt=True, confirmation_prompt=True)
):
typer.echo(f"Hello {name}, your email is {email}")

if __name__ == "__main__":
typer.run(main)
```

**argsense**

```python
"""
Argsense doesn't have built in support for confirmation prompt.
Here is a workaround but not so good.
"""
from argsense import cli

@cli.cmd()
def main(name: str):
email = input('Email: ')
if input('Repeat for confirmation: ') != email:
print('Email repetition failed.')
exit(1)

print(f'Hello {name}, your email is {email}')

if __name__ == '__main__':
cli.run(main)
```

![](.assets/snip-20220618-140432.png)