websocket 在屏幕重置后获取输入中键入的字符串

nwsw7zdq  于 2024-01-09  发布在  其他
关注(0)|答案(1)|浏览(135)

我有一个WebSocket聊天应用程序。用户可以同时发送和接收消息。然而,我遇到的问题是,因为它是一个CLI应用程序,用户的输入线被传入的消息搞砸了。
你会有这样的东西:

Message: Hello
Type message: Hi
Message: How are you

字符串
我想有输入字段的用户总是低于“聊天屏幕”。

Message: Hello
Message: How are you

Type message: Hi


我通过将所有收到的消息放在一个列表中来实现这一点。当收到新消息时,屏幕将清空,并显示聊天列表的内容。在聊天列表上循环后,我们再次显示输入字段。这很好。

**我的问题:**当用户在输入字段中键入一条消息时,当他键入一条消息时,屏幕会被清空以显示聊天。但他在输入字段中键入的消息也会被清空。

# Chat session
Hello
How are you

Type message: Hi, I am o

# Message comes in > screen gets emptied to display chat again > user-input is also emptied
Hello
How are you
Test

Type message:

# Wanted behavior (The message the user was typing is still visible in input-field)
Hello
How are you
Test

Type message: Hi, I am oka

**注意:**有趣的是,当屏幕和输入被清空,用户按下回车键时,清空之前输入的消息仍然是send。这意味着Python必须将输入的字符串保存在缓冲区的某个地方。
当前行为(传入消息时输入重置):


的数据

需要的行为(输入进度在收到消息时保存):



就像我说的。即使屏幕被清空,按下回车键也会在清空之前发送输入字段的内容。所以Python必须在某个地方有一个包含字符串的缓冲区。我可以使用某种流或stdin缓冲区来检索消息吗?

产品代码:

import sys
import asyncio
import aioconsole

chat = []

async def start():
    sendTask = asyncio.ensure_future(send())
    receiveTask = asyncio.ensure_future(receiveSimulator())

    await asyncio.gather(sendTask, receiveTask)

async def send():
    while True:
        # Here I somehow need to capture the input of the user
        # even if he hasn't pressed enter
        sys.stdout.flush()
        sys.stdout.write("Type message: ")
        message = await aioconsole.ainput("")
        # Note that when the user sends a message, it is not directly
        # inputted in the chat. But first send to the server who
        # echo's it. Hence why we simulate it by calling receive
        receive(message)

def receive(message, sim = False):
    chat.append(message)
    reset_chat_screen(sim = sim)

# This function is purely to simulate a incoming message
async def receiveSimulator():
    await asyncio.sleep(8)
    receive("Incoming message", sim = True)

def reset_chat_screen(sim = False):
    # Empty screen
    print(chr(27) + "[2J")

    # Show all messages including new incoming one
    for message in chat:
        print(message)
  
    # Here I somehow need to put the captured input before the screen was emptied
    # e.g: sys.stdout.write("Type message: " + captured_input)
    if sim:
        sys.stdout.write("Type message: I am oka")
    else:
        sys.stdout.write("Type message: ")
    sys.stdout.flush()

if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(start())

alen0pnh

alen0pnh1#

多亏了this answer,我找到了解决方案。
这是我获取用户输入的函数:

@contextlib.contextmanager
def raw_mode(file):
    old_attrs = termios.tcgetattr(file.fileno())
    new_attrs = old_attrs[:]
    new_attrs[3] = new_attrs[3] & ~(termios.ECHO | termios.ICANON)
    try:
        termios.tcsetattr(file.fileno(), termios.TCSADRAIN, new_attrs)
        yield
    finally:
        termios.tcsetattr(file.fileno(), termios.TCSADRAIN, old_attrs)

async def get_user_input():
    with raw_mode(sys.stdin):
        global user_input

        reader = asyncio.StreamReader()
        loop = asyncio.get_event_loop()
        await loop.connect_read_pipe(lambda: asyncio.StreamReaderProtocol(reader), sys.stdin)

        while not reader.at_eof():
            ch = await reader.read(1)

            if ch == b'\n' or ch == '\r':
                r = user_input
                user_input = ""
                return r
            elif ch == b'\x7f':
                user_input = user_input[:-1]
                sys.stdout.write('\b \b')
                sys.stdout.flush()
            else:
                user_input += ch.decode('utf-8')
                sys.stdout.write(ch.decode('utf-8'))
                sys.stdout.flush()

字符串
在我的send()函数中,像这样检索用户输入:

async def send():
    while True:

        message = await get_user_input()

        # Note that when the user sends a message, it is not directly
        # inputted in the chat. But first send to the server who
        # echo's it. Hence why we simulate it by calling receive
        receive(message)


reset_chat_screen中,您可以调用

sys.stdout.write("> " + user_input)
    sys.stdout.flush()


user_input是全局变量。

相关问题