On 12/22/20, Barry Scott <ba...@barrys-emacs.org> wrote:
>
> import sys
>
> def clear_terminal():
>     if sys.platform == 'win32':
>         import ctypes
>         kernel32 = ctypes.windll.kernel32
>         # turn on the console ANSI colour handling
>         kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
>
>     sys.stdout.write('\x1b[2J' '\x1b[H')

Here are some concerns I have:

* Does not support Windows 8
* Does not support legacy console in Windows 10 (on the "options" tab)
* Does not check for SetConsoleMode failure
* Does not support a different active screen buffer
* Assumes StandardOutput is a screen buffer for the current console
* Assumes the current mode of the screen buffer is 3 or 7. New modes
have been added, and even more may be added
* Sets a global console setting that persists after Python exits

Like the CRT's "conio" API, clear_screen() should open "conout$"
(temporarily), which will succeed if Python is attached to a console,
regardless of the state of the standard handles, file descriptors, or
sys.stdout, and will always open the currently active screen buffer,
regardless of how many screen buffers exist in the current console
session.

The current mode should be queried for
ENABLE_VIRTUAL_TERMINAL_PROCESSING (4) via GetConsoleMode(). If it's
not enabled, bitwise OR it into the mode and try to enable it via
SetConsoleMode(). If VT mode is enabled, write '\x1b[2J\x1b[H' to the
file.

If VT mode can't be enabled, then fall back on the legacy console API.
In particular, some people mentioned not wanting to spawn a cmd.exe
process just to use its CLS command. Even if spawning a process is
okay, the CLS command clears the scrollback, which is inconsistent
with ESC[2J. If clear_screen() is going to add ESC[3J to clear the
scrollback, then it's at least consistent, but I'd rather not clear
the scrollback.

clear_screen() should be able to emulate ESC[2J via
GetConsoleScreenBufferInfoEx (get the screen buffer size, window,
cursor position, and default character attributes),
ScrollConsoleScreenBuffer (if the screen buffer has to be scrolled up
to make space), and SetConsoleScreenBufferInfoEx (shift the visible
window in the buffer and set the cursor position). This can be
implemented in ctypes or C. But normally the standard library avoids
using ctypes.

Finally, if VT mode was temporarily enabled, revert to the original
mode, and always close the "conout$" file.

Off topic comment:

>         kernel32 = ctypes.windll.kernel32

I recommend the following instead:

    kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)

The global library loaders such as ctypes.cdll and ctypes.windll are
not reliable for production code in the wild. They cache CDLL library
instances, which cache function pointers, which may have argtypes,
restype, and errcheck prototypes. Another imported package might set
function prototypes that break your code, which is an actual problem
that I've seen a few times, particularly with common routines from
kernel32, advapi32, and user32. It's not worth taking the chance of a
conflict with another package just to save a few keystrokes.

The global loaders also don't allow setting use_errno=True or
use_last_error=True, so the function pointers they create don't
capture the C errno value for ctypes.get_errno() or Windows last error
value for ctypes.get_last_error(). Calling kernel32.GetLastError()
after the fact may not be reliable in a scripting environment even if
it's called directly after the previous FFI call.
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/AHDEAUNZNUT6EWT7GTEGSKKFL3GABZ4W/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to