我正在尝试实现一个clear_terminal()函数,它只清除给定数量的行,而不是整个屏幕。
在unix终端中,这可以通过以下ansi转义序列解决:
\033[{rows}A \033[0J
使用Windows API函数可以重现完全相同的结果:
hConsoleOutput = ctypes.windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
lpConsoleScreenBufferInfo = CONSOLE_SCREEN_BUFFER_INFO()
ctypes.windll.kernel32.GetConsoleScreenBufferInfo(
hConsoleOutput,
ctypes.byref(lpConsoleScreenBufferInfo)
)
lpConsoleScreenBufferInfo.dwCursorPosition.Y -= rows
ctypes.windll.kernel32.SetConsoleCursorPosition(
hConsoleOutput,
lpConsoleScreenBufferInfo.dwCursorPosition
)
ctypes.windll.kernel32.FillConsoleOutputCharacterA(
hConsoleOutput,
ctypes.c_char(b' '),
lpConsoleScreenBufferInfo.dwSize.X * rows,
lpConsoleScreenBufferInfo.dwCursorPosition,
ctypes.byref(wintypes.DWORD(0))
)
ctypes.windll.kernel32.FillConsoleOutputAttribute(
hConsoleOutput,
lpConsoleScreenBufferInfo.wAttributes,
lpConsoleScreenBufferInfo.dwSize.X * rows,
lpConsoleScreenBufferInfo.dwCursorPosition,
ctypes.byref(wintypes.DWORD(0))
)
但这正如微软所说的遗留问题。因为从Windows 10 TH2(v1511)开始,cmd.exe支持ANSI转义序列。它们必须使用SetConsoleMode ENABLE_VIRTUAL_TERMINAL_PROCESSING标志启用。
启用此选项会显示转义码无法正常工作:仅清除固定数量的行。文档中说明了此原因:
光标的移动将被当前 windows 限制在缓冲区内。滚动(如果可用)将不会发生。
所以使用虚拟序列时,不可能将光标位置设置得高于可视区域的上限。有没有解决办法来消除这种不必要的视口限制?
我使用了与上面相同的转义序列。Windows API解决方案总是清理正确的行数,并且不会遇到这些限制。
1条答案
按热度按时间qco9c6ql1#
没有真实的的区别:您使用的转义序列仅限于可见屏幕。根据引用的文档,Windows控制台不实现擦除滚动区:
对于以下命令,参数有3个有效值:
与xterm相比:
(Windows终端不同,但完全没有文档记录)。