From c9eb8c85a9127c0699726795ee459cd40d343c1c Mon Sep 17 00:00:00 2001 From: Zhiming Wang Date: Wed, 10 Apr 2019 18:53:07 +0800 Subject: [PATCH 1/2] Introduce smarter coloring and --colorize option By default, do not colorize when stdout is not a tty. The --colorize option, with possible values 'auto', 'always', and 'never' -- defaults to 'auto' when not specified, and registers as 'always' when specified without a value -- is similar to the --color option found in many well known *nix tools, with coreutils ls(1) being a notable example. (Our option is named --colorize since we already have a --colors option.) The old -C, --nocolor option is now a shortcut for --colorize=never. Limitation: due to limitations of Python argparse, specifically not being able to make the equal sign between a long option and its value mandatory, one might expect the following to work: googler --colorize google but it does not, due to "google" being parsed as an argument to --colorize. One has to write googler --colorize -- google instead. --- googler | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/googler b/googler index 67ea8b1..6837536 100755 --- a/googler +++ b/googler @@ -3126,8 +3126,13 @@ def parse_args(args=None, namespace=None): addarg('-l', '--lang', metavar='LANG', help='display in language LANG') addarg('-x', '--exact', action='store_true', help='disable automatic spelling correction') - addarg('-C', '--nocolor', dest='colorize', action='store_false', - help='disable color output') + addarg('--colorize', nargs='?', choices=['auto', 'always', 'never'], + const='always', default='auto', + help="""whether to colorize output; defaults to 'auto', which enables + color when stdout is a tty device; using --colorize without an argument + is equivalent to --colorize=always""") + addarg('-C', '--nocolor', action='store_true', + help='equivalent to --colorize=never') addarg('--colors', dest='colorstr', type=argparser.is_colorstr, default=colorstr_env if colorstr_env else 'GKlgxy', metavar='COLORS', help='set output colors (see man page for details)') @@ -3165,7 +3170,11 @@ def parse_args(args=None, namespace=None): addarg('-D', '--debugger', action='store_true', help=argparse.SUPPRESS) addarg('--complete', help=argparse.SUPPRESS) - return argparser.parse_args(args, namespace) + parsed = argparser.parse_args(args, namespace) + if parsed.nocolor: + parsed.colorize = 'never' + + return parsed def main(): @@ -3203,7 +3212,16 @@ def main(): pass # Set colors - if opts.colorize: + if opts.colorize == 'always': + colorize = True + elif opts.colorize == 'auto': + colorize = sys.stdout.isatty() + elif opts.colorize == 'never': + colorize = False + else: + raise ValueError("invalid --colorize value '%s'" % opts.colorize) + + if colorize: colors = Colors(*[COLORMAP[c] for c in opts.colorstr], reset=COLORMAP['x']) else: colors = None From d2b579fddcbe8db083d6c6868f22170226e336bc Mon Sep 17 00:00:00 2001 From: Zhiming Wang Date: Wed, 10 Apr 2019 19:59:25 +0800 Subject: [PATCH 2/2] Enable ANSI color in cmd and PowerShell on Windows 10 VT100 control sequences are supported in cmd and PowerShell starting from Windows 10 Anniversary Update, but only if the ENABLE_VIRTUAL_TERMINAL_PROCESSING flag is set on the screen buffer handle using SetConsoleMode. Setting this flag does not seem to negatively affect third party terminal emulators with native ANSI support such as ConEmu, so hopefully there's no regression. References: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences https://docs.microsoft.com/en-us/windows/console/setconsolemode Credits: https://github.com/jarun/googler/pull/275 https://github.com/tartley/colorama/pull/139 --- googler | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/googler b/googler index 6837536..c21fa67 100755 --- a/googler +++ b/googler @@ -30,6 +30,7 @@ from http.client import HTTPSConnection import locale import logging import os +import platform import shutil import signal import socket @@ -3229,6 +3230,29 @@ def main(): Result.urlexpand = True if os.getenv('DISABLE_URL_EXPANSION') is None else False GooglerCmd.colors = colors + # Try to enable ANSI color support in cmd or PowerShell on Windows 10 + if sys.platform == 'win32' and sys.stdout.isatty() and colorize: + # VT100 control sequences are supported on Windows 10 Anniversary Update and later. + # https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences + # https://docs.microsoft.com/en-us/windows/console/setconsolemode + if platform.release() == '10': + STD_OUTPUT_HANDLE = -11 + ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004 + try: + from ctypes import windll, wintypes, byref + kernel32 = windll.kernel32 + stdout_handle = kernel32.GetStdHandle(STD_OUTPUT_HANDLE) + old_mode = wintypes.DWORD() + if not kernel32.GetConsoleMode(stdout_handle, byref(old_mode)): + raise RuntimeError('GetConsoleMode failed') + new_mode = old_mode.value | ENABLE_VIRTUAL_TERMINAL_PROCESSING + if not kernel32.SetConsoleMode(stdout_handle, new_mode): + raise RuntimeError('SetConsoleMode failed') + # Note: No need to restore at exit. SetConsoleMode seems to + # be limited to the calling process. + except Exception: + pass + if opts.url_handler is not None: open_url.url_handler = opts.url_handler else: