Uploading m5rcode Ubuntu Port to the repo

This commit is contained in:
m5rcel { Marcel }
2025-10-09 20:24:27 +02:00
committed by GitHub
commit 342a616ff9
30 changed files with 2363 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

46
commands/cmd_cd.py Normal file
View File

@@ -0,0 +1,46 @@
# commands/cmd_cd.py
import os
from colorama import Fore
class CdCommand:
def __init__(self, files_dir, shell_ref, target_dir):
# files_dir = ~/m5rcode/files
self.files_dir = files_dir
self.project_root = os.path.dirname(files_dir) # ~/m5rcode
self.shell = shell_ref[0] # the M5RShell instance
self.target = target_dir.strip()
def run(self):
if not self.target or self.target == '.':
# Stay in current directory
return
# Compute new absolute path
candidate = os.path.abspath(
os.path.normpath(
os.path.join(self.shell.cwd, self.target)
)
)
# If they typed '..' from files_dir, allow up to project_root
if self.target == '..':
# from files_dir → project_root
if self.shell.cwd == self.files_dir:
new_path = self.project_root
# from any subfolder of files_dir → one level up, but not above project_root
else:
new_path = os.path.dirname(self.shell.cwd)
if not new_path.startswith(self.project_root):
new_path = self.project_root
else:
new_path = candidate
# Check it stays within project_root
if not new_path.startswith(self.project_root):
print(Fore.RED + "Access denied: You cannot leave the m5rcode project.")
return
if os.path.isdir(new_path):
self.shell.cwd = new_path
else:
print(Fore.RED + f"No such directory: {self.target}")

47
commands/cmd_credits.py Normal file
View File

@@ -0,0 +1,47 @@
from colorama import Fore, Style
from pyfiglet import Figlet
def strip_ansi(text):
import re
return re.sub(r'\x1b\[[0-9;]*m', '', text)
class CreditsCommand:
def run(self):
box_width = 70
inner_width = box_width - 2
fig = Figlet(font='slant')
credits = [
(f"{Style.BRIGHT}{Fore.CYAN}m5rcel{Style.RESET_ALL}", "Lead Developer"),
(f"{Style.BRIGHT}{Fore.YELLOW}pythonjs.cfd{Style.RESET_ALL}", "Project Hosting & Deployment"),
(f"{Style.BRIGHT}{Fore.MAGENTA}colorama{Style.RESET_ALL}", "Used for terminal styling"),
(f"{Style.BRIGHT}{Fore.GREEN}fastfetch inspired{Style.RESET_ALL}", "Design influence"),
(f"{Style.BRIGHT}{Fore.RED}openai.com{Style.RESET_ALL}", "Some smart AI help ;)"),
]
# Top border
print(Fore.MAGENTA + "" + "" * inner_width + "")
# Figlet "CREDITS" title, trimmed/padded and centered vertically
credits_title_lines = fig.renderText("CREDITS").splitlines()
for line in credits_title_lines:
if line.strip() == '': continue
raw = line[:inner_width]
pad = (inner_width - len(strip_ansi(raw))) // 2
out = " " * pad + raw
out = out[:inner_width]
out = out + " " * (inner_width - len(strip_ansi(out)))
print(Fore.MAGENTA + "" + Fore.LIGHTMAGENTA_EX + out + Fore.MAGENTA + "")
print(Fore.MAGENTA + "" + "" * inner_width + "")
# Content, each line padded to match box width
for name, role in credits:
left = f"{name:<25}"
dash = f"{Fore.CYAN}{Style.RESET_ALL}"
right = f"{Fore.LIGHTWHITE_EX}{role}{Style.RESET_ALL}"
raw_text = f"{left} {dash} {right}"
raw_len = len(strip_ansi(raw_text))
line = raw_text + " " * (inner_width - raw_len)
print(Fore.MAGENTA + "" + line + Fore.MAGENTA + "")
# Bottom border
print(Fore.MAGENTA + "" + "" * inner_width + "" + Style.RESET_ALL)

163
commands/cmd_dir.py Normal file
View File

