magmax / python-readchar

Python library to read characters and key strokes
MIT License
143 stars 43 forks source link

Provide input prompt functionality #98

Closed impredicative closed 1 year ago

impredicative commented 1 year ago

It may make sense to provide an input prompt functionality.

For example, with Python input, I can do:

input_str = input('Reading input: ')

This serves two purposes:

  1. It shows the input prompt.
  2. It echos the user input immediately on the same line. This is useful for clarity.

To get this with readchar, I would have to use something like:

import readchar

def input_char(prompt: str, /, *, echo: bool = True) -> str:
    print(prompt, end='', flush=True)
    char = readchar.readchar()

    if echo:
        print(char)
    else:
        print()
    return char

def input_key(prompt: str, /, *, echo: bool = True) -> str:
    print(prompt, end='', flush=True)
    key = readchar.readkey()

    if echo:
        print(key)
    else:
        print()
    return key

# Usage:
char = input_char('Reading a char: ')
key = input_key('Reading a key: ')
Cube707 commented 1 year ago

this is exactly provided by input, so why do you want it in readchar?

readchar is mostly meant for usecase where you don't want this and need finer controll, so you would write the functions yourself anyway?

impredicative commented 1 year ago

this is exactly provided by input, so why do you want it in readchar?

Huh. That's not true. With input I have to press Enter. With readchar I don't have to press Enter. This makes all the difference.

so you would write the functions yourself anyway?

When one is coming from having used input, an input prompt is probably the most common expected usage. What you're saying is as if Python didn't have input, and just had readchars (multiple) instead.

Cube707 commented 1 year ago

readchars most common usecase is something like this:

print("type a: ", end='')
while True:
    k = readchar()
    if k == 'a':
        break
    print(k, end='')

print("well done")

a input like function would re-prompt for every wrong input and is usually undesirable and the exact prosessing is specific to the usecase, so it cant be part of the libary.

So whats the usecase where this needs a prompt-function and it doesn't make more sens to prompt yourself, matcing your usecase

impredicative commented 1 year ago

So whats the usecase

I have to sometimes seek user confirmation for a very urgent action. There is no time to spare for the user to press Enter as with input. As soon as the y key is received using input_char (to indicate confirmation), the intended action is to be urgently executed.

Cube707 commented 1 year ago

I can defnetly see this usecase, but it is still quite special to you and not really something thats usefull inside the libary for a lot of people. You already have the function written, so just use it. Same for other users that will have slightly different requirement.

Also if you want your response so urgently, you will probably want to also implement a timeout. and than it becomes even more specific to your usecase...

Cube707 commented 1 year ago

but if you want to code it up, feel free to implement a generic approach and send in a PR

Cube707 commented 1 year ago

sidenote, you can shorten your function to this:

def input_char(prompt: str, /, *, echo: bool = True) -> str:
    print(prompt, end='', flush=True)
    char = readchar.readchar()
    if echo:
        print(char)
    return char
impredicative commented 1 year ago

you will probably want to also implement a timeout

Although I don't have a timeout, I do check the time used to receive the confirmation. If the user takes more than say five seconds to provide a character (from the time it was requested), it is considered invalid. In this case, the missile launch is aborted.

impredicative commented 1 year ago
print(prompt, end='', flush=True)

Thank you. I now use this.

I do need still a newline at the end even if the char is not echoed, which is why I have a print().