You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			132 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Python
		
	
			
		
		
	
	
			132 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Python
		
	
#!/usr/bin/env python3
 | 
						|
# Copyright (c) 2016 The Chromium Authors. All rights reserved.
 | 
						|
# Use of this source code is governed by a BSD-style license that can be
 | 
						|
# found in the LICENSE file.
 | 
						|
 | 
						|
from __future__ import print_function
 | 
						|
 | 
						|
import ctypes
 | 
						|
import os
 | 
						|
import platform
 | 
						|
import subprocess
 | 
						|
import sys
 | 
						|
from third_party import colorama
 | 
						|
 | 
						|
IS_TTY = None
 | 
						|
OUT_TYPE = 'unknown'
 | 
						|
 | 
						|
 | 
						|
def enable_native_ansi():
 | 
						|
  """Enables native ANSI sequences in console. Windows 10 only.
 | 
						|
 | 
						|
  Returns whether successful.
 | 
						|
  """
 | 
						|
  kernel32 = ctypes.windll.kernel32
 | 
						|
  ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x04
 | 
						|
 | 
						|
  out_handle = kernel32.GetStdHandle(subprocess.STD_OUTPUT_HANDLE)
 | 
						|
 | 
						|
  # GetConsoleMode fails if the terminal isn't native.
 | 
						|
  mode = ctypes.wintypes.DWORD()
 | 
						|
  if kernel32.GetConsoleMode(out_handle, ctypes.byref(mode)) == 0:
 | 
						|
    return False
 | 
						|
 | 
						|
  if not (mode.value & ENABLE_VIRTUAL_TERMINAL_PROCESSING):
 | 
						|
    if kernel32.SetConsoleMode(
 | 
						|
        out_handle, mode.value | ENABLE_VIRTUAL_TERMINAL_PROCESSING) == 0:
 | 
						|
      print(
 | 
						|
          'kernel32.SetConsoleMode to enable ANSI sequences failed',
 | 
						|
          file=sys.stderr)
 | 
						|
      return False
 | 
						|
 | 
						|
  return True
 | 
						|
 | 
						|
 | 
						|
def init():
 | 
						|
  # should_wrap instructs colorama to wrap stdout/stderr with an ANSI colorcode
 | 
						|
  # interpreter that converts them to SetConsoleTextAttribute calls. This only
 | 
						|
  # should be True in cases where we're connected to cmd.exe's console. Setting
 | 
						|
  # this to True on non-windows systems has no effect.
 | 
						|
  should_wrap = False
 | 
						|
  global IS_TTY, OUT_TYPE
 | 
						|
  IS_TTY = sys.stdout.isatty()
 | 
						|
  is_windows = sys.platform.startswith('win')
 | 
						|
  if IS_TTY:
 | 
						|
    # Yay! We detected a console in the normal way. It doesn't really matter
 | 
						|
    # if it's windows or not, we win.
 | 
						|
    OUT_TYPE = 'console'
 | 
						|
    should_wrap = True
 | 
						|
  elif is_windows:
 | 
						|
    # assume this is some sort of file
 | 
						|
    OUT_TYPE = 'file (win)'
 | 
						|
 | 
						|
    import msvcrt
 | 
						|
    h = msvcrt.get_osfhandle(sys.stdout.fileno())
 | 
						|
    # h is the win32 HANDLE for stdout.
 | 
						|
    ftype = ctypes.windll.kernel32.GetFileType(h)
 | 
						|
    if ftype == 2: # FILE_TYPE_CHAR
 | 
						|
      # This is a normal cmd console, but we'll only get here if we're running
 | 
						|
      # inside a `git command` which is actually git->bash->command. Not sure
 | 
						|
      # why isatty doesn't detect this case.
 | 
						|
      OUT_TYPE = 'console (cmd via msys)'
 | 
						|
      IS_TTY = True
 | 
						|
      should_wrap = True
 | 
						|
    elif ftype == 3: # FILE_TYPE_PIPE
 | 
						|
      OUT_TYPE = 'pipe (win)'
 | 
						|
      # This is some kind of pipe on windows. This could either be a real pipe
 | 
						|
      # or this could be msys using a pipe to emulate a pty. We use the same
 | 
						|
      # algorithm that msys-git uses to determine if it's connected to a pty or
 | 
						|
      # not.
 | 
						|
 | 
						|
      # This function and the structures are defined in the MSDN documentation
 | 
						|
      # using the same names.
 | 
						|
      def NT_SUCCESS(status):
 | 
						|
        # The first two bits of status are the severity. The success
 | 
						|
        # severities are 0 and 1, and the !success severities are 2 and 3.
 | 
						|
        # Therefore since ctypes interprets the default restype of the call
 | 
						|
        # to be an 'C int' (which is guaranteed to be signed 32 bits), All
 | 
						|
        # success codes are positive, and all !success codes are negative.
 | 
						|
        return status >= 0
 | 
						|
 | 
						|
      class UNICODE_STRING(ctypes.Structure):
 | 
						|
        _fields_ = [('Length', ctypes.c_ushort),
 | 
						|
                    ('MaximumLength', ctypes.c_ushort),
 | 
						|
                    ('Buffer', ctypes.c_wchar_p)]
 | 
						|
 | 
						|
      class OBJECT_NAME_INFORMATION(ctypes.Structure):
 | 
						|
        _fields_ = [('Name', UNICODE_STRING),
 | 
						|
                    ('NameBuffer', ctypes.c_wchar_p)]
 | 
						|
 | 
						|
      buf = ctypes.create_string_buffer(1024)
 | 
						|
      # Ask NT what the name of the object our stdout HANDLE is. It would be
 | 
						|
      # possible to use GetFileInformationByHandleEx, but it's only available
 | 
						|
      # on Vista+. If you're reading this in 2017 or later, feel free to
 | 
						|
      # refactor this out.
 | 
						|
      #
 | 
						|
      # The '1' here is ObjectNameInformation
 | 
						|
      if NT_SUCCESS(ctypes.windll.ntdll.NtQueryObject(h, 1, buf, len(buf)-2,
 | 
						|
                    None)):
 | 
						|
        out = OBJECT_NAME_INFORMATION.from_buffer(buf)
 | 
						|
        name = out.Name.Buffer.split('\\')[-1]
 | 
						|
        IS_TTY = name.startswith('msys-') and '-pty' in name
 | 
						|
        if IS_TTY:
 | 
						|
          OUT_TYPE = 'bash (msys)'
 | 
						|
    else:
 | 
						|
      # A normal file, or an unknown file type.
 | 
						|
      pass
 | 
						|
  else:
 | 
						|
    # This is non-windows, so we trust isatty.
 | 
						|
    OUT_TYPE = 'pipe or file'
 | 
						|
 | 
						|
  if IS_TTY and is_windows:
 | 
						|
    # Wrapping may cause errors on some Windows versions (crbug.com/1114548).
 | 
						|
    if platform.release() != '10' or enable_native_ansi():
 | 
						|
      should_wrap = False
 | 
						|
 | 
						|
  colorama.init(wrap=should_wrap)
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
  init()
 | 
						|
  print('IS_TTY:', IS_TTY)
 | 
						|
  print('OUT_TYPE:', OUT_TYPE)
 |