Repository: mesonbuild/meson

Issue:
meson color output is broken with conemu (windows)
I currently use conemu with the quake-style dropdown menu, and while trying to run meson under windows, I get the following output

![screenshot 2018-04-29 00 34 23](https://user-images.githubusercontent.com/63051/39404269-0f519e72-4b45-11e8-9d15-b71667951b0f.png)

I think that on windows, it might be best to use the [colorama](https://pypi.org/project/colorama/) library as a conditional dependency on windows. This can be done inside of the `setup.py` with the `install_requires` looking like:

```python
install_requires =
  colorama;sys_platform == 'win32'
```

Alternatively, simply importing colorama causes it to "do the right thing" on non-windows platforms. This also means you can get color support for pre-Windows 10 versions (Windows 10 added VT100 escape sequence support, but it requires an explicit opt in via a win32 function call)

I'm unsure if either of these options are valid, or even wanted.
meson color output is broken with conemu (windows)
I currently use conemu with the quake-style dropdown menu, and while trying to run meson under windows, I get the following output

![screenshot 2018-04-29 00 34 23](https://user-images.githubusercontent.com/63051/39404269-0f519e72-4b45-11e8-9d15-b71667951b0f.png)

I think that on windows, it might be best to use the [colorama](https://pypi.org/project/colorama/) library as a conditional dependency on windows. This can be done inside of the `setup.py` with the `install_requires` looking like:

```python
install_requires =
  colorama;sys_platform == 'win32'
```

Alternatively, simply importing colorama causes it to "do the right thing" on non-windows platforms. This also means you can get color support for pre-Windows 10 versions (Windows 10 added VT100 escape sequence support, but it requires an explicit opt in via a win32 function call)

I'm unsure if either of these options are valid, or even wanted.


Discussion:
Meson has a coding requirement that are not allowed to depend on any library that is outside the standard library. Thus using colorama or something like it is sadly not possible.

However we disable color on Windows exactly because of this. The exact code snippet is this one (in `mlog.py`):

```python
if platform.system().lower() == 'windows':
    colorize_console = os.isatty(sys.stdout.fileno()) and os.environ.get('ANSICON')
else:
    colorize_console = os.isatty(sys.stdout.fileno()) and os.environ.get('TERM') != 'dumb'
```

Is `ANSICON` set in your environment? 
> Is ANSICON set in your environment?

It seems as though ConEmu does set this by default.

Since you won't use anything outside the python stdlib, some ctypes specific calls could be made to permit colors of VT100 escape sequences on windows 10. Code for previous versions should continue to follow the current approach.
> It seems as though ConEmu does set this by default.

Then this particular issue would seem to be a bug in ConEmu. It is explicitly setting `ANSICON` on a terminal that does not support ANSI colors. It should not do that. There's not much we can do when run with broken settings.

> some ctypes specific calls could be made to permit colors of VT100 escape sequences on windows 10

We could definitely do that (even using the win32 module that ships with Python if it has the necessary bits). I don't know enough about Windows to get this done, but patches are welcome.
ConEmu seems to have a setting to automatically parse VT100 escape sequences into Win32 color commands for sub-Windows 10 systems, but it seems to be disabled on Windows 10 (I haven't gotten it to work)

> We could definitely do that (even using the win32 module that ships with Python if it has the necessary bits). I don't know enough about Windows to get this done, but patches are welcome.

I'll see if I can knock this out. Apparently, enabling it is quite simple from ctypes.



Meson has a coding requirement that are not allowed to depend on any library that is outside the standard library. Thus using colorama or something like it is sadly not possible.

However we disable color on Windows exactly because of this. The exact code snippet is this one (in `mlog.py`):

```python
if platform.system().lower() == 'windows':
    colorize_console = os.isatty(sys.stdout.fileno()) and os.environ.get('ANSICON')
else:
    colorize_console = os.isatty(sys.stdout.fileno()) and os.environ.get('TERM') != 'dumb'
```

Is `ANSICON` set in your environment? 
> Is ANSICON set in your environment?

It seems as though ConEmu does set this by default.

Since you won't use anything outside the python stdlib, some ctypes specific calls could be made to permit colors of VT100 escape sequences on windows 10. Code for previous versions should continue to follow the current approach.
> It seems as though ConEmu does set this by default.

Then this particular issue would seem to be a bug in ConEmu. It is explicitly setting `ANSICON` on a terminal that does not support ANSI colors. It should not do that. There's not much we can do when run with broken settings.

> some ctypes specific calls could be made to permit colors of VT100 escape sequences on windows 10

We could definitely do that (even using the win32 module that ships with Python if it has the necessary bits). I don't know enough about Windows to get this done, but patches are welcome.
ConEmu seems to have a setting to automatically parse VT100 escape sequences into Win32 color commands for sub-Windows 10 systems, but it seems to be disabled on Windows 10 (I haven't gotten it to work)

> We could definitely do that (even using the win32 module that ships with Python if it has the necessary bits). I don't know enough about Windows to get this done, but patches are welcome.

I'll see if I can knock this out. Apparently, enabling it is quite simple from ctypes.




Resolving patch:
diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py
--- a/mesonbuild/mlog.py
+++ b/mesonbuild/mlog.py
@@ -19,8 +19,22 @@
 information about Meson runs. Some output goes to screen,
 some to logging dir and some goes to both."""
 
+def _windows_ansi():
+    from ctypes import windll, byref
+    from ctypes.wintypes import DWORD
+
+    kernel = windll.kernel32
+    stdout = kernel.GetStdHandle(-11)
+    mode = DWORD()
+    if not kernel.GetConsoleMode(stdout, byref(mode)):
+        return False
+    # ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0x4
+    # If the call to enable VT processing fails (returns 0), we fallback to
+    # original behavior
+    return kernel.SetConsoleMode(stdout, mode.value | 0x4) or os.environ.get('ANSICON')
+
 if platform.system().lower() == 'windows':
-    colorize_console = os.isatty(sys.stdout.fileno()) and os.environ.get('ANSICON')
+    colorize_console = os.isatty(sys.stdout.fileno()) and _windows_ansi()
 else:
     colorize_console = os.isatty(sys.stdout.fileno()) and os.environ.get('TERM') != 'dumb'
 log_dir = None


Test patch: