Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
ansitowin32.py278 linesDownload Raw Back to colorama
1# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.2import re3import sys4import os5 6from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style, BEL7from .winterm import enable_vt_processing, WinTerm, WinColor, WinStyle8from .win32 import windll, winapi_test9 10 11winterm = None12if windll is not None:13    winterm = WinTerm()14 15 16class StreamWrapper(object):17    '''18    Wraps a stream (such as stdout), acting as a transparent proxy for all19    attribute access apart from method 'write()', which is delegated to our20    Converter instance.21    '''22    def __init__(self, wrapped, converter):23        # double-underscore everything to prevent clashes with names of24        # attributes on the wrapped stream object.25        self.__wrapped = wrapped26        self.__convertor = converter27 28    def __getattr__(self, name):29        return getattr(self.__wrapped, name)30 31    def __enter__(self, *args, **kwargs):32        # special method lookup bypasses __getattr__/__getattribute__, see33        # https://stackoverflow.com/questions/12632894/why-doesnt-getattr-work-with-exit34        # thus, contextlib magic methods are not proxied via __getattr__35        return self.__wrapped.__enter__(*args, **kwargs)36 37    def __exit__(self, *args, **kwargs):38        return self.__wrapped.__exit__(*args, **kwargs)39 40    def __setstate__(self, state):41        self.__dict__ = state42 43    def __getstate__(self):44        return self.__dict__45 46    def write(self, text):47        self.__convertor.write(text)48 49    def isatty(self):50        stream = self.__wrapped51        if 'PYCHARM_HOSTED' in os.environ:52            if stream is not None and (stream is sys.__stdout__ or stream is sys.__stderr__):53                return True54        try:55            stream_isatty = stream.isatty56        except AttributeError:57            return False58        else:59            return stream_isatty()60 61    @property62    def closed(self):63        stream = self.__wrapped64        try:65            return stream.closed66        # AttributeError in the case that the stream doesn't support being closed67        # ValueError for the case that the stream has already been detached when atexit runs68        except (AttributeError, ValueError):69            return True70 71 72class AnsiToWin32(object):73    '''74    Implements a 'write()' method which, on Windows, will strip ANSI character75    sequences from the text, and if outputting to a tty, will convert them into76    win32 function calls.77    '''78    ANSI_CSI_RE = re.compile('\001?\033\\[((?:\\d|;)*)([a-zA-Z])\002?')   # Control Sequence Introducer79    ANSI_OSC_RE = re.compile('\001?\033\\]([^\a]*)(\a)\002?')             # Operating System Command80 81    def __init__(self, wrapped, convert=None, strip=None, autoreset=False):82        # The wrapped stream (normally sys.stdout or sys.stderr)83        self.wrapped = wrapped84 85        # should we reset colors to defaults after every .write()86        self.autoreset = autoreset87 88        # create the proxy wrapping our output stream89        self.stream = StreamWrapper(wrapped, self)90 91        on_windows = os.name == 'nt'92        # We test if the WinAPI works, because even if we are on Windows93        # we may be using a terminal that doesn't support the WinAPI94        # (e.g. Cygwin Terminal). In this case it's up to the terminal95        # to support the ANSI codes.96        conversion_supported = on_windows and winapi_test()97        try:98            fd = wrapped.fileno()99        except Exception:100            fd = -1101        system_has_native_ansi = not on_windows or enable_vt_processing(fd)102        have_tty = not self.stream.closed and self.stream.isatty()103        need_conversion = conversion_supported and not system_has_native_ansi104 105        # should we strip ANSI sequences from our output?106        if strip is None:107            strip = need_conversion or not have_tty108        self.strip = strip109 110        # should we should convert ANSI sequences into win32 calls?111        if convert is None:112            convert = need_conversion and have_tty113        self.convert = convert114 115        # dict of ansi codes to win32 functions and parameters116        self.win32_calls = self.get_win32_calls()117 118        # are we wrapping stderr?119        self.on_stderr = self.wrapped is sys.stderr120 121    def should_wrap(self):122        '''123        True if this class is actually needed. If false, then the output124        stream will not be affected, nor will win32 calls be issued, so125        wrapping stdout is not actually required. This will generally be126        False on non-Windows platforms, unless optional functionality like127        autoreset has been requested using kwargs to init()128        '''129        return self.convert or self.strip or self.autoreset130 131    def get_win32_calls(self):132        if self.convert and winterm:133            return {134                AnsiStyle.RESET_ALL: (winterm.reset_all, ),135                AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT),136                AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL),137                AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL),138                AnsiFore.BLACK: (winterm.fore, WinColor.BLACK),139                AnsiFore.RED: (winterm.fore, WinColor.RED),140                AnsiFore.GREEN: (winterm.fore, WinColor.GREEN),141                AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW),142                AnsiFore.BLUE: (winterm.fore, WinColor.BLUE),143                AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA),144                AnsiFore.CYAN: (winterm.fore, WinColor.CYAN),145                AnsiFore.WHITE: (winterm.fore, WinColor.GREY),146                AnsiFore.RESET: (winterm.fore, ),147                AnsiFore.LIGHTBLACK_EX: (winterm.fore, WinColor.BLACK, True),148                AnsiFore.LIGHTRED_EX: (winterm.fore, WinColor.RED, True),149                AnsiFore.LIGHTGREEN_EX: (winterm.fore, WinColor.GREEN, True),150                AnsiFore.LIGHTYELLOW_EX: (winterm.fore, WinColor.YELLOW, True),151                AnsiFore.LIGHTBLUE_EX: (winterm.fore, WinColor.BLUE, True),152                AnsiFore.LIGHTMAGENTA_EX: (winterm.fore, WinColor.MAGENTA, True),153                AnsiFore.LIGHTCYAN_EX: (winterm.fore, WinColor.CYAN, True),154                AnsiFore.LIGHTWHITE_EX: (winterm.fore, WinColor.GREY, True),155                AnsiBack.BLACK: (winterm.back, WinColor.BLACK),156                AnsiBack.RED: (winterm.back, WinColor.RED),157                AnsiBack.GREEN: (winterm.back, WinColor.GREEN),158                AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW),159                AnsiBack.BLUE: (winterm.back, WinColor.BLUE),160                AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA),161                AnsiBack.CYAN: (winterm.back, WinColor.CYAN),162                AnsiBack.WHITE: (winterm.back, WinColor.GREY),163                AnsiBack.RESET: (winterm.back, ),164                AnsiBack.LIGHTBLACK_EX: (winterm.back, WinColor.BLACK, True),165                AnsiBack.LIGHTRED_EX: (winterm.back, WinColor.RED, True),166                AnsiBack.LIGHTGREEN_EX: (winterm.back, WinColor.GREEN, True),167                AnsiBack.LIGHTYELLOW_EX: (winterm.back, WinColor.YELLOW, True),168                AnsiBack.LIGHTBLUE_EX: (winterm.back, WinColor.BLUE, True),169                AnsiBack.LIGHTMAGENTA_EX: (winterm.back, WinColor.MAGENTA, True),170                AnsiBack.LIGHTCYAN_EX: (winterm.back, WinColor.CYAN, True),171                AnsiBack.LIGHTWHITE_EX: (winterm.back, WinColor.GREY, True),172            }173        return dict()174 175    def write(self, text):176        if self.strip or self.convert:177            self.write_and_convert(text)178        else:179            self.wrapped.write(text)180            self.wrapped.flush()181        if self.autoreset:182            self.reset_all()183 184 185    def reset_all(self):186        if self.convert:187            self.call_win32('m', (0,))188        elif not self.strip and not self.stream.closed:189            self.wrapped.write(Style.RESET_ALL)190 191 192    def write_and_convert(self, text):193        '''194        Write the given text to our wrapped stream, stripping any ANSI195        sequences from the text, and optionally converting them into win32196        calls.197        '''198        cursor = 0199        text = self.convert_osc(text)200        for match in self.ANSI_CSI_RE.finditer(text):201            start, end = match.span()202            self.write_plain_text(text, cursor, start)203            self.convert_ansi(*match.groups())204            cursor = end205        self.write_plain_text(text, cursor, len(text))206 207 208    def write_plain_text(self, text, start, end):209        if start < end:210            self.wrapped.write(text[start:end])211            self.wrapped.flush()212 213 214    def convert_ansi(self, paramstring, command):215        if self.convert:216            params = self.extract_params(command, paramstring)217            self.call_win32(command, params)218 219 220    def extract_params(self, command, paramstring):221        if command in 'Hf':222            params = tuple(int(p) if len(p) != 0 else 1 for p in paramstring.split(';'))223            while len(params) < 2:224                # defaults:225                params = params + (1,)226        else:227            params = tuple(int(p) for p in paramstring.split(';') if len(p) != 0)228            if len(params) == 0:229                # defaults:230                if command in 'JKm':231                    params = (0,)232                elif command in 'ABCD':233                    params = (1,)234 235        return params236 237 238    def call_win32(self, command, params):239        if command == 'm':240            for param in params:241                if param in self.win32_calls:242                    func_args = self.win32_calls[param]243                    func = func_args[0]244                    args = func_args[1:]245                    kwargs = dict(on_stderr=self.on_stderr)246                    func(*args, **kwargs)247        elif command in 'J':248            winterm.erase_screen(params[0], on_stderr=self.on_stderr)249        elif command in 'K':250            winterm.erase_line(params[0], on_stderr=self.on_stderr)251        elif command in 'Hf':     # cursor position - absolute252            winterm.set_cursor_position(params, on_stderr=self.on_stderr)253        elif command in 'ABCD':   # cursor position - relative254            n = params[0]255            # A - up, B - down, C - forward, D - back256            x, y = {'A': (0, -n), 'B': (0, n), 'C': (n, 0), 'D': (-n, 0)}[command]257            winterm.cursor_adjust(x, y, on_stderr=self.on_stderr)258 259 260    def convert_osc(self, text):261        for match in self.ANSI_OSC_RE.finditer(text):262            start, end = match.span()263            text = text[:start] + text[end:]264            paramstring, command = match.groups()265            if command == BEL:266                if paramstring.count(";") == 1:267                    params = paramstring.split(";")268                    # 0 - change title and icon (we will only change title)269                    # 1 - change icon (we don't support this)270                    # 2 - change title271                    if params[0] in '02':272                        winterm.set_title(params[1])273        return text274 275 276    def flush(self):277        self.wrapped.flush()278 
codekingpro/portable-devtools · Team Ai