Initial commit.

This commit is contained in:
Yohan Boujon 2025-04-10 14:00:42 +02:00
commit a61536cb7d
6 changed files with 227 additions and 0 deletions

5
.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
# Python
**/__pycache__
# Temporary
**/temp

3
README.md Normal file
View file

@ -0,0 +1,3 @@
# Python Loading Bar
Just a simple loading bar to use in any of your projects. A fully working example can be found in main.py.

15
dummy.sh Executable file
View file

@ -0,0 +1,15 @@
#!/bin/bash
# Simulate a "download" process with fake delays
echo "Starting download (3 files)..."
sleep 2
echo "Downloading file 1 of 3..."
sleep 2
echo "Downloading file 2 of 3..."
sleep 2
echo "Downloading file 3 of 3..."
sleep 2
echo "Extracting files..."
sleep 1
echo "Download complete!"

64
main.py Executable file
View file

@ -0,0 +1,64 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import tui
from tuicolors import *
import os
import subprocess
import threading
import time
ROOT_FOLDER = os.path.dirname(os.path.abspath(__file__))
def updateprogress(text: str, lb: tui.LoadingBar) -> int:
if text == None:
return -1
if lb.getMaximum() == -1 and text.startswith("Starting download"):
filetotal=int(text[19])
lb.updateLine(1,f"Downloading files ({filetotal})...")
lb.setMaximum(filetotal+2)
elif lb.getMaximum() > 0:
if text.startswith("Downloading file"):
filenum = int(text[17])
lb.setValue(filenum)
if text.startswith("Extracting files..."):
lb.updateLine(1,"Extracting files...")
lb.incrementValue()
if text.startswith("Download complete!"):
lb.finish()
def showprogress():
# File info
lastentry = ""
# Loading bar
lb = tui.LoadingBar()
lb.addLine(3)
lb.updateLine(1,"Preparing download...")
while not(lb.hasFinished()):
newentry = tui.getLastEntry(f"{ROOT_FOLDER}/temp/log.txt")
# If we get a new string -> update percentage depending on the entry
if newentry != lastentry:
lastentry = newentry
updateprogress(lastentry,lb)
# Printing and waiting
print(f"\r{lb}", end='', flush=True)
time.sleep(0.1)
# Testing printing capabilities
colouredText = tui.colourText("Hello", colour=BRIGHT_RED, backgroundcolour=BLUE)
print(colouredText)
wow = tui.limitText("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec dapibus, tellus a consectetur elementum, ex ex laoreet ligula, sit amet dignissim metus eros vel ligula. Nulla malesuada risus nec libero gravida mattis. Fusce sit amet pharetra felis, congue cursus tellus. Morbi faucibus nisi at gravida viverra. Praesent a posuere ex. In hac habitasse platea dictumst. Sed sed feugiat leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec tincidunt porttitor arcu vel cursus. Vestibulum luctus quam vitae gravida viverra. ")
print(wow)
wow = tui.limitText("Tu ne parleras pas", 5)
print(wow)
os.makedirs(ROOT_FOLDER + "/temp", exist_ok=True)
with open(ROOT_FOLDER + "/temp/log.txt", "a") as log_file:
thread = threading.Thread(target=showprogress)
thread.start()
subprocess.run(["bash", "dummy.sh"], stdout=log_file, stderr=log_file)
thread.join()
print(tui.colourText("\nSuccessfully downloaded project!", GREEN))

123
tui.py Normal file
View file

@ -0,0 +1,123 @@
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

17
tuicolors.py Normal file
View file

@ -0,0 +1,17 @@
BLACK = 30
RED = 31
GREEN = 32
YELLOW = 33
BLUE = 34
MAGENTA = 35
CYAN = 36
WHITE = 37
BRIGHT_BLACK = 90
BRIGHT_RED = 91
BRIGHT_GREEN = 92
BRIGHT_YELLOW = 93
BRIGHT_BLUE = 94
BRIGHT_MAGENTA = 95
BRIGHT_CYAN = 96
BRIGHT_WHITE = 97