Coverage for src/markdown_exec/formatters/tree.py: 69.64%
42 statements
« prev ^ index » next coverage.py v7.2.3, created at 2023-04-16 20:19 +0200
« prev ^ index » next coverage.py v7.2.3, created at 2023-04-16 20:19 +0200
1"""Formatter for file-system trees."""
3from __future__ import annotations
5from textwrap import dedent
6from typing import TYPE_CHECKING, Any
8from markdown_exec.rendering import MarkdownConverter, code_block
10if TYPE_CHECKING:
11 from markdown import Markdown
14def _rec_build_tree(lines: list[str], parent: list, offset: int, base_indent: int) -> int:
15 while offset < len(lines):
16 line = lines[offset]
17 lstripped = line.lstrip()
18 indent = len(line) - len(lstripped)
19 if indent == base_indent: 19 ↛ 22line 19 didn't jump to line 22, because the condition on line 19 was never false
20 parent.append((lstripped, []))
21 offset += 1
22 elif indent > base_indent:
23 offset = _rec_build_tree(lines, parent[-1][1], offset, indent)
24 else:
25 return offset
26 return offset
29def _build_tree(code: str) -> list[tuple[str, list]]:
30 lines = dedent(code.strip()).split("\n")
31 root_layer: list[tuple[str, list]] = []
32 _rec_build_tree(lines, root_layer, 0, 0)
33 return root_layer
36def _rec_format_tree(tree: list[tuple[str, list]], *, root: bool = True) -> list[str]:
37 lines = []
38 n_items = len(tree)
39 for index, node in enumerate(tree):
40 last = index == n_items - 1
41 prefix = "" if root else f"{'└' if last else '├'}── "
42 if node[1]: 42 ↛ 43line 42 didn't jump to line 43, because the condition on line 42 was never true
43 lines.append(f"{prefix}📁 {node[0]}")
44 sublines = _rec_format_tree(node[1], root=False)
45 if root:
46 lines.extend(sublines)
47 else:
48 indent_char = " " if last else "│"
49 lines.extend([f"{indent_char} {line}" for line in sublines])
50 else:
51 name = node[0].split()[0]
52 icon = "📁" if name.endswith("/") else "📄"
53 lines.append(f"{prefix}{icon} {node[0]}")
54 return lines
57def _format_tree(code: str, md: Markdown, result: str, **options: Any) -> str:
58 markdown = MarkdownConverter(md)
59 output = "\n".join(_rec_format_tree(_build_tree(code)))
60 return markdown.convert(code_block(result or "bash", output, **options.get("extra", {})))