I have a Python program I am writing and I want it to be able to change text after it is printed. For example, let\'s say I want to print \"hello\" and erase one letter eve
You could use dynamical stdout with getch() characters and loop
Example: https://asciinema.org/a/238478
Code:
# Script make you able to edit printed text
# stdin and stdout at the same time
# https://asciinema.org/a/238478
# https://gist.github.com/SoleSensei/05a97bbe8b75cd2368a8e6d5e00d6047
import sys
from getch import getch
def flush_append(char):
# just append char to the end
sys.stdout.write(char)
sys.stdout.flush()
def flush_write(line):
# clear all and rewrite line
sys.stdout.write(f"\r{' '*100}\r")
sys.stdout.flush()
sys.stdout.write(line)
sys.stdout.flush()
def interactive_input(line):
flush_write(line)
c = getch()
while ord(c) not in (13, 3): # 13 - Enter, 3 - Ctrl+C
if ord(c) in (127, 8): # 127,8 - Backspace (Unix, Windows)
line = line[:-1]
flush_write(line)
else:
# decode to string if byte
c = c.decode('ascii') if str(c)[0] == 'b' else c
line += c
flush_append(c)
c = getch()
print() # add EOL
return line
s = interactive_input('stdout editable line')
Here's one way to do it.
print 'hello',
sys.stdout.flush()
...
print '\rhell ',
sys.stdout.flush()
...
print '\rhel ',
sys.stdout.flush()
You can probably also get clever with ANSI escapes. Something like
sys.stdout.write('hello')
sys.stdout.flush()
for _ in range(5):
time.sleep(1)
sys.stdout.write('\033[D \033[D')
sys.stdout.flush()
Here's something that seems to work well:
import time
text = '\rgood-bye'
for i in xrange(len(text), 0, -1):
print text[0:i],
time.sleep(1)
print ' '
You could use this:
call these modules:
import time
import sys
Then copy this method:
# Custom Print Method
def custom_print(string, how = "normal", dur = 0, inline = True):
Copy just this part for the method to do typing
# string = the string to print & how = way to print & dur = time to print whole word or letter & inline = print on single line or not
if how == "typing": # if how is equal to typing then run this block of code
letter = 1
while letter <= len(string):
new_string = string[0:letter]
if inline: sys.stdout.write("\r")
sys.stdout.write("{0}".format(new_string))
if inline == False: sys.stdout.write("\n")
if inline: sys.stdout.flush()
letter += 1
time.sleep(float(dur))
OR just this part of the method for a string to print in reverse
if how == "reverse": # if how is equal to reverse then run this block of code
new_string = string
while len(new_string) > 0:
if inline == True: sys.stdout.write("\r")
sys.stdout.write('{message: <{fill}}'.format(message=new_string, fill=str(len(string))))
if inline == False: sys.stdout.write("\n")
if inline == True: sys.stdout.flush()
new_string = new_string[0:len(new_string) - 1]
time.sleep(float(dur))
OR just this part of the method for a normal string to print normally
if how == "normal": # if how is equal to normal then run this block of code
sys.stdout.write("\r")
sys.stdout.write(string)
time.sleep(float(dur))
sys.stdout.write("\n")
OR you can put all of it in the method for all the options
All you have to do is call custom_print() instead of
print`
# custom_print("string", "howtoprint", seconds in int, inline:true or false)
custom_print("hello", "reverse", 1) # for reverse printing hello
custom_print("hello", "typing", 1) # for typing hello slowly
custom_print("hello", "normal", 0) # for just printing hello
custom_print("hello") # for just printing hello
For multi-line output, you can also clear the screen each time and reprint the entire thing:
from time import sleep
import os
def cls():
os.system('cls' if os.name=='nt' else 'clear')
message = 'hello'
for i in range(len(message), 0, -1):
cls()
print message[:i]
sleep(1)