from tuicolors import WHITE, BRIGHT_BLACK, GREEN, RED import os import math SPIN_STATUS = ['|','/','-','\\'] CORRECT = "\033[92mv\033[00m" INCORRECT = "\033[91mX\033[00m" UP_LINE = "\033[A" def colourText(string: str, colour: int = WHITE, backgroundcolour: int = None) -> str: if backgroundcolour is not None: bg_code = backgroundcolour + 10 return f"\033[{colour};{bg_code}m{string}\033[0m" else: return f"\033[{colour}m{string}\033[0m" def limitText(string: str, limit: int=-1) -> str: if limit == -1: limit = os.get_terminal_size().columns-3 if len(string) > limit: return string[:limit]+"..." else: return string class LoadingBar: def __init__(self): if os.get_terminal_size().columns < 57: self.size = os.get_terminal_size().columns - 5 else: self.size = 55 self.percentage = 0.0 self.spin = 0 self.line = [] self.first = True self.max = -1 def addLine(self, line: int): self.line = [""] * line def updateLine(self, index: int, text: str): self.line[index] = f"{text}{' '*(os.get_terminal_size().columns-len(text))}" def setPercentage(self, percentage: float): if percentage >= 0.0 and percentage <= 100.0: self.percentage = percentage def getPercentage(self) -> float: return self.percentage def setMaximum(self, max: int): self.max = max def getMaximum(self) -> int: return self.max def setValue(self, value: int): if self.max == -1: raise ValueError("Please set the maximum before setValue by calling LoadingBar.setMaximum()") elif value > self.max: raise ValueError(f"Cannot set a value superior to LoadingBar maximum: {self.max}") else: self.percentage = (value/self.max)*100.0 def incrementValue(self): if self.max == -1: raise ValueError("Please set the maximum before incrementValue by calling LoadingBar.setMaximum()") value = math.floor((self.percentage/100.0)*self.max)+1 self.setValue(value) def finish(self): self.percentage = 100.0 def hasFinished(self) -> bool: return self.percentage == 100.0 def updateSpin(self): self.spin += 1 if self.spin >= len(SPIN_STATUS): self.spin = 0 def getSpin(self) -> str: if self.percentage >= 100.0: return CORRECT else: return SPIN_STATUS[self.spin] def getBackgroundColour(self) -> str: if self.percentage >= 100.0: return GREEN else: return WHITE def getUpLine(self) -> str: if not(self.first): return UP_LINE*len(self.line) else: return "" def start(self): print("\n"*(len(self.line)+1), end='', flush=True) def __str__(self) -> str: filled = math.floor((self.percentage/100)*(self.size-5)) empty = (self.size-5)-filled filled_str = colourText(" " * filled, backgroundcolour=self.getBackgroundColour()) empty_str = colourText(" " * empty, backgroundcolour=BRIGHT_BLACK) formatted_percent = colourText(str(int(self.percentage)), self.getBackgroundColour()) ret = self.getUpLine() for l in self.line: ret += f"{l}\n" ret += f"{self.getSpin()} {filled_str}{empty_str} {formatted_percent}%" self.updateSpin() self.first = False return ret def getLastEntry(filepath: str) -> str: with open(filepath, "r") as log_file: log_file.seek(0) new_data = log_file.readlines() if new_data: last_line = new_data[-1].strip() return last_line