Python 诅咒终端调整大小问题
Python Curses Terminal Resize Issue
在可以处理调整大小的终端 window 底部打印一行的正确方法是什么?
import curses
from curses import wrapper
def main(stdscr):
inp = 0
y,x = stdscr.getmaxyx()
stdscr.clear()
stdscr.nodelay(1)
while inp != 48 and inp != 27:
stdscr.addnstr(y-1,0, 'I AM KILL TERMINAL WHEN RESIZE AAAAAAAH', x)
inp = stdscr.getch()
wrapper(main)
一旦我将终端的大小调整为更少的列,然后它尝试将字符串的长度换行到下一行并出错。我在文档中看不到任何关于禁用环绕的内容。
我尝试在 addstr 函数之前更新我的最大 y、x 值。
while inp != 48 and inp != 27:
if (y,x) != stdscr.getmaxyx():
y,x = stdscr.getmaxyx()
stdscr.addnstr(y-1,0, 'I AM KILL TERMINAL WHEN RESIZE AAAAAAAH', x)
inp = stdscr.getch()
我也试过捕获 SIGWINCH
while inp != 48 and inp != 27:
def resize_handler(signum, frame):
stdscr.erase()
stdscr.refresh()
termsize = shutil.get_terminal_size()
curses.resizeterm(termsize[1],termsize[0])
y,x = stdscr.getmaxyx()
signal.signal(signal.SIGWINCH, resize_handler)
stdscr.addnstr(y-1,0, 'I AM KILL TERMINAL WHEN RESIZE AAAAAAAH', x)
inp = stdscr.getch()
但是这些似乎都没有足够早地捕获终端更新。
对于给定的示例,正确处理SIGWINCH
的方法是包装stdscr.addnstr
和stdscr.getch
调用一个重绘文本的代码块(将字符数限制为现有的终端大小),在调整终端大小时经常这样做。
问题是 stdscr.getch
调用(实际上是 ncurses 中的 C 函数在做这项工作)被中断了。这就是第一个示例中在循环中执行的 refresh
。 ncurses 的 stdscr.getch
应该从 stdscr.getch
调用中返回一个 KEY_RESIZE
,应用程序可以使用它来判断何时重绘。 (这适用于 OpenBSD,它出于非技术原因省略了该功能)。
建立信号句柄可防止 ncurses 告知应用程序终端已调整大小。阅读第二个示例,似乎 ncurses 库仍将等待输入,已经完成将 addnstr
文本放在屏幕上的刷新(从第一次调整大小之前开始)。
讨论 Curses and resizing windows 显示了一个陷阱:如果应用程序不打算读取字符,它永远不会看到 KEY_RESIZE
。但是你的例子没有这样做。我会放弃信号处理程序(除了妨碍,它使用信号不安全的函数可以破坏 python),并将第一个示例更改为如下内容:
import curses
from curses import wrapper
def main(stdscr):
inp = 0
y,x = stdscr.getmaxyx()
stdscr.clear()
stdscr.nodelay(1)
while inp != 48 and inp != 27:
while True:
try:
stdscr.addnstr(y-1,0, 'I AM KILL TERMINAL WHEN RESIZE AAAAAAAH', x)
except curses.error:
pass
inp = stdscr.getch()
if inp != curses.KEY_RESIZE:
break
stdscr.erase()
y,x = stdscr.getmaxyx()
wrapper(main)
在可以处理调整大小的终端 window 底部打印一行的正确方法是什么?
import curses
from curses import wrapper
def main(stdscr):
inp = 0
y,x = stdscr.getmaxyx()
stdscr.clear()
stdscr.nodelay(1)
while inp != 48 and inp != 27:
stdscr.addnstr(y-1,0, 'I AM KILL TERMINAL WHEN RESIZE AAAAAAAH', x)
inp = stdscr.getch()
wrapper(main)
一旦我将终端的大小调整为更少的列,然后它尝试将字符串的长度换行到下一行并出错。我在文档中看不到任何关于禁用环绕的内容。
我尝试在 addstr 函数之前更新我的最大 y、x 值。
while inp != 48 and inp != 27:
if (y,x) != stdscr.getmaxyx():
y,x = stdscr.getmaxyx()
stdscr.addnstr(y-1,0, 'I AM KILL TERMINAL WHEN RESIZE AAAAAAAH', x)
inp = stdscr.getch()
我也试过捕获 SIGWINCH
while inp != 48 and inp != 27:
def resize_handler(signum, frame):
stdscr.erase()
stdscr.refresh()
termsize = shutil.get_terminal_size()
curses.resizeterm(termsize[1],termsize[0])
y,x = stdscr.getmaxyx()
signal.signal(signal.SIGWINCH, resize_handler)
stdscr.addnstr(y-1,0, 'I AM KILL TERMINAL WHEN RESIZE AAAAAAAH', x)
inp = stdscr.getch()
但是这些似乎都没有足够早地捕获终端更新。
对于给定的示例,正确处理SIGWINCH
的方法是包装stdscr.addnstr
和stdscr.getch
调用一个重绘文本的代码块(将字符数限制为现有的终端大小),在调整终端大小时经常这样做。
问题是 stdscr.getch
调用(实际上是 ncurses 中的 C 函数在做这项工作)被中断了。这就是第一个示例中在循环中执行的 refresh
。 ncurses 的 stdscr.getch
应该从 stdscr.getch
调用中返回一个 KEY_RESIZE
,应用程序可以使用它来判断何时重绘。 (这适用于 OpenBSD,它出于非技术原因省略了该功能)。
建立信号句柄可防止 ncurses 告知应用程序终端已调整大小。阅读第二个示例,似乎 ncurses 库仍将等待输入,已经完成将 addnstr
文本放在屏幕上的刷新(从第一次调整大小之前开始)。
讨论 Curses and resizing windows 显示了一个陷阱:如果应用程序不打算读取字符,它永远不会看到 KEY_RESIZE
。但是你的例子没有这样做。我会放弃信号处理程序(除了妨碍,它使用信号不安全的函数可以破坏 python),并将第一个示例更改为如下内容:
import curses
from curses import wrapper
def main(stdscr):
inp = 0
y,x = stdscr.getmaxyx()
stdscr.clear()
stdscr.nodelay(1)
while inp != 48 and inp != 27:
while True:
try:
stdscr.addnstr(y-1,0, 'I AM KILL TERMINAL WHEN RESIZE AAAAAAAH', x)
except curses.error:
pass
inp = stdscr.getch()
if inp != curses.KEY_RESIZE:
break
stdscr.erase()
y,x = stdscr.getmaxyx()
wrapper(main)