Move the Cursor Back For taking Input Python
Solution 1:
Having looked at this further, my final solution is to create my own custom input. NB: this only works in windows command prompt. If you are looking to do this in Unix you will have to look into an alternative. I may update this answer later to support Unix. [Edit: Updated to support both Unix and Windows]
Again, this will not work in IDLE
This function takes a prefix for your input, the number of max_length of the input, and the blank_char to fill the length of the input with.
First, we capture the user input and if it is a displayable character, we add it to our word. Every time we get a new character we overwrite the existing input line to keep up to date with the current state of the word.
We also look for the b'\x08'
charater (backspace) so we can remove the last character from our word, and the return charcter to see if our user has pressed Enter.
Once enter has been pressed, return the word.
There is also a built in limit, where the user can only input as many characters as there are underscores, as this will cause letters to linger, you can always modify this by incrementing the number of underscores or something similar.
WINDOWS ONLY:
import msvcrt
def windows_get_input(prefix="", underscores=20, blank_char='_'):
word = ""
print(prefix + (underscores - len(word)) * blank_char, end='\r', flush=True)
# Reprint prefix to move cursor
print(prefix, end="", flush=True)
while True:
ch = msvcrt.getch()
if ch in b'\x08':
# Remove character if backspace
word = word[:-1]
elif ch in b'\r':
# break if enter pressed
break
else:
if len(word) == underscores:
continue
try:
char = str(ch.decode("utf-8"))
except:
continue
word += str(char)
# Print `\r` to return to start of line and then print prefix, word and underscores.
print('\r' + prefix + word + (underscores - len(word)) * blank_char, end='\r', flush=True)
# Reprint prefix and word to move cursor
print(prefix + word, end="", flush=True)
print()
return word
print(windows_get_input("Name: ", 20, '_'))
Handling both Windows and Unix
WINDOWS and UNIX:
def unix_getch():
import termios
import sys, tty
def _getch():
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(fd)
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch.encode("utf-8")
return _getch()
def get_input(prefix="", underscores=20, blank_char='_'):
word = ""
try:
import msvcrt
func = msvcrt.getch
except:
func = unix_getch
print(prefix + (underscores - len(word)) * blank_char, end='\r', flush=True)
# Reprint prefix to move cursor
print(prefix, end="", flush=True)
while True:
ch = func()
if ch in b'\x08\x7f':
# Remove character if backspace
word = word[:-1]
elif ch in b'\r':
# break if enter pressed
break
else:
if len(word) == underscores:
continue
try:
char = str(ch.decode("utf-8"))
except:
continue
word += str(char)
# Print `\r` to return to start of line and then print prefix, word and underscores.
print('\r' + prefix + word + (underscores - len(word)) * blank_char, end='\r', flush=True)
# Reprint prefix and word to move cursor
print(prefix + word, end="", flush=True)
print()
return word
print(get_input("Name: ", 20, '_'))
Handling IDLE
With IDLE, this fails. Thanks Python for giving us this... Anayway, if you want to handle running in IDLE, simply add the following at the top of the get_input()
function:
import sys
if 'idlelib.run' in sys.modules:
return input(prefix)
This will check if you are using IDLE and just prompt the user for input normally.
Solution 2:
Compose your prompt of text, a number of underscores, and then same number of backspace characters (\b
).
n_underscores = 45
a = input('Enter your name:' + '_' * n_underscores + '\b' * n_underscores)
print('Hi,', a)
Solution 3:
You can use a \r
character to return to the start of the line and overwrite text until you want the input cursor:
print("Enter your name: ____________________", end='\rEnter your name: ', flush=True)
a = input()
It is worth noting that moving a cursor only works in some consoles, for example, it will not work in IDLE, but it will work in windows command prompt