Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/usr/bin/env python | |
| 2 # Copyright (c) 2016 The Chromium Authors. All rights reserved. | |
| 3 # Use of this source code is governed by a BSD-style license that can be | |
| 4 # found in the LICENSE file. | |
| 5 | |
| 6 import os | |
| 7 import sys | |
| 8 from third_party import colorama | |
| 9 | |
| 10 IS_TTY = None | |
| 11 OUT_TYPE = 'unknown' | |
| 12 | |
| 13 def init(): | |
| 14 should_wrap = True | |
|
dnj
2016/04/03 00:57:45
I feel like this should start False and turn True
iannucci
2016/04/04 20:24:59
done
| |
| 15 global IS_TTY, OUT_TYPE | |
| 16 IS_TTY = sys.stdout.isatty() | |
| 17 if IS_TTY: | |
| 18 # Yay! We detected a console in the normal way. It doesn't really matter | |
| 19 # if it's windows or not, we win. | |
| 20 OUT_TYPE = 'console' | |
| 21 elif sys.platform.startswith('win'): | |
| 22 # assume this is some sort of file | |
| 23 OUT_TYPE = 'file (win)' | |
| 24 # On windows, things are a bit more nuanced. We start by assuming that it's | |
| 25 # a pipe. | |
| 26 | |
| 27 import msvcrt | |
| 28 import ctypes | |
| 29 h = msvcrt.get_osfhandle(sys.stdout.fileno()) | |
| 30 # h is the win32 HANDLE for stdout. | |
| 31 ftype = ctypes.windll.kernel32.GetFileType(h) | |
| 32 if ftype == 2: # FILE_TYPE_CHAR | |
| 33 # This is a normal cmd console, but we'll only get here if we're running | |
| 34 # inside a `git command` which is actually git->bash->command. Not sure | |
| 35 # why isatty doesn't detect this case. This case still needs to be wrapped | |
| 36 # on windows though, because it needs to use SetConsoleTextAttribute to | |
| 37 # do actual color manipulation. | |
| 38 OUT_TYPE = 'console (cmd via msys)' | |
| 39 IS_TTY = True | |
| 40 elif ftype == 3: # FILE_TYPE_PIPE | |
| 41 OUT_TYPE = 'pipe (win)' | |
| 42 # This is some kind of pipe on windows. This could either be a real pipe | |
| 43 # or this could be msys using a pipe to emulate a pty. We use the same | |
| 44 # algorithm that msys-git uses to determine if it's connected to a pty or | |
| 45 # not. | |
| 46 | |
| 47 # We don't want to wrap since it's either a real pipe, or an msys pty. | |
| 48 # Either way it doesn't need SetConsoleTextAttribute. | |
| 49 should_wrap = False | |
| 50 | |
| 51 # This function and the structures are defined in the MSDN documentation | |
| 52 # using the same names. | |
| 53 def NT_SUCCESS(status): | |
| 54 if status >= 0 and status <= 0x3FFFFFFF: | |
|
dnj
2016/04/03 00:57:45
Windows success and information types are contiguo
iannucci
2016/04/04 20:24:59
yeah changed and added comment.
| |
| 55 return True | |
| 56 if status >= 0x40000000 and status <= 0x7FFFFFFF: | |
| 57 return True | |
| 58 return False | |
| 59 | |
| 60 class UNICODE_STRING(ctypes.Structure): | |
| 61 _fields_ = [('Length', ctypes.c_ushort), | |
| 62 ('MaximumLength', ctypes.c_ushort), | |
| 63 ('Buffer', ctypes.c_wchar_p)] | |
| 64 | |
| 65 class OBJECT_NAME_INFORMATION(ctypes.Structure): | |
| 66 _fields_ = [('Name', UNICODE_STRING), | |
| 67 ('NameBuffer', ctypes.c_wchar_p)] | |
| 68 | |
| 69 buf = ctypes.create_string_buffer('\0', 1024) | |
| 70 # Ask NT what the name of the object our stdout HANDLE is. It would be | |
| 71 # possible to use GetFileInformationByHandleEx, but it's only available | |
| 72 # on Vista+. If you're reading this in 2017 or later, feel free to | |
| 73 # refactor this out. | |
| 74 # | |
| 75 # The '1' here is ObjectNameInformation | |
| 76 if NT_SUCCESS(ctypes.windll.ntdll.NtQueryObject(h, 1, buf, len(buf)-2, | |
| 77 None)): | |
| 78 # MSYS console, but not an MSYS pipe | |
| 79 out = OBJECT_NAME_INFORMATION.from_buffer(buf) | |
| 80 name = out.Name.Buffer.split('\\')[-1] | |
| 81 IS_TTY = name.startswith('msys-') and '-pty' in name | |
| 82 if IS_TTY: | |
| 83 OUT_TYPE = 'console (msys)' | |
| 84 else: | |
| 85 # A normal file, or an unknown file type. | |
| 86 should_wrap = False | |
| 87 else: | |
| 88 # This is non-windows, so we trust isatty. | |
| 89 OUT_TYPE = 'pipe|file' | |
| 90 | |
| 91 colorama.init(wrap=should_wrap) | |
| 92 | |
| 93 if __name__ == '__main__': | |
| 94 init() | |
| 95 print 'IS_TTY:', IS_TTY | |
| 96 print 'OUT_TYPE:', OUT_TYPE | |
| OLD | NEW |