curses - текст addstr не виден в больших терминалах
Я пишу IRC-клиент, который использует библиотеку проклятий Python, но ответ сервера не выводится на экран должным образом.
По сути, чем меньше мой терминал, тем ближе вывод к тому, каким он должен быть:
На полноразмерном терминале (разрешение 1366х768) практически нет выхода
На терминале половинного размера гораздо более заметный вывод
На терминале размером с четверть программа выводит все, что я ожидаю.
Основываясь на этом шаблоне, я предпочитаю решить проблему длины строки, но я действительно не знаю, в чем проблема.
Исходный код
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)
Разные заметки
Я использую i3 и xterm на Arch Linux в VirtualBox
2 ответа
Проблема была вызвана использованием addstr
на строке с символом возврата каретки.
Я не знаю специфическое поведение \r
в проклятиях, но меняя сообщение на msg = s.recv(512).decode("latin-1").replace("\r\n","\n")
предоставил мне идеальный выход.
Значения LINES и COLS не являются магией в любом смысле; они инициализируются библиотекой 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 и / или $ COLUMNS более высокие значения, чем то, что обеспечивает терминал, результат не будет хорошим.
Напомним из комментариев (есть и другие подводные камни, которые могут иметь значение, но у меня нет подходящей конфигурации для тестирования вашего скрипта):
- Пэд не такой же кусок памяти, как stdscr. Getch в данном окне сообщает curses обновить это окно. Поэтому, если в окне ожидающие изменения, оно перезаписывает любое другое окно, поскольку библиотека curses копирует данные в curscr.
- Другая потенциальная проблема, если ваш addstr пишет новые строки. Новая строка в addch / addstr очистит остаток строки.