Skip to content

User Input

arc comes with tooling for requsting input from the user in the form of the arc.prompt package. Here's a quick example of it in action:

examples/user_input.py
import arc
from arc.prompt import Prompt


@arc.command()
def hello(prompt: Prompt):
    name = prompt.input("Name: ")

    while not prompt.confirm("Are you sure?"):
        name = prompt.input("Name: ")

    print(f"Hello, {name}!")


hello()

$ python user_input.py
Name: Sean
Are you sure? [y/n] y
Hello, Sean!

Writing a Question

Below is an example of how you could write a custom RegexQuesion that validates user input to match a provided regular expression

examples/custom_question.py
import re
from typing import Iterable
from arc.prompt import Prompt, Question


class RegexQuestion(Question[str]):
    def __init__(self, prompt: str, pattern: re.Pattern):
        super().__init__()
        self.prompt = prompt
        self.pattern = pattern

    def render(self) -> Iterable[str]:
        """Render should return an iterable of strings
        to output before stopping for input"""
        yield self.prompt
        yield f" [Must match: '{self.pattern.pattern}'] "

    def handle_answer(self, value: str) -> str:
        """The handle answer method checks the validity
        of the user input. In addition, it should perform any
        additional parsing / conversion of the value that is required
        and return that.
        """
        if not self.pattern.match(value):
            self.err(f"Must match pattern: '{self.pattern.pattern}'")

        return value


prompt = Prompt()
question = RegexQuestion("Pick a number", re.compile("\d+"))
number = prompt.ask(question)
print(f"You picked: {number}")

$ python custom_question.py
Pick a number [Must match: '\d+'] 2
You picked: 2

You can look at the reference to see the kinds of questions that arc ships with by default.

Configuring the Prompt

You can provide your own Prompt instance like so:

import arc
from arc.prompt import Prompt

arc.configure(prompt=Prompt()) # could also be a subclass, etc...

Tip

The prompt object you recieve via dependency injection is the same object that powers the prompt functionality of parameters. By configuring your own customized instance of the prompt, you can have the same appearance across both uses.