@@ -0,0 +1,163 @@
import os
from colorama import Fore, Style
import re
def strip_ansi(text):
return re.sub(r'\x1b\[[0-9;]*m', '', text)
class DirCommand:
def __init__(self, cwd, target):
self.cwd = cwd
self.target = target if target else cwd
def run(self):
path = os.path.abspath(os.path.join(self.cwd, self.target))
box_min = 60
if not os.path.exists(path):
# Error box
width = max(box_min, len(f"No such file or directory: {self.target}") + 10)
print(Fore.RED + "" + "" * (width - 2) + "")
error_msg = f"No such file or directory: {self.target}"
print(Fore.RED + "" + error_msg.center(width - 2) + "")
print(Fore.RED + "" + "" * (width - 2) + "" + Style.RESET_ALL)
return
if os.path.isfile(path):
# Single file info box
file_size = os.path.getsize(path)
if file_size > 1024*1024:
size_str = f"{file_size/(1024*1024):.1f} MB"
elif file_size > 1024:
size_str = f"{file_size/1024:.1f} KB"
else:
size_str = f"{file_size} B"
width = max(box_min, len(self.target) + 20)
print(Fore.MAGENTA + "" + "" * (width - 2) + "")
title = "File Information"
print(Fore.MAGENTA + "" + Fore.CYAN + Style.BRIGHT + title.center(width - 2) + Fore.MAGENTA + "")
print(Fore.MAGENTA + "" + "" * (width - 2) + "")
name_line = f"Name: {Fore.LIGHTWHITE_EX}{self.target}{Style.RESET_ALL}"
size_line = f"Size: {Fore.LIGHTWHITE_EX}{size_str}{Style.RESET_ALL}"
type_line = f"Type: {Fore.LIGHTWHITE_EX}File{Style.RESET_ALL}"
for line in [name_line, size_line, type_line]:
pad = " " * (width - 2 - len(strip_ansi(line)))
print(Fore.MAGENTA + "" + line + pad + Fore.MAGENTA + "")
print(Fore.MAGENTA + "" + "" * (width - 2) + "" + Style.RESET_ALL)
return
# Directory listing
try:
items = os.listdir(path)
if not items:
# Empty directory
width = box_min
print(Fore.MAGENTA + "" + "" * (width - 2) + "")
title = f"Directory: {os.path.basename(path) or 'Root'}"
print(Fore.MAGENTA + "" + Fore.CYAN + Style.BRIGHT + title.center(width - 2) + Fore.MAGENTA + "")
print(Fore.MAGENTA + "" + "" * (width - 2) + "")
empty_msg = "Directory is empty"
print(Fore.MAGENTA + "" + Fore.YELLOW + empty_msg.center(width - 2) + Fore.MAGENTA + "")
print(Fore.MAGENTA + "" + "" * (width - 2) + "" + Style.RESET_ALL)
return
# Calculate columns for nice layout
name_col = 35
type_col = 12
size_col = 15
total_width = name_col + type_col + size_col + 6 # spaces + borders
width = max(box_min, total_width)
# Separate files and directories
dirs = []
files = []
for item in sorted(items):
full_path = os.path.join(path, item)
if os.path.isdir(full_path):
dirs.append(item)
else:
try:
size = os.path.getsize(full_path)
if size > 1024*1024:
size_str = f"{size/(1024*1024):.1f} MB"
elif size > 1024:
size_str = f"{size/1024:.1f} KB"
else:
size_str = f"{size} B"
except:
size_str = "Unknown"
files.append((item, size_str))
# Header
print(Fore.MAGENTA + "" + "" * (width - 2) + "")
title = f"Directory: {os.path.basename(path) or 'Root'}"
print(Fore.MAGENTA + "" + Fore.CYAN + Style.BRIGHT + title.center(width - 2) + Fore.MAGENTA + "")
print(Fore.MAGENTA + "" + "" * (width - 2) + "")
# Column headers
header = (
Fore.LIGHTMAGENTA_EX + Style.BRIGHT +
f"{'Name':<{name_col}} {'Type':<{type_col}} {'Size':<{size_col}}" +
Style.RESET_ALL
)
pad = " " * (width - 2 - len(strip_ansi(header)))
print(Fore.MAGENTA + "" + header + pad + Fore.MAGENTA + "")
print(Fore.MAGENTA + "" + "" * (width - 2) + "")
# List directories first
for dirname in dirs:
name = (dirname[:name_col-2] + "..") if len(dirname) > name_col-1 else dirname
name_colored = f"{Fore.BLUE + Style.BRIGHT}{name:<{name_col}}{Style.RESET_ALL}"
type_colored = f"{Fore.LIGHTCYAN_EX}Directory{Style.RESET_ALL}"
size_colored = f"{Style.DIM}-{Style.RESET_ALL}"
row = f"{name_colored} {type_colored:<{type_col}} {size_colored:<{size_col}}"
pad = " " * (width - 2 - len(strip_ansi(row)))
print(Fore.MAGENTA + "" + row + pad + Fore.MAGENTA + "")
# List files
for filename, file_size in files:
name = (filename[:name_col-2] + "..") if len(filename) > name_col-1 else filename
name_colored = f"{Fore.LIGHTWHITE_EX}{name:<{name_col}}{Style.RESET_ALL}"
# File type based on extension
if '.' in filename:
ext = filename.split('.')[-1].lower()
if ext in ['txt', 'md', 'log']:
type_color = Fore.GREEN
elif ext in ['py', 'js', 'html', 'css', 'php']:
type_color = Fore.YELLOW
elif ext in ['jpg', 'png', 'gif', 'bmp']:
type_color = Fore.MAGENTA
elif ext in ['mp3', 'wav', 'mp4', 'avi']:
type_color = Fore.CYAN
else:
type_color = Fore.WHITE
file_type = f".{ext} file"
else:
type_color = Fore.WHITE
file_type = "File"
type_colored = f"{type_color}{file_type:<{type_col}}{Style.RESET_ALL}"
size_colored = f"{Style.DIM}{Fore.LIGHTWHITE_EX}{file_size:<{size_col}}{Style.RESET_ALL}"
row = f"{name_colored} {type_colored} {size_colored}"
pad = " " * (width - 2 - len(strip_ansi(row)))
print(Fore.MAGENTA + "" + row + pad + Fore.MAGENTA + "")
# Footer with count
print(Fore.MAGENTA + "" + "" * (width - 2) + "")
count_msg = f"{len(dirs)} directories, {len(files)} files"
print(Fore.MAGENTA + "" + Fore.LIGHTBLACK_EX + Style.DIM + count_msg.center(width - 2) + Fore.MAGENTA + "")
print(Fore.MAGENTA + "" + "" * (width - 2) + "" + Style.RESET_ALL)
except PermissionError:
width = box_min
print(Fore.RED + "" + "" * (width - 2) + "")
error_msg = "Access denied"
print(Fore.RED + "" + error_msg.center(width - 2) + "")
print(Fore.RED + "" + "" * (width - 2) + "" + Style.RESET_ALL)

