can one get the key used to select in python inquirerpy inquirer.select?

213 views Asked by At

Using python3.10 and InquirerPy inquirer I would like to be able to take a choice and run another inquirer prompt based on that choice then return to the select.

I have something like this:

from InquirerPy import inquirer
    prompt = inquirer.select(
        "Edit an item",
        mandatory=False,
        keybindings={
            "answer": [
                {"key":"enter"},
                {"key":"e"},
                {"key":"i"},
                {"key":"d"},
                {"key":"n"},
                {"key":"p"}
            ],
            "skip": [
                {"key":"q"}
            ]
        },
        choices=choices,
        long_instruction="'e' to edit, 'n' to insert after, 'i' to insert before, 'd' to delete current, 'p' to print, 'q' when finished",
    )

When I .execute() this I would like to get the normal choice and the key pressed to choose it.

Is there a way to get the key pressed and the choice from inquirer.select? Alternately, is there a way to trigger the selection from within a @prompt.register_kb event handler? (in which case I imagine I could save the event so that I could inspect the key pressed later).

Option 1:

    choice = prompt.execute()
    if prompt.event.key_sequence[0].key == 'p':
       inquirer.confirm(f"Did you mean to 'p' {choice}?").execute()

Option 2:

This currently fails with RuntimeError('This event loop is already running') but otherwise it does provide me with the event to determine the keypress (and I could have a different event handler for each keypress.

@prompt.register_kb('p')
def _handle_key_p(event):
    inquirer.confirm(f"Did you meant to 'p' {prompt.result_name}?").execute()

Is there a way to stop the outer event loop so that I can run additional prompts?

Option 3:

@prompt.register_kb('p')
def _handle_key_p(event):
    prompt.answer()  # somehow preserving event for Option 1 to inspect

I originally tried to use @prompt.register_kb which successfully passes the choice to a function according to the key pressed, but since we are still within the execute() loop, I cannot run another inquirer prompt. It fails with 'This event loop is already running'.

I have inspected the prompt and event objects within the register_kb event handler and I don't see anything that does what I need.

For Option 1 I tried:

1.1

print(dir(prompt))

And then inspecting quite a few of the available methods and attributes. None seemed to have the event or the keypress.

For Option 2 I tried:

2.1

(inside register_kb handler)

prompt.status['result'] = prompt.result_name
prompt.status['answered'] = True

This did not change the fact that we were still executing. My _handle_key_p did not return anything in particular.

2.2

(inside register_kb handler)

return True

2.3

(inside register_kb handler)

return False

The documentation doesn't mention these as possibilities, I was just trying to find anything that worked.

1

There are 1 answers

0
M Rice On

I found event.app.exit() as one way to achieve Option 3

    @prompt.register_kb("p")
    @prompt.register_kb("i")
    @prompt.register_kb("n")
    @prompt.register_kb("e")
    @prompt.register_kb("d")
    def _handle_key(event):
        """When one of these keys is pressed we want to exit the prompt as it
        it were answered, saving the event for later inspection."""
        global current_event
        current_event = event
        prompt.status["answered"] = True
        prompt.status["result"] = prompt.result_name
        event.app.exit(result=prompt.result_value)

This exits my current prompt and lets me check current_event for the event details (current_event.key_sequence[0].key).