151 lines
4.8 KiB
Python
151 lines
4.8 KiB
Python
import os
|
|
from pathlib import Path
|
|
|
|
import typer
|
|
|
|
ROOT_FOLDER = "/home/kodjo/Dev/MyDocManager/src/frontend/node_modules/@sicons"
|
|
MAX_SIZE = 2000000
|
|
|
|
import re
|
|
|
|
|
|
def pascal_to_snake(name: str) -> str:
|
|
"""Convert a PascalCase or CamelCase string to snake_case."""
|
|
# Insert underscore before capital letters (except the first one)
|
|
s1 = re.sub(r'(.)([A-Z][a-z]+)', r'\1_\2', name)
|
|
# Handle consecutive capital letters (like 'HTTPServer' -> 'http_server')
|
|
s2 = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', s1)
|
|
return s2.lower()
|
|
|
|
|
|
app = typer.Typer()
|
|
|
|
|
|
def list_sources(source_folder: str):
|
|
return os.listdir(source_folder)
|
|
|
|
|
|
def list_icons_from_source(source_folder: str, source: str):
|
|
res = []
|
|
for f in os.listdir(f"{source_folder}/{source}"):
|
|
if f.endswith(".svg"):
|
|
res.append(f)
|
|
return res
|
|
|
|
|
|
def read_content(source_folder: str, source: str, file_name: str):
|
|
with open(f"{source_folder}/{source}/{file_name}", "r") as f:
|
|
return f.read().strip()
|
|
|
|
|
|
def get_dir_size(path: str | Path) -> int:
|
|
p = Path(path)
|
|
if p.is_file():
|
|
return p.stat().st_size
|
|
elif p.is_dir():
|
|
return sum(f.stat().st_size for f in p.rglob('*') if f.is_file())
|
|
else:
|
|
raise FileNotFoundError(f"Path not found: {path}")
|
|
|
|
|
|
def sizeof_fmt(num, suffix="B"):
|
|
for unit in ["", "K", "M", "G", "T"]:
|
|
if abs(num) < 1024.0:
|
|
return f"{num:3.1f}{unit}{suffix}"
|
|
num /= 1024.0
|
|
return f"{num:.1f}P{suffix}"
|
|
|
|
|
|
def init_buffer(source_folder: str, source: str):
|
|
buffer = ""
|
|
readme_file_path = f"{source_folder}/{source}/README.md"
|
|
if os.path.exists(readme_file_path):
|
|
with open(readme_file_path, "r") as f_readme:
|
|
for line in f_readme:
|
|
if line.startswith("#"):
|
|
buffer += line
|
|
else:
|
|
buffer += f"# {line}"
|
|
buffer += "\n\n"
|
|
|
|
buffer += "from fastcore.basics import NotStr\n\n"
|
|
return buffer
|
|
|
|
|
|
def flush(dry_run, suppress_suffix, source_folder: str, target_folder: str, buffer: str, size: int, part: int, source: str):
|
|
suffix = '' if suppress_suffix else f"_test"
|
|
outfile = f"{source}{suffix}.py" if part == 0 else f"{source}_p{part}{suffix}.py"
|
|
if not dry_run:
|
|
output_path = f"{target_folder}/{outfile}" if part == 0 else f"{target_folder}/{outfile}"
|
|
with open(output_path, "w") as f:
|
|
f.write(buffer)
|
|
|
|
typer.echo(f" Generated {source} as {outfile} ({sizeof_fmt(size)}, max={sizeof_fmt(MAX_SIZE)})")
|
|
return init_buffer(source_folder, source), 0, part + 1
|
|
|
|
|
|
@app.command("list")
|
|
def list_icons(
|
|
source: str = typer.Argument(None, help="The source file to list icons from"),
|
|
source_folder: str = typer.Option(ROOT_FOLDER, help="The source folder containing icons"),
|
|
count: bool = typer.Option(False, help="Counts the number of items"),
|
|
size: bool = typer.Option(False, help="Gets the size of the items"),
|
|
):
|
|
res = []
|
|
if source:
|
|
res.extend(list_icons_from_source(source_folder, source))
|
|
else:
|
|
res.extend(list_sources(source_folder))
|
|
|
|
if count:
|
|
typer.echo(len(res))
|
|
return
|
|
|
|
if size:
|
|
path = f"{source_folder}/{source}" if source else f"{source_folder}"
|
|
size = get_dir_size(path)
|
|
typer.echo(sizeof_fmt(size))
|
|
return
|
|
|
|
for r in res:
|
|
typer.echo(r)
|
|
|
|
|
|
@app.command("generate")
|
|
def generate_icons(
|
|
source: str = typer.Argument(None, help="The source file to list icons from"),
|
|
source_folder: str = typer.Option(ROOT_FOLDER, help="The source folder containing icons"),
|
|
target_folder: str = typer.Option(".", help="The folder where to create the python files."),
|
|
top: int = typer.Option(0, help="The number of top items to generate"),
|
|
dry_run: bool = typer.Option(True, help="Does not generate the icons"),
|
|
suppress_suffix: bool = typer.Option(False, help="Does not add the suffix to the icon names"),
|
|
):
|
|
sources = [source] if source else list_sources(source_folder)
|
|
for current_source in sources:
|
|
typer.echo(f"Generating icons for {current_source}")
|
|
buffer = init_buffer(source_folder, current_source)
|
|
size = 0
|
|
part = 0
|
|
for index, svg_file in enumerate(list_icons_from_source(source_folder, current_source)):
|
|
|
|
if 0 < top <= index:
|
|
break
|
|
|
|
icon_name = os.path.splitext(os.path.basename(svg_file))[0]
|
|
svg_content = read_content(source_folder, current_source, svg_file)
|
|
svg_content = svg_content.replace("<svg ", f'<svg name="{current_source}-{icon_name}" ').replace("\n", "")
|
|
|
|
content = f"{pascal_to_snake(icon_name)} = NotStr('''{svg_content}''')"
|
|
buffer += f"{content}\n"
|
|
size += len(content)
|
|
|
|
if size > MAX_SIZE:
|
|
buffer, size, part = flush(dry_run, suppress_suffix, source_folder, target_folder, buffer, size, part,
|
|
current_source)
|
|
|
|
flush(dry_run, suppress_suffix, source_folder, target_folder, buffer, size, part, current_source)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
app()
|