Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use the new support for ANSI escape sequences in the Windows 10 console?

The latest Windows 10 updates include support for ANSI escape sequences in conhost.exe.

enter image description here

I have been able to confirm that the escape sequences are properly picked up in cmd.exe, so I have the necessary updates. In particular, I tried typing in prompt $e[?25l, which hides the cursor, and then prompt $e[?25h, which again shows the cursor.

However, if I start a Python interpreter, and then do the following:

>>> import sys
>>> sys.stdout.write("\033[?25l")

Well, the cursor isn't hidden. How can I set things up the right way so that the console is able to get escape sequences from Python?

like image 871
bzm3r Avatar asked Apr 21 '16 05:04

bzm3r


People also ask

Does Windows support ANSI escape sequences?

ANSI. SYS also works in NT-derived systems for 16-bit legacy programs executing under the NTVDM. The Win32 console does not natively support ANSI escape sequences at all.

Does Windows terminal support ANSI?

How-to: Use ANSI colors in the terminal. ANSI colors are available by default in Windows version 1909 or newer.

Do ANSI escape codes work in PowerShell?

PowerShell has many features that support the use of ANSI escape sequences to control the rendering of output in the terminal application that is hosting PowerShell. PowerShell 7.2 added a new automatic variable, $PSStyle , and changes to the PowerShell engine to support the output of ANSI-decorated text.

How can I remove the ANSI escape sequences from a string in Python?

You can use regexes to remove the ANSI escape sequences from a string in Python. Simply substitute the escape sequences with an empty string using re. sub(). The regex you can use for removing ANSI escape sequences is: '(\x9B|\x1B\[)[0-?]


2 Answers

The problem is that the Python interpreter doesn't enable the processing of ANSI escape sequences. The ANSI sequences work from the Windows command prompt because cmd does enable them. If you start Python from the command prompt you'll find the ANSI sequences do work, including the ones for enabling and disabling the cursor. That's because cmd has already enabled them for that console window.

If you want have something you can click on to start the Python interpreter with ANSI escapes enabled you can create a shortcut that runs a command something like cmd /c C:\PythonXY\python.

Another, harder, solution would be to use ctypes to enable ANSI escape sequence processing for the console window by calling the SetConsoleMode Windows API with the ENABLE_VIRTUAL_TERMINAL_PROCESSING flag set. For example:

import ctypes  kernel32 = ctypes.windll.kernel32 kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7) 
like image 191
Ross Ridge Avatar answered Oct 21 '22 02:10

Ross Ridge


This adaptation of some code I proposed here should help get you started. Enables ANSI VT mode (virtual terminal processing) on Windows 10. Pass in argument value 1 for stdout or 2 stderr.

def _windows_enable_ANSI(std_id):
    """Enable Windows 10 cmd.exe ANSI VT Virtual Terminal Processing."""
    from ctypes import byref, POINTER, windll, WINFUNCTYPE
    from ctypes.wintypes import BOOL, DWORD, HANDLE

    GetStdHandle = WINFUNCTYPE(
        HANDLE,
        DWORD)(('GetStdHandle', windll.kernel32))

    GetFileType = WINFUNCTYPE(
        DWORD,
        HANDLE)(('GetFileType', windll.kernel32))

    GetConsoleMode = WINFUNCTYPE(
        BOOL,
        HANDLE,
        POINTER(DWORD))(('GetConsoleMode', windll.kernel32))

    SetConsoleMode = WINFUNCTYPE(
        BOOL,
        HANDLE,
        DWORD)(('SetConsoleMode', windll.kernel32))

    if std_id == 1:       # stdout
        h = GetStdHandle(-11)
    elif std_id == 2:     # stderr
        h = GetStdHandle(-12)
    else:
        return False

    if h is None or h == HANDLE(-1):
        return False

    FILE_TYPE_CHAR = 0x0002
    if (GetFileType(h) & 3) != FILE_TYPE_CHAR:
        return False

    mode = DWORD()
    if not GetConsoleMode(h, byref(mode)):
        return False

    ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
    if (mode.value & ENABLE_VIRTUAL_TERMINAL_PROCESSING) == 0:
        SetConsoleMode(h, mode.value | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
    return True
like image 32
Glenn Slayden Avatar answered Oct 21 '22 02:10

Glenn Slayden