[llvm] [lit] cross platform progress bar (PR #189970)
Charles Zablit via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 2 08:02:52 PDT 2026
https://github.com/charles-zablit updated https://github.com/llvm/llvm-project/pull/189970
>From 29e4522b99cfb6b472fa1780fdcafa1be87391b2 Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Thu, 2 Apr 2026 16:02:36 +0100
Subject: [PATCH] [lit][windows] implement progress bar on Windows
---
llvm/utils/lit/lit/ProgressBar.py | 106 +++++++++++++++++++++++-------
1 file changed, 83 insertions(+), 23 deletions(-)
diff --git a/llvm/utils/lit/lit/ProgressBar.py b/llvm/utils/lit/lit/ProgressBar.py
index 382b8f2e52540..dadbe6522ed19 100644
--- a/llvm/utils/lit/lit/ProgressBar.py
+++ b/llvm/utils/lit/lit/ProgressBar.py
@@ -3,7 +3,10 @@
# Source: http://code.activestate.com/recipes/475116/, with
# modifications by Daniel Dunbar.
-import sys, re, time
+import os
+import re
+import sys
+import time
def to_bytes(str):
@@ -81,23 +84,40 @@ class TerminalController:
BG_BLACK = BG_BLUE = BG_GREEN = BG_CYAN = ""
BG_RED = BG_MAGENTA = BG_YELLOW = BG_WHITE = ""
+ _ANSICOLORS = "BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE".split()
+
+ def __new__(cls, term_stream=sys.stdout):
+ if cls is TerminalController:
+ if sys.platform == "win32":
+ return super().__new__(_WindowsTerminalController)
+ return super().__new__(_PosixTerminalController)
+ return super().__new__(cls)
+
+ def render(self, template):
+ """
+ Replace each $-substitutions in the given template string with
+ the corresponding terminal control string (if it's defined) or
+ '' (if it's not).
+ """
+ return re.sub(r"\$\$|\${\w+}", self._render_sub, template)
+
+ def _render_sub(self, match):
+ s = match.group()
+ if s == "$$":
+ return s
+ else:
+ return getattr(self, s[2:-1])
+
+
+class _PosixTerminalController(TerminalController):
_STRING_CAPABILITIES = """
BOL=cr UP=cuu1 DOWN=cud1 LEFT=cub1 RIGHT=cuf1
CLEAR_SCREEN=clear CLEAR_EOL=el CLEAR_BOL=el1 CLEAR_EOS=ed BOLD=bold
BLINK=blink DIM=dim REVERSE=rev UNDERLINE=smul NORMAL=sgr0
HIDE_CURSOR=cinvis SHOW_CURSOR=cnorm""".split()
_COLORS = """BLACK BLUE GREEN CYAN RED MAGENTA YELLOW WHITE""".split()
- _ANSICOLORS = "BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE".split()
def __init__(self, term_stream=sys.stdout):
- """
- Create a `TerminalController` and initialize its attributes
- with appropriate values for the current terminal.
- `term_stream` is the stream that will be used for terminal
- output; if this stream is not a tty, then the terminal is
- assumed to be a dumb terminal (i.e., have no capabilities).
- """
- # Curses isn't available on all platforms
try:
import curses
except:
@@ -160,20 +180,60 @@ def _tigetstr(self, cap_name):
cap = cap.decode("utf-8")
return re.sub(r"\$<\d+>[/*]?", "", cap)
- def render(self, template):
- """
- Replace each $-substitutions in the given template string with
- the corresponding terminal control string (if it's defined) or
- '' (if it's not).
- """
- return re.sub(r"\$\$|\${\w+}", self._render_sub, template)
- def _render_sub(self, match):
- s = match.group()
- if s == "$$":
- return s
- else:
- return getattr(self, s[2:-1])
+class _WindowsTerminalController(TerminalController):
+ def __init__(self, term_stream=sys.stdout):
+ try:
+ import ctypes
+ import ctypes.wintypes
+ import msvcrt
+
+ kernel32 = ctypes.windll.kernel32
+ ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
+ handle = msvcrt.get_osfhandle(term_stream.fileno())
+ mode = ctypes.wintypes.DWORD()
+ if not kernel32.GetConsoleMode(handle, ctypes.byref(mode)):
+ return
+ if not kernel32.SetConsoleMode(
+ handle, mode.value | ENABLE_VIRTUAL_TERMINAL_PROCESSING
+ ):
+ return
+
+ self.BOL = "\r"
+ self.UP = "\033[A"
+ self.DOWN = "\033[B"
+ self.LEFT = "\033[D"
+ self.RIGHT = "\033[C"
+
+ self.CLEAR_SCREEN = "\033[2J\033[H"
+ self.CLEAR_EOL = "\033[K"
+ self.CLEAR_BOL = "\033[1K"
+ self.CLEAR_EOS = "\033[J"
+
+ self.BOLD = "\033[1m"
+ self.BLINK = "\033[5m"
+ self.DIM = "\033[2m"
+ self.REVERSE = "\033[7m"
+ self.NORMAL = "\033[0m"
+
+ self.HIDE_CURSOR = "\033[?25l"
+ self.SHOW_CURSOR = "\033[?25h"
+
+ for i, color in enumerate(self._ANSICOLORS):
+ setattr(self, color, "\033[%dm" % (30 + i))
+ setattr(self, "BG_" + color, "\033[%dm" % (40 + i))
+
+ try:
+ size = os.get_terminal_size(term_stream.fileno())
+ self.COLS = size.columns
+ self.LINES = size.lines
+ except (AttributeError, ValueError, OSError):
+ pass
+
+ # The Windows Terminal handles the right-margin newline correctly.
+ self.XN = True
+ except Exception:
+ return
#######################################################################
More information about the llvm-commits
mailing list