Search code examples
pythonwindowscmdasciigetch

Python 3.4: getch() - A Typewriter - Python


Main question, for the way my python program is built, I am trying to build a typewriter for my program that when a key is pressed it refreshes like a GUI. However, I am encountering a weird problem with ASCII especially Backspace.

from msvcrt import getch
import os
#Test
# Always run in Python CMD
myinput = ""
Finished = False
while Finished != True:
    os.system('cls')
    print("Name: " + myinput)
    while True:
        key = ord(getch())
        realkey = chr(key)
        print(key)
        if key != 0:
            if key == 13: #Enter
                Finished = True
                break
            else:
                myinput = myinput + realkey
                break

When you are typing something in the mini typewriter, then you make a mistake and you press Backspace, it look like it did nothing however when you press a key again strangely it wil overwrite the char depending on how many times you backspaced, and even stranglely if you backspace more then you typed, it would actually overwrite the consoles output. I know for sure its not an error in my block, it is just how ASCII works.

P
>Name: P
y
>Name: Py
t
>Name: Pyt
h
>Name: Pyth
o
>Name: Pytho
n
>Name: Python
(Backspace)
>Name: Python
(Backspace)
>Name: Python
(Backspace)
>Name: Python
K
>Name: PytKon
#See?!    |

Why? and How can I fix this error? Is there a cleaner way to do what I'm doing? But it has to be done in the GUI style I've done. (If that makes sense)

Also, I know that this getch() is supposed to capture everything I type, but is there a way to capture only proper characters( Basically I want my typewrite to be like input() ) without having to if condition every single illegal char?

Thank you.


Solution

  • I am guessing that you are using the curses library. If you are, you can use from curses import ascii to get the ASCII values of characters. In this case, you can use ascii.DEL to get the value of the backspace key: 127. The backspace key is often written with \b. Just try typing print("foo\b\b") into the Python shell. You will see that the whole string is printed. If you do print("foo\b\bf"), though, ffo is printed. This is because the \b character just moves the cursor to the left by one character. It doesn't actually overwrite characters with spaces to remove them from the screen. You need to treat the backspace character as special:

    myinput = ""
    Finished = False
    while Finished != True:
        os.system('cls')
        print("Name: " + myinput)
        while True:
            key = ord(getch())
            realkey = chr(key)
            print(key)
            if key != 0:
                if key == 13: #Enter
                    Finished = True
                elif key == ascii.DEL:
                    myinput = myinput[:-1]
                else:
                    myinput += realkey
                break
    

    Edit: Actual code used by the OP:

    from msvcrt import getch
    import os
    
    Finished = False
    mydict = "" ## my_dict has no special value, just decided to call it that.
    
    while Finished != True:
        while True:
            key = ord(getch())
            realkey = chr(key)
            if key != 0:
                if key == 13: #Enter
                    Finished = True
                    break
                elif key == 8: #Backspace
                    my_dict[CurrentItem] = my_dict[CurrentItem][:-1]
                    break
                elif key in range(32, 127):
                    my_dict[CurrentItem] += realkey
                    break