Skip to content

Instantly share code, notes, and snippets.

@fdmysterious
Created August 2, 2025 14:32
Show Gist options
  • Save fdmysterious/65454f1b087e8db7743ff134dd962a64 to your computer and use it in GitHub Desktop.
Save fdmysterious/65454f1b087e8db7743ff134dd962a64 to your computer and use it in GitHub Desktop.
"""
Quick, dirty and weird script to print a file tree with a separator to write doc after it
- Florian Dupeyron ([email protected])
- August 2025
Change the TREE variable to change the file tree to display
Example output tree:
--------------------
<root> ∙ (you can add your documentation here)
├─ docs ∙
├─ web/ ∙
│ ├─ landing-page/ ∙
│ └─ documentation/ ∙
│ ∙
├─ platform/ ∙
│ ├─ observability/ → compose.yml ∙
│ ├─ proxy/ → compose.yml ∙
│ ├─ websrv/ → compose.yml ∙
│ ├─ analytics/ → compose.yml ∙
│ │ ∙
│ ├─ Justfile ∙
│ └─ compose.yml ∙
│ ∙
└─ Justfile ∙
"""
from __future__ import annotations
###########################################
INDENT_AMT = 1 # Indentation space count, change how long is bar before file name
PADDING_AMT = 0 # Number of skip lines between each level
OFFSET_TXT = 1 # Offset between the item name and start of next arrow
TOTAL_LENGTH = 38 # Total length before right bar
###########################################
def print_indent(lvlstack: tuple[bool]) -> str:
it_lvl = iter(lvlstack)
try:
next(it_lvl)
except StopIteration:
pass
s_indent = (" " * OFFSET_TXT if lvlstack else "") + "".join(
("│" if not x else " ") + (" " * (INDENT_AMT + OFFSET_TXT))
for x in it_lvl
)
return s_indent
def print_item_txt(lvlstack: tuple[bool], leaf: bool, txt: str) -> str:
# Print start of line
if txt:
s_start = ("├" + "─" * INDENT_AMT + " " if not leaf else "└" + "─" * INDENT_AMT + " ") if lvlstack else ""
else:
s_start = "" if leaf else "│"
s_indent = print_indent(lvlstack)
s_line = f"{s_indent}{s_start}{txt}"
l_line = len(s_line)
if l_line < TOTAL_LENGTH:
s_line += " " * (TOTAL_LENGTH - l_line)
s_line += " ∙ "
return s_line
def iterate_last(x):
"""Utility iterator that returns all items in an iterator with a boolean
that indicates if it's the last element
"""
try:
cur = next(x) # Can throw StopIteration if empty
try:
while True:
nxt = next(x)
yield cur, False
cur = nxt
except StopIteration:
yield cur, True
except StopIteration:
pass
def process_tree(tree, lvlstack: tuple[bool] = None, leaf: bool = True) -> str:
lvlstack = lvlstack or tuple()
if isinstance(tree, str):
item_name, item_children = tree, None
else:
item_name, item_children = tree
s_start = print_item_txt(lvlstack, leaf, item_name)
if item_children:
s_content = "\n" + "\n".join(map(
lambda x: process_tree(x[0], lvlstack + (leaf,), x[1]),
iterate_last(iter(item_children))
))
else:
s_content = ""
if leaf and lvlstack:
s_content += ("\n" + print_indent(lvlstack)) * PADDING_AMT
return s_start + s_content
###########################################
TREE = ("<root>", (
"docs",
("web/", (
"landing-page/",
"documentation/"
)),
"",
("platform/", (
"observability/ → compose.yml",
"proxy/ → compose.yml",
"websrv/ → compose.yml",
"analytics/ → compose.yml",
"",
"Justfile",
"compose.yml",
)),
"",
"Justfile",
))
print(process_tree(iter(TREE)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment