curses - addstr 文本在较大的终端中不可见
curses - addstr text is not visible in larger terminals
我正在编写一个使用 Python 的 curses 库的 IRC 客户端,但是服务器的响应没有在屏幕上正确输出。
基本上,我的终端越小,输出就越接近它应该的样子:
在全尺寸终端(1366x768分辨率)上基本没有输出
在半尺寸的终端上,可见的输出要多得多
在四分之一大小的终端上,程序输出了我期望的所有内容。
根据这个模式,我最好的猜测是一些行长度问题,但我真的不知道问题是什么。
源代码
import curses
import queue
import socket
import threading
import time
PAD_LENGTH = 1000
def main(stdscr):
s = socket.create_connection(("chat.freenode.net",6667))
s.settimeout(1.0)
s.send(b"PASS hello\r\n")
s.send(b"NICK testingclient\r\n")
s.send(b"USER testingclient tclient tclient :Test Client\r\n")
s.setblocking(False)
curses.noecho()
curses.cbreak()
stdscr.nodelay(1)
pad = curses.newpad(PAD_LENGTH,curses.COLS-1)
top = 0
while True:
try:
msg = s.recv(512).decode("latin-1")
pad.addstr(msg)
except BlockingIOError:
pass
kc = stdscr.getch()
if kc != -1:
k = chr(kc)
if k == "q":
break
elif k == "j" and top < PAD_LENGTH:
top += 1
elif k == "k" and top > 0:
top -= 1
pad.refresh(top,0,0,0,curses.LINES-1,curses.COLS-1)
s.close()
curses.nocbreak()
curses.echo()
curses.endwin()
curses.wrapper(main)
杂项注释
我在 VirtualBox
中的 Arch Linux 上使用 i3 和 xterm
LINES 和 COLS 值在任何意义上都不是 magic;它们由基于终端大小(来自操作系统)的 curses 库初始化,并且可以(通常)通过设置环境变量(名为 $LINES 和 $COLUMNS)来覆盖。有关详细信息,请阅读 use_env
的手册页
如果您的应用程序使用更窄的格式更具可读性,那么您始终可以在脚本中检查 COLS 的值并在此处限制传递给 curses.newpad 的值:
pad = curses.newpad(PAD_LENGTH,curses.COLS-1)
比如说,到 40。您应该在该调用中使用您自己的变量(COLS 的副本),并在此处对 COLS 的其他引用中重用它:
pad.refresh(top,0,0,0,curses.LINES-1,curses.COLS-1)
如前所述,您可以使用环境变量对其进行操作,但并不经常使用。请记住,如果您将 $LINES and/or $COLUMNS 设置为 比终端提供的值更大 的值,则结果不会很好。
回顾一下评论(还有其他可能相关的陷阱,但我没有合适的配置来测试你的脚本):
- pad 与 stdscr 不是同一个内存块。给定 window 上的 getch 告诉 curses 刷新 window。因此,如果 window 上有未决更改,它会覆盖任何其他 window,因为 curses 库将数据复制到 curscr.
- 另一个潜在的问题是如果你的 addstr 写了换行符。 addch/addstr 中的换行符将清除该行的其余部分。
问题是由于在带有回车符 return 的字符串上使用 addstr
引起的。
我不知道 \r
在 curses 中的具体行为,但是将消息更改为 msg = s.recv(512).decode("latin-1").replace("\r\n","\n")
已经为我提供了完美的输出。
我正在编写一个使用 Python 的 curses 库的 IRC 客户端,但是服务器的响应没有在屏幕上正确输出。
基本上,我的终端越小,输出就越接近它应该的样子:
在全尺寸终端(1366x768分辨率)上基本没有输出
在半尺寸的终端上,可见的输出要多得多
在四分之一大小的终端上,程序输出了我期望的所有内容。
根据这个模式,我最好的猜测是一些行长度问题,但我真的不知道问题是什么。
源代码
import curses
import queue
import socket
import threading
import time
PAD_LENGTH = 1000
def main(stdscr):
s = socket.create_connection(("chat.freenode.net",6667))
s.settimeout(1.0)
s.send(b"PASS hello\r\n")
s.send(b"NICK testingclient\r\n")
s.send(b"USER testingclient tclient tclient :Test Client\r\n")
s.setblocking(False)
curses.noecho()
curses.cbreak()
stdscr.nodelay(1)
pad = curses.newpad(PAD_LENGTH,curses.COLS-1)
top = 0
while True:
try:
msg = s.recv(512).decode("latin-1")
pad.addstr(msg)
except BlockingIOError:
pass
kc = stdscr.getch()
if kc != -1:
k = chr(kc)
if k == "q":
break
elif k == "j" and top < PAD_LENGTH:
top += 1
elif k == "k" and top > 0:
top -= 1
pad.refresh(top,0,0,0,curses.LINES-1,curses.COLS-1)
s.close()
curses.nocbreak()
curses.echo()
curses.endwin()
curses.wrapper(main)
杂项注释
我在 VirtualBox
中的 Arch Linux 上使用 i3 和 xtermLINES 和 COLS 值在任何意义上都不是 magic;它们由基于终端大小(来自操作系统)的 curses 库初始化,并且可以(通常)通过设置环境变量(名为 $LINES 和 $COLUMNS)来覆盖。有关详细信息,请阅读 use_env
的手册页如果您的应用程序使用更窄的格式更具可读性,那么您始终可以在脚本中检查 COLS 的值并在此处限制传递给 curses.newpad 的值:
pad = curses.newpad(PAD_LENGTH,curses.COLS-1)
比如说,到 40。您应该在该调用中使用您自己的变量(COLS 的副本),并在此处对 COLS 的其他引用中重用它:
pad.refresh(top,0,0,0,curses.LINES-1,curses.COLS-1)
如前所述,您可以使用环境变量对其进行操作,但并不经常使用。请记住,如果您将 $LINES and/or $COLUMNS 设置为 比终端提供的值更大 的值,则结果不会很好。
回顾一下评论(还有其他可能相关的陷阱,但我没有合适的配置来测试你的脚本):
- pad 与 stdscr 不是同一个内存块。给定 window 上的 getch 告诉 curses 刷新 window。因此,如果 window 上有未决更改,它会覆盖任何其他 window,因为 curses 库将数据复制到 curscr.
- 另一个潜在的问题是如果你的 addstr 写了换行符。 addch/addstr 中的换行符将清除该行的其余部分。
问题是由于在带有回车符 return 的字符串上使用 addstr
引起的。
我不知道 \r
在 curses 中的具体行为,但是将消息更改为 msg = s.recv(512).decode("latin-1").replace("\r\n","\n")
已经为我提供了完美的输出。