""" Module: markdown_parser.py ---------------------------- Rozšířený Markdown parser pro curses. Podporované funkce: 1. Nadpisy (řádky začínající #) -> zobrazeny tučně a podtrženě 2. Odrážky (řádky začínající - a *) -> zobrazeny s tučným textem a symbolickou tečkou 3. Víceřádkové bloky kódu (```): vše mezi trojitými backticky je zobrazeno s curses.A_REVERSE 4. Inline formátování: **text** -> curses.A_BOLD *text* -> curses.A_UNDERLINE `text` -> curses.A_REVERSE Poznámka: nepodporujeme vnořené značky, a parser je pouze zjednodušený. """ import re import curses def parse_markdown(text): """ Hlavní funkce pro rozparsování zadaného textu na seznam (segment_text, attribute). Respektuje víceřádkové bloky kódu (```), nadpisy, odrážky a volá parse_inline pro zpracování běžných řádků. """ segments = [] lines = text.splitlines() in_code_block = False # Indikátor, zda se nacházíme uvnitř bloku ```. for line in lines: stripped = line.strip() # Kontrola začátku/konce bloku kódu (```). if stripped.startswith("```"): # Přepínáme stav in_code_block = not in_code_block if in_code_block: # Řádek obsahující samotné ``` # Pokud tam je něco navíc, ořežeme code_block_marker = stripped[3:].strip() # Můžeme sem zařadit logiku pro detekci jazyka, pokud by to bylo potřeba else: # Konec bloku kódu pass continue if in_code_block: # Ve víceřádkovém kódu každou linku zobrazíme s curses.A_REVERSE segments.append((line + "\n", curses.A_REVERSE)) continue # Pokud nejsme v bloku kódu, zpracujeme nadpisy, odrážky a inline formát. if stripped.startswith("#"): # Nadpis: zjistíme, kolik # tam je hash_count = 0 for ch in line: if ch == '#': hash_count += 1 else: break # Obsah nadpisu za #... content = line[hash_count:].strip() # Atribut: tučný a podtržený segments.append((content + "\n", curses.A_BOLD | curses.A_UNDERLINE)) elif stripped.startswith("-") or stripped.startswith("*"): # Odrážka content = line[1:].strip() segments.append((" • " + content + "\n", curses.A_BOLD)) else: # Běžný řádek -> inline formát inline_segments = parse_inline(line) for seg_text, seg_attr in inline_segments: segments.append((seg_text, seg_attr)) segments.append(("\n", 0)) return segments def parse_inline(text): """ Rozparsuje inline Markdown značky (tučný, kurzíva, inline kód) v jednom řádku, vrací seznam (text, attr). """ segments = [] pos = 0 # Regulární výraz pro zachycení **text**, *text*, `text` pattern = re.compile(r'(\*\*.*?\*\*|\*.*?\*|`.*?`)') for match in pattern.finditer(text): start, end = match.span() if start > pos: segments.append((text[pos:start], 0)) token = match.group(0) if token.startswith("**") and token.endswith("**"): content = token[2:-2] segments.append((content, curses.A_BOLD)) elif token.startswith("*") and token.endswith("*"): content = token[1:-1] segments.append((content, curses.A_UNDERLINE)) elif token.startswith("`") and token.endswith("`"): content = token[1:-1] segments.append((content, curses.A_REVERSE)) else: segments.append((token, 0)) pos = end if pos < len(text): segments.append((text[pos:], 0)) return segments if __name__ == "__main__": # Krátký test sample = """# Nadpis 1 Toto je normální text s **tučným** a *kurzívou*. - Odrážka 1 * Odrážka 2 A teď blok kódu: ls -la echo "Hello" Další text s `inline kódem` a ## menším nadpisem? ## Nadpis 2 """ segs = parse_markdown(sample) for seg, attr in segs: # Ukázkové vypsání v terminálu (bez curses) pro debug print(f"{repr(seg)} attr={attr}")