#!/usr/bin/python3 import os import sys from urllib.parse import urljoin, quote def path_to_file_uri(path): """ Converts a file path to a file URI. Handles absolute and relative paths. """ abs_path = os.path.abspath(path) return urljoin("file://", quote(abs_path)) def is_binary_file(filepath, chunk_size=1024): """ Prüft, ob eine Datei binär ist, indem sie den Inhalt der Datei auf nicht-druckbare Zeichen untersucht. """ try: with open(filepath, "rb") as file: chunk = file.read(chunk_size) if b"\0" in chunk: # Nullbyte ist ein typisches Zeichen für Binärdateien return True return False except Exception as e: print(f"Fehler beim Prüfen, ob Datei binär ist: {filepath}: {e}") return True def search_keywords_in_files(keywords): if not keywords: print("Bitte geben Sie mindestens ein Stichwort an.") sys.exit(1) # Allowed comment symbols comment_symbols = {"//", "#", ";"} for root, dirs, files in os.walk("."): # Ausschließen bestimmter Verzeichnisse dirs[:] = [d for d in dirs if d not in {".git", "build"}] for file in files: filepath = os.path.join(root, file) # Überspringen von Binärdateien if is_binary_file(filepath): continue try: with open(filepath, "r", encoding="utf-8") as f: lines = f.readlines() for line_number, line in enumerate(lines, start=1): stripped_line = line.lstrip() # Entfernt führende Leerzeichen for symbol in comment_symbols: if stripped_line.startswith(symbol): # Entfernt das Kommentarzeichen und nachfolgende Leerzeichen howtoMatch = stripped_line[len(symbol):].lstrip() if howtoMatch.startswith(("HOWTO ", "HOWTO: ", "How to ")): if all(keyword in howtoMatch.lower() for keyword in keywords): # Titelzeile ohne Kommentarzeichen print(howtoMatch.rstrip()) # Ausgabe nachfolgender Zeilen mit dem gleichen Kommentar-Präfix for subsequent_line in lines[line_number:]: subsequent_line = subsequent_line.lstrip() if subsequent_line.startswith(symbol): # Entfernt Kommentarzeichen aus Folgezeilen print("\t" + subsequent_line[len(symbol):].strip()) else: break # Link mit Zeilennummer print(f"--> {path_to_file_uri(filepath)}:{line_number}") # Abstand zwischen Matches print() break except Exception as e: print(f"Fehler beim Lesen der Datei {filepath}: {e}") if __name__ == "__main__": if len(sys.argv) < 2: print("Verwendung: bin/howto ...") sys.exit(1) search_keywords_in_files([arg.lower() for arg in sys.argv[1:]])