Issue
I have written the program below which is intended to act as the terminal UI for a chat I am about to build for a university project. At its present state, the aim is to always have the last line act as the area to write a message, and when enter is pressed the message is written above and the last line becomes blank again.
That works fine if that's all I want. But, I also want to always have a number of "prompt symbols" at the start of the last line, namely here :>
. To make that happen, when enter is pressed,the whole current line is deleted, the bare message is printed, a newline character inserted, and finally I wish to print the :>
in the new line and repeat.
What happens, however, is that the prompt string is indeed printed, but the cursor, after the first enter pressed, begins at the start of the line, which means any subsequent input will overwrite the prompt characters. That does not happen the first time for some reason, where the first prompt is printed before anything else happens.
So in the end, I would like for a way for the cursor to actually start after the two prompt characters when a newline is printed. This is all I want as regards to functionality of the terminal, therefore I would like to find an easy way to solve this and be done with it instead of meddling with ncurses
library and the likes. Thank you all for your time. The point of interest in the code where happens whatever I want to happen is inside the last while loop.
The code should be run with Python3.
import sys
from string import printable
import termios
import tty
class _Getch:
"""Gets a single character from standard input. Does not echo to the
screen."""
def __init__(self):
try:
self.impl = _GetchWindows()
except ImportError:
self.impl = _GetchUnix()
def __call__(self): return self.impl()
class _GetchUnix:
def __init__(self):
import tty, sys
def __call__(self):
import sys, tty, termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
# ch = sys.stdin.read(1)
ch = sys.stdin.read(1)[0]
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
class _GetchWindows:
def __init__(self):
import msvcrt
def __call__(self):
import msvcrt
return msvcrt.getch()
# enter: ord 13
#backspace: ord 127
current_input = ""
prompt_msg = ":> "
print(10*"\n"+prompt_msg,end="")
getch = _Getch()
def clear_input():
linelen = (len(current_input)+len(prompt_msg))
sys.stdout.write("\b"*linelen+" "*linelen+"\b"*linelen)
sys.stdout.flush()
while(True):
ch=getch()
if ord(ch)==3:# ctrl+c
exit()
# >>>>>>>.POINT OF INTEREST<<<<<<<<<<<
if ord(ch)==13:# enter
clear_input()
print(current_input)
current_input = ""
# print(prompt_msg,end="")
sys.stdout.write(prompt_msg)
sys.stdout.flush()
if ord(ch)==127 and len(current_input)>0:# backspace
sys.stdout.write("\b"+" "+"\b")
sys.stdout.flush()
current_input=current_input[:-1]
if ch in printable or ord(ch)>127: # printable
current_input+=ch
sys.stdout.write(ch)
sys.stdout.flush()
Solution
Rather than trying to get the pointer to go two places forward - which I had no luck finding an answer for - I simply deleted the carriage return character ("\r") from the current_input
string in every place that should be done - there were rogue carriage return characters surviving in the string as it seems, that caused the problem.
Answered By - Noob Doob
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.