From 46071b62cf607a751c597f54e579b2df934b99d4 Mon Sep 17 00:00:00 2001 From: Adam Skotarczak Date: Sun, 27 Apr 2025 04:15:52 +0200 Subject: [PATCH] v0.2.1 --- CHANGELOG.md | 5 ++++ scanner.py | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1287ca..523c042 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGELOG +- **2025-04-27 - Commit v0.2.1** + + - **Geändert:** + - [x] `scanner.py`: Vollständige Google-Style-Docstrings und saubere Kommentare hinzugefügt (keine Funktionsänderung). + - **2025-04-27 - Commit v0.2.0** - **Hinzugefügt:** diff --git a/scanner.py b/scanner.py index 8c40ceb..e3e8e5e 100644 --- a/scanner.py +++ b/scanner.py @@ -3,7 +3,28 @@ import argparse from typing import Optional, List class TreeScannerConfig: - def __init__(self, root_path: str = ".", folder_icon: str = "\U0001F4C1", file_icon: str = "\U0001F4C4", max_files_per_dir: int = 2, max_depth: Optional[int] = None, align_comments: bool = True, language: str = "de"): + """Konfigurationsklasse für den TreeScanner. + + Attributes: + root_path (str): Pfad des Stammverzeichnisses. + folder_icon (str): Icon für Ordner. + file_icon (str): Icon für Dateien und Platzhalter. + max_files_per_dir (int): Maximale Anzahl Dateien pro Verzeichnis. + max_depth (Optional[int]): Maximale Rekursionstiefe. + align_comments (bool): Kommentare am Zeilenende ausrichten. + language (str): Sprache der Programmausgabe (de oder en). + """ + + def __init__( + self, + root_path: str = ".", + folder_icon: str = "\U0001F4C1", + file_icon: str = "\U0001F4C4", + max_files_per_dir: int = 2, + max_depth: Optional[int] = None, + align_comments: bool = True, + language: str = "de" + ): self.root_path = root_path self.folder_icon = folder_icon self.file_icon = file_icon @@ -13,7 +34,14 @@ class TreeScannerConfig: self.language = language class TreeScanner: + """Klasse zum Scannen von Verzeichnissen und Erzeugen einer ASCII-Baumstruktur.""" + def __init__(self, config: TreeScannerConfig): + """Initialisiert den TreeScanner. + + Args: + config (TreeScannerConfig): Konfiguration für den Scanner. + """ self.config = config self.folder_count = 0 self.file_count = 0 @@ -27,13 +55,25 @@ class TreeScanner: } def scan_directory(self, path: str, depth: int = 0, prefix: str = "") -> List[str]: + """Scannt ein Verzeichnis und gibt eine Liste von ASCII-Zeilen zurück. + + Args: + path (str): Pfad des zu scannenden Verzeichnisses. + depth (int): Aktuelle Rekursionstiefe. + prefix (str): Präfix für Einrückung und Connectoren. + + Returns: + List[str]: Zeilen der Baumstruktur. + """ lines: List[str] = [] try: entries = sorted(os.listdir(path)) except PermissionError: return [f"{prefix}└── [Zugriff verweigert] {path}"] + folders = [e for e in entries if os.path.isdir(os.path.join(path, e))] files = [e for e in entries if os.path.isfile(os.path.join(path, e))] + for idx, folder in enumerate(folders): self.folder_count += 1 folder_path = os.path.join(path, folder) @@ -42,19 +82,30 @@ class TreeScanner: if self.config.max_depth is None or depth < self.config.max_depth: extension = "│ " if idx < len(folders) - 1 or files else " " lines.extend(self.scan_directory(folder_path, depth + 1, prefix + extension)) + visible_files = files[: self.config.max_files_per_dir] remaining = len(files) - len(visible_files) combined = visible_files.copy() if remaining > 0: combined.append(f"") + for idx, name in enumerate(combined): if not name.startswith(" List[str]: + """Richtet alle Zeilen so aus, dass Kommentare am gleichen Spaltenindex stehen. + + Args: + lines (List[str]): Liste der Baumstruktur-Zeilen ohne Kommentare. + + Returns: + List[str]: Zeilen mit ausgerichteten Kommentar-Platzhaltern (#). + """ max_length = max(len(line.rstrip()) for line in lines) aligned: List[str] = [] for line in lines: @@ -64,6 +115,11 @@ class TreeScanner: return aligned def generate_tree(self) -> str: + """Generiert den vollständigen Verzeichnisbaum als String. + + Returns: + str: Mehrzeiliger String mit Ordner-Icon, Ordner- und Dateienstruktur. + """ root_name = os.path.basename(os.path.abspath(self.config.root_path)) or self.config.root_path lines = [f"{self.config.folder_icon} {root_name}/"] lines += self.scan_directory(self.config.root_path) @@ -72,10 +128,16 @@ class TreeScanner: return "\n".join(lines) def print_summary(self, output_file: str) -> None: + """Gibt eine Zusammenfassung des Scanlaufs aus. + + Args: + output_file (str): Name der geschriebenen Ausgabedatei. + """ message_template = self.messages.get(self.config.language, self.messages["de"]) print(message_template["summary"].format(folders=self.folder_count, files=self.file_count, file=output_file)) def main(): + """Standalone-Ausführung mit CLI-Parameter-Unterstützung.""" parser = argparse.ArgumentParser(description="Generiert eine ASCII-Baumstruktur eines Verzeichnisses.") parser.add_argument("root_path", nargs="?", default=".", help="Pfad des Stammverzeichnisses (default: aktuelles Verzeichnis).") parser.add_argument("-n", "--max-files-per-dir", type=int, default=2, help="Maximale Anzahl Dateien pro Verzeichnis (default: 2).")