72
commands/cmd_exit.py Normal file
View File

@@ -0,0 +1,72 @@
from colorama import Fore, Style
import time
import os
import sys
class ExitCommand:
def shutdown_animation(self):
# Clear screen for clean shutdown
os.system('cls' if os.name == 'nt' else 'clear')
# Shutdown sequence messages
shutdown_msgs = [
"Stopping Discord RPC Integration...",
"Saving shell session...",
"Clearing command history...",
"Stopping background processes...",
"Unmounting m5rcode directories...",
"Finalizing cleanup...",
"Thank you for using m5rcode shell!"
]
print(Fore.LIGHTBLACK_EX + "m5rOS Shutdown Sequence" + Style.RESET_ALL)
print(Fore.LIGHTBLACK_EX + "=" * 25 + Style.RESET_ALL)
for i, msg in enumerate(shutdown_msgs):
time.sleep(0.3)
if i == len(shutdown_msgs) - 1:
# Last message in cyan
print(Fore.CYAN + Style.BRIGHT + f"[ OK ] {msg}" + Style.RESET_ALL)
else:
# Regular messages in white/grey
color = Fore.WHITE if i % 2 == 0 else Fore.LIGHTBLACK_EX
print(color + f"[ OK ] {msg}" + Style.RESET_ALL)
time.sleep(0.5)
# Animated "powering down" effect
print()
sys.stdout.write(Fore.LIGHTMAGENTA_EX + "Powering down")
for _ in range(6):
time.sleep(0.2)
sys.stdout.write(".")
sys.stdout.flush()
print(Style.RESET_ALL)
time.sleep(0.3)
# Final goodbye box
box_width = 50
print(Fore.MAGENTA + "" + "" * (box_width - 2) + "")
goodbye_lines = [
"m5rcode shell session ended",
"",
"Thanks for coding with us!",
"See you next time! 👋"
]
for line in goodbye_lines:
if line == "":
print(Fore.MAGENTA + "" + " " * (box_width - 2) + "")
else:
color = Fore.CYAN if "m5rcode" in line else Fore.LIGHTWHITE_EX
centered = color + line.center(box_width - 2) + Style.RESET_ALL
print(Fore.MAGENTA + "" + centered + Fore.MAGENTA + "")
print(Fore.MAGENTA + "" + "" * (box_width - 2) + "" + Style.RESET_ALL)
time.sleep(1)
def run(self):
self.shutdown_animation()
return True # Signals to shell to exit

