From 206d2d34f61d90da25d9710a5f46aa4b66933901 Mon Sep 17 00:00:00 2001 From: Jeff Smith Date: Mon, 6 Apr 2026 14:26:37 -0600 Subject: [PATCH] feat: in-place per-file progress for classify, count, and large-file steps --- luminos.py | 40 ++++++++++++++++++++++++++++++++++------ luminos_lib/code.py | 14 +++++++++++--- luminos_lib/filetypes.py | 5 ++++- 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/luminos.py b/luminos.py index 4e4bc45..0790041 100644 --- a/luminos.py +++ b/luminos.py @@ -3,8 +3,9 @@ import argparse import json -import sys import os +import shutil +import sys from luminos_lib.tree import build_tree, render_tree from luminos_lib.filetypes import classify_files, summarize_categories @@ -15,6 +16,28 @@ from luminos_lib.watch import watch_loop from luminos_lib.report import format_report +def _progress(label): + """Return (on_file, finish) for in-place per-file progress on stderr. + + on_file(path) overwrites the current line with the label and truncated path. + finish() finalises the line with a newline. + """ + cols = shutil.get_terminal_size((80, 20)).columns + prefix = f" [scan] {label}... " + available = max(cols - len(prefix), 10) + + def on_file(path): + rel = os.path.relpath(path) + if len(rel) > available: + rel = "..." + rel[-(available - 3):] + print(f"\r{prefix}{rel}\033[K", end="", file=sys.stderr, flush=True) + + def finish(): + print(f"\r{prefix}done\033[K", file=sys.stderr, flush=True) + + return on_file, finish + + def scan(target, depth=3, show_hidden=False): """Run all analyses on the target directory and return a report dict.""" report = {} @@ -24,16 +47,21 @@ def scan(target, depth=3, show_hidden=False): report["tree"] = tree report["tree_rendered"] = render_tree(tree) - print(" [scan] Classifying files...", file=sys.stderr) - classified = classify_files(target, show_hidden=show_hidden) + on_file, finish = _progress("Classifying files") + classified = classify_files(target, show_hidden=show_hidden, on_file=on_file) + finish() report["file_categories"] = summarize_categories(classified) report["classified_files"] = classified - print(" [scan] Detecting languages and counting lines...", file=sys.stderr) - languages, loc = detect_languages(classified) + on_file, finish = _progress("Counting lines") + languages, loc = detect_languages(classified, on_file=on_file) + finish() report["languages"] = languages report["lines_of_code"] = loc - report["large_files"] = find_large_files(classified) + + on_file, finish = _progress("Checking for large files") + report["large_files"] = find_large_files(classified, on_file=on_file) + finish() print(" [scan] Finding recently modified files...", file=sys.stderr) report["recent_files"] = find_recent_files(target, show_hidden=show_hidden) diff --git a/luminos_lib/code.py b/luminos_lib/code.py index 6d2571c..d6c5596 100644 --- a/luminos_lib/code.py +++ b/luminos_lib/code.py @@ -34,10 +34,11 @@ def _count_lines(filepath): return 0 -def detect_languages(classified_files): +def detect_languages(classified_files, on_file=None): """Detect languages present and count lines of code per language. Returns (languages_set, loc_by_language). + on_file(path) is called per source file, if provided. """ source_files = [f for f in classified_files if f["category"] == "source"] languages = set() @@ -49,12 +50,17 @@ def detect_languages(classified_files): languages.add(lang) lines = _count_lines(f["path"]) loc[lang] = loc.get(lang, 0) + lines + if on_file: + on_file(f["path"]) return sorted(languages), loc -def find_large_files(classified_files): - """Find files that are unusually large (>1000 lines or >10MB).""" +def find_large_files(classified_files, on_file=None): + """Find files that are unusually large (>1000 lines or >10MB). + + on_file(path) is called per source file checked, if provided. + """ source_files = [f for f in classified_files if f["category"] == "source"] large = [] @@ -68,5 +74,7 @@ def find_large_files(classified_files): if reasons: large.append({"path": f["path"], "name": f["name"], "reasons": reasons}) + if on_file: + on_file(f["path"]) return large diff --git a/luminos_lib/filetypes.py b/luminos_lib/filetypes.py index fa99abf..da47571 100644 --- a/luminos_lib/filetypes.py +++ b/luminos_lib/filetypes.py @@ -86,10 +86,11 @@ def _classify_one(filepath): return "unknown", desc -def classify_files(target, show_hidden=False): +def classify_files(target, show_hidden=False, on_file=None): """Walk the target directory and classify every file. Returns a list of dicts: {path, name, category, size, description}. + on_file(path) is called after each file is classified, if provided. """ results = [] for root, dirs, files in os.walk(target): @@ -112,6 +113,8 @@ def classify_files(target, show_hidden=False): "size": size, "description": desc, }) + if on_file: + on_file(full) return results