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 очистит остаток строки.
Другие вопросы по тегам