I'm in the process of writing a server application in Python3 to handle and manage several client connections at the same time. I need to be able to send data to the clients while also instantly printing anything they send and any information from my program. Most answers on SO regarding this recommend using Urwid or Curses. I chose urwid mainly because it's more high-level and harder to mess up.
After looking through the docs, some tutorials and some examples, I managed to piece together this code:
import urwid
def await_command():
return urwid.Pile([urwid.Edit(("root@localhost~# "))])
# This will actually send the command in the future and wait for a reply
def process_command(command):
return urwid.Text(("root@localhost~# " + command + "\nCommand [" + command + "] executed successfully!"))
class CommandListBox(urwid.ListBox):
def __init__(self):
body = urwid.SimpleFocusListWalker([await_command()])
super().__init__(body)
def keypress(self, size, key):
key = super().keypress(size, key)
if key != 'enter': return key
try: command = self.focus[0].edit_text
except TypeError: return
pos = self.focus_position
self.body.insert(pos, process_command(command))
self.focus_position = pos + 1
self.focus[0].set_edit_text("")
main_screen_loop = urwid.MainLoop(CommandListBox()).run()
This works mostly like a normal terminal with the exception that it should be possible to insert text above the current line which awaits input.
Being a complete newbie to Urwid, I have no idea how this could be done in Python. I'm guessing it would just involve finding which line we're at and inserting a new one above it. Could anyone provide an example of how this can be done? Any improvements to my code are also welcome.
Thanks in advance :)
As it turns out, it's pretty simple. Posting this in case anyone has a similar problem. Any corrections and improvements are still welcome.
This is what did it for me:
def print(self, text): # A method of the CommandListBox function
"""Insert text just above where the cursor currently is."""
self.body.insert(self.focus_position, urwid.Text(text))
This still doesn't seem like a foolproof method since the position of the cursor can change but it seems to work so far.