121
commands/cmd_fastfetch.py Normal file
View File

@@ -0,0 +1,121 @@
import platform
import re
import datetime
from pathlib import Path
from colorama import Fore, Style
from pyfiglet import Figlet
try:
import psutil
_PSUTIL_AVAILABLE = True
except ImportError:
_PSUTIL_AVAILABLE = False
def strip_ansi(text):
return re.sub(r'\x1b\[[0-9;]*m', '', text)
class FastfetchCommand:
def _get_uptime(self):
if not _PSUTIL_AVAILABLE:
return "N/A (psutil not installed)"
try:
boot_time_timestamp = psutil.boot_time()
boot_datetime = datetime.datetime.fromtimestamp(boot_time_timestamp)
current_datetime = datetime.datetime.now()
uptime_seconds = (current_datetime - boot_datetime).total_seconds()
days = int(uptime_seconds // (24 * 3600))
uptime_seconds %= (24 * 3600)
hours = int(uptime_seconds // 3600)
uptime_seconds %= 3600
minutes = int(uptime_seconds // 60)
seconds = int(uptime_seconds % 60)
uptime_str = []
if days > 0:
uptime_str.append(f"{days}d")
if hours > 0:
uptime_str.append(f"{hours}h")
if minutes > 0:
uptime_str.append(f"{minutes}m")
if seconds > 0 or not uptime_str:
uptime_str.append(f"{seconds}s")
return " ".join(uptime_str)
except Exception:
return "Error calculating uptime"
def run(self):
m5rcode_version = "1.0.0"
try:
version_file = Path(__file__).parents[1] / "version.txt"
if version_file.exists():
m5rcode_version = version_file.read_text().strip()
except Exception:
pass
# ASCII "M" logo—27 chars wide
ascii_m = [
" _____ ",
" /\\ \\ ",
" /::\\____\\ ",
" /::::| | ",
" /:::::| | ",
" /::::::| | ",
" /:::/|::| | ",
" /:::/ |::| | ",
" /:::/ |::|___|______ ",
" /:::/ |::::::::\\ \\ ",
" /:::/ |:::::::::\\____\\",
" \\::/ / ~~~~~/:::/ / ",
" \\/____/ /:::/ / ",
" /:::/ / ",
" /:::/ / ",
" /:::/ / ",
" /:::/ / ",
" /:::/ / ",
" /:::/ / ",
" \\::/ / ",
" \\/____/ ",
" ",
]
uptime_info = self._get_uptime()
LABEL_PAD = 17
info_lines = [
f"{Fore.CYAN}{'m5rcode Version:':<{LABEL_PAD}}{Style.RESET_ALL} {Fore.LIGHTWHITE_EX}{m5rcode_version}{Style.RESET_ALL}",
f"{Fore.CYAN}{'Python Version:':<{LABEL_PAD}}{Style.RESET_ALL} {Fore.LIGHTWHITE_EX}{platform.python_version()}{Style.RESET_ALL}",
f"{Fore.CYAN}{'Platform:':<{LABEL_PAD}}{Style.RESET_ALL} {Fore.LIGHTWHITE_EX}{platform.system()} {platform.release()}{Style.RESET_ALL}",
f"{Fore.CYAN}{'Machine:':<{LABEL_PAD}}{Style.RESET_ALL} {Fore.LIGHTWHITE_EX}{platform.machine()}{Style.RESET_ALL}",
f"{Fore.CYAN}{'Processor:':<{LABEL_PAD}}{Style.RESET_ALL} {Fore.LIGHTWHITE_EX}{platform.processor()}{Style.RESET_ALL}",
f"{Fore.CYAN}{'Uptime:':<{LABEL_PAD}}{Style.RESET_ALL} {Fore.LIGHTWHITE_EX}{uptime_info}{Style.RESET_ALL}",
]
ascii_width = len(strip_ansi(ascii_m[0]))
content_width = max(len(strip_ansi(line)) for line in info_lines)
sep = " "
sep_width = len(sep)
total_content_width = ascii_width + sep_width + content_width
box_width = max(total_content_width, 48) + 2
# Pad info lines vertically to align with "M"
n_ascii = len(ascii_m)
n_info = len(info_lines)
info_lines_padded = [""] * ((n_ascii - n_info)//2) + info_lines + [""] * (n_ascii - n_info - (n_ascii - n_info)//2)
if len(info_lines_padded) < n_ascii:
info_lines_padded += [""] * (n_ascii - len(info_lines_padded))
# Header
print(Fore.MAGENTA + "" + "" * (box_width-2) + "")
title = f"m5rcode Fastfetch"
print(Fore.MAGENTA + "" + Fore.CYAN + title.center(box_width-2) + Fore.MAGENTA + "")
print(Fore.MAGENTA + "" + "" * (box_width-2) + "")
# Body
for mline, iline in zip(ascii_m, info_lines_padded):
line_content = (mline + sep + iline).rstrip()
pad = " " * (box_width - 2 - len(strip_ansi(line_content)))
print(Fore.MAGENTA + "" + line_content + pad + Fore.MAGENTA + "")
print(Fore.MAGENTA + "" + "" * (box_width-2) + "" + Style.RESET_ALL)

15
commands/cmd_nano.py Normal file
View File

@@ -0,0 +1,15 @@
import os, subprocess
from colorama import Fore
class NanoCommand:
def __init__(self, base_dir, filename):
if not filename.endswith(".m5r"):
filename += ".m5r"
self.path = os.path.join(base_dir, filename)
def run(self):
editor = os.getenv("EDITOR", "notepad")
if not os.path.exists(self.path):
print(Fore.YELLOW + f"Note: {self.path} does not exist, creating it.")
open(self.path, "w").close()
subprocess.call([editor, self.path])

16
commands/cmd_new.py Normal file
View File

@@ -0,0 +1,16 @@
import os
from colorama import Fore
class NewCommand:
def __init__(self, base_dir, filename):
if not filename.endswith(".m5r"):
filename += ".m5r"
self.path = os.path.join(base_dir, filename)
def run(self):
if os.path.exists(self.path):
print(Fore.RED + f"Error: {self.path} already exists.")
return
with open(self.path, "w") as f:
f.write("// New m5r file\n")
print(Fore.GREEN + f"Created: {self.path}")

48
commands/cmd_run.py Normal file
View File

@@ -0,0 +1,48 @@
import os
import re
import subprocess
import tempfile
from colorama import Fore
class RunCommand:
def __init__(self, base_dir, filename):
if not filename.endswith(".m5r"):
filename += ".m5r"
self.base_dir = base_dir
self.path = os.path.join(base_dir, filename)
def run(self):
if not os.path.exists(self.path):
print(Fore.RED + f"Error: {self.path} not found.")
return
source = open(self.path, encoding="utf-8").read()
# Extract only Python segments
py_segs = re.findall(r'<\?py(.*?)\?>', source, re.S)
if not py_segs:
print(Fore.YELLOW + "No Python code found in this .m5r file.")
return
combined = "\n".join(seg.strip() for seg in py_segs)
# Write to a temporary .py file
with tempfile.NamedTemporaryFile("w", delete=False, suffix=".py") as tf:
tf.write(combined)
tmp_path = tf.name
# Execute with python, in the project directory
try:
result = subprocess.run(
[ "python", tmp_path ],
cwd=self.base_dir,
capture_output=True,
text=True
)
if result.stdout:
print(result.stdout, end="")
if result.stderr:
print(Fore.RED + result.stderr, end="")
except FileNotFoundError:
print(Fore.RED + "Error: 'python' executable not found on PATH.")
finally:
os.unlink(tmp_path)

113
commands/cmd_wdir.py Normal file
View File

@@ -0,0 +1,113 @@
import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin
from colorama import Fore, Style
import re
def strip_ansi(text):
return re.sub(r'\x1b\[[0-9;]*m', '', text)
class WdirCommand:
def __init__(self, url):
self.url = url.strip()
def run(self):
box_min = 72
if not self.url:
print(Fore.RED + "Usage: wdir <url>" + Style.RESET_ALL)
return
# Ensure scheme
if not self.url.startswith("http://") and not self.url.startswith("https://"):
self.url = "http://" + self.url
try:
print(Fore.CYAN + f"[FETCH] Scanning directory at {self.url}..." + Style.RESET_ALL)
resp = requests.get(self.url, timeout=5)
resp.raise_for_status()
except Exception as e:
print(Fore.RED + f"[ERR] Failed to fetch {self.url}: {e}" + Style.RESET_ALL)
return
soup = BeautifulSoup(resp.text, "html.parser")
links = soup.find_all("a")
files = []
for link in links:
href = link.get("href")
if not href:
continue
if href.startswith("?") or href.startswith("#") or href.startswith("../"):
continue
is_dir = href.endswith("/")
filename = href.rstrip("/").split("/")[-1]
if not is_dir and re.search(r"\.(php|html?|asp|aspx|jsp)$", filename, re.I):
continue
if is_dir:
ftype = "Directory"
elif "." in filename:
ftype = f".{filename.split('.')[-1]} file"
else:
ftype = "File"
row_text = link.parent.get_text(" ", strip=True)
size_match = re.search(r"(\d+(?:\.\d+)?\s*(?:KB|MB|GB|B))", row_text, re.I)
date_match = re.search(r"(\d{4}-\d{2}-\d{2} \d{2}:\d{2})", row_text)
size = size_match.group(1) if size_match else "-"
modified = date_match.group(1) if date_match else "-"
files.append((filename, ftype, size, modified))
# Calculate column widths for nice boxed output
col_names = ["Name", "Type", "Size", "Modified"]
pad = [30, 15, 12, 20]
table_width = sum(pad) + len(pad) + 1 # columns + spaces + box
width = max(box_min, table_width + 2)
# If no files, pretty box saying so
if not files:
print(Fore.MAGENTA + "" + "" * (width - 2) + "")
out = "No files or directories found (maybe directory listing is disabled)."
out = out.center(width - 2)
print(Fore.MAGENTA + "" + Fore.YELLOW + out + Fore.MAGENTA + "")
print(Fore.MAGENTA + "" + "" * (width - 2) + "" + Style.RESET_ALL)
return
# Pretty header
print(Fore.MAGENTA + "" + "" * (width - 2) + "")
title = "Web Directory Listing"
print(Fore.MAGENTA + "" + Fore.CYAN + Style.BRIGHT + title.center(width - 2) + Fore.MAGENTA + "")
print(Fore.MAGENTA + "" + "" * (width - 2) + "")
# Table header
header = (
Fore.LIGHTMAGENTA_EX
+ f"{col_names[0]:<{pad[0]}} {col_names[1]:<{pad[1]}} {col_names[2]:<{pad[2]}} {col_names[3]:<{pad[3]}}"
+ Style.RESET_ALL
)
print(
Fore.MAGENTA + ""
+ header
+ " " * (width - 2 - len(strip_ansi(header)))
+ Fore.MAGENTA + ""
)
print(Fore.MAGENTA + "" + "" * (width - 2) + "")
# Table rows
for fname, ftype, size, modified in files:
if ftype == "Directory":
color = Fore.BLUE + Style.BRIGHT
elif ftype.endswith("file"):
color = Fore.CYAN
else:
color = Fore.WHITE
filecol = f"{color}{fname:<{pad[0]}}{Style.RESET_ALL}"
typecol = f"{Style.DIM}{Fore.WHITE}{ftype:<{pad[1]}}{Style.RESET_ALL}"
sizecol = f"{Style.DIM}{Fore.LIGHTWHITE_EX}{size:<{pad[2]}}{Style.RESET_ALL}"
modcol = f"{Style.DIM}{Fore.LIGHTWHITE_EX}{modified:<{pad[3]}}{Style.RESET_ALL}"
row = f"{filecol} {typecol} {sizecol} {modcol}"
print(
Fore.MAGENTA + ""
+ row
+ " " * (width - 2 - len(strip_ansi(row)))
+ Fore.MAGENTA + ""
)
# Footer
print(Fore.MAGENTA + "" + "" * (width - 2) + "" + Style.RESET_ALL)