forked from genewildish/Mainline
feat: Implement interactive font selection by scanning the fonts/ directory for .otf, .ttf, and .ttc files, adding new fonts and updating documentation.
This commit is contained in:
114
engine/app.py
114
engine/app.py
@@ -90,7 +90,7 @@ def _draw_font_picker(faces, selected):
|
||||
print()
|
||||
print(f" {G_HI}FONT PICKER{RST}")
|
||||
print(f" {W_GHOST}{'─' * (w - 4)}{RST}")
|
||||
print(f" {W_DIM}{config.FONT_PATH[:max_preview_w]}{RST}")
|
||||
print(f" {W_DIM}{config.FONT_DIR[:max_preview_w]}{RST}")
|
||||
print(f" {W_GHOST}↑/↓ move · Enter select · q accept current{RST}")
|
||||
print()
|
||||
|
||||
@@ -99,7 +99,7 @@ def _draw_font_picker(faces, selected):
|
||||
active = pos == selected
|
||||
pointer = "▶" if active else " "
|
||||
color = G_HI if active else W_DIM
|
||||
print(f" {color}{pointer} [{face['index']}] {face['name']}{RST}")
|
||||
print(f" {color}{pointer} {face['name']}{RST}{W_GHOST} · {face['file_name']}{RST}")
|
||||
|
||||
if top > 0:
|
||||
print(f" {W_GHOST}… {top} above{RST}")
|
||||
@@ -108,53 +108,93 @@ def _draw_font_picker(faces, selected):
|
||||
|
||||
print()
|
||||
print(f" {W_GHOST}{'─' * (w - 4)}{RST}")
|
||||
print(f" {W_DIM}Preview: {faces[selected]['name']}{RST}")
|
||||
print(
|
||||
f" {W_DIM}Preview: {faces[selected]['name']} · {faces[selected]['file_name']}{RST}"
|
||||
)
|
||||
preview_rows = faces[selected]["preview_rows"][:preview_h]
|
||||
for row in preview_rows:
|
||||
shown = row[:max_preview_w]
|
||||
print(f" {shown}")
|
||||
|
||||
def pick_font_face():
|
||||
"""Interactive startup picker for selecting a face from a font file."""
|
||||
"""Interactive startup picker for selecting a face from repo OTF files."""
|
||||
if not config.FONT_PICKER:
|
||||
return
|
||||
|
||||
print(CLR, end="")
|
||||
print(CURSOR_OFF, end="")
|
||||
print()
|
||||
print(f" {G_HI}FONT PICKER{RST}")
|
||||
print(f" {W_GHOST}{'─' * (tw() - 4)}{RST}")
|
||||
print(f" {W_DIM}{config.FONT_PATH}{RST}")
|
||||
print()
|
||||
|
||||
try:
|
||||
faces = render.list_font_faces(config.FONT_PATH, max_faces=64)
|
||||
except Exception as exc:
|
||||
print(f" {G_DIM}> unable to load font file: {exc}{RST}")
|
||||
print(f" {W_GHOST}> startup aborted (font selection is required){RST}")
|
||||
time.sleep(1.4)
|
||||
font_files = config.list_repo_font_files()
|
||||
if not font_files:
|
||||
print(CLR, end="")
|
||||
print(CURSOR_OFF, end="")
|
||||
print()
|
||||
print(f" {G_HI}FONT PICKER{RST}")
|
||||
print(f" {W_GHOST}{'─' * (tw() - 4)}{RST}")
|
||||
print(f" {G_DIM}> no .otf/.ttf/.ttc files found in: {config.FONT_DIR}{RST}")
|
||||
print(f" {W_GHOST}> add font files to the fonts folder, then rerun{RST}")
|
||||
time.sleep(1.8)
|
||||
sys.exit(1)
|
||||
|
||||
face_ids = [face["index"] for face in faces]
|
||||
default = config.FONT_INDEX if config.FONT_INDEX in face_ids else faces[0]["index"]
|
||||
|
||||
prepared = []
|
||||
for face in faces:
|
||||
idx = face["index"]
|
||||
name = face["name"]
|
||||
for font_path in font_files:
|
||||
try:
|
||||
fnt = render.load_font_face(config.FONT_PATH, idx)
|
||||
rows = _normalize_preview_rows(render.render_line(name, fnt))
|
||||
faces = render.list_font_faces(font_path, max_faces=64)
|
||||
except Exception:
|
||||
rows = ["(preview unavailable)"]
|
||||
prepared.append({"index": idx, "name": name, "preview_rows": rows})
|
||||
fallback = os.path.splitext(os.path.basename(font_path))[0]
|
||||
faces = [{"index": 0, "name": fallback}]
|
||||
for face in faces:
|
||||
idx = face["index"]
|
||||
name = face["name"]
|
||||
file_name = os.path.basename(font_path)
|
||||
try:
|
||||
fnt = render.load_font_face(font_path, idx)
|
||||
rows = _normalize_preview_rows(render.render_line(name, fnt))
|
||||
except Exception:
|
||||
rows = ["(preview unavailable)"]
|
||||
prepared.append(
|
||||
{
|
||||
"font_path": font_path,
|
||||
"font_index": idx,
|
||||
"name": name,
|
||||
"file_name": file_name,
|
||||
"preview_rows": rows,
|
||||
}
|
||||
)
|
||||
|
||||
if not prepared:
|
||||
print(CLR, end="")
|
||||
print(CURSOR_OFF, end="")
|
||||
print()
|
||||
print(f" {G_HI}FONT PICKER{RST}")
|
||||
print(f" {W_GHOST}{'─' * (tw() - 4)}{RST}")
|
||||
print(f" {G_DIM}> no readable font faces found in: {config.FONT_DIR}{RST}")
|
||||
time.sleep(1.8)
|
||||
sys.exit(1)
|
||||
|
||||
def _same_path(a, b):
|
||||
try:
|
||||
return os.path.samefile(a, b)
|
||||
except Exception:
|
||||
return os.path.abspath(a) == os.path.abspath(b)
|
||||
|
||||
selected = next(
|
||||
(
|
||||
i
|
||||
for i, f in enumerate(prepared)
|
||||
if _same_path(f["font_path"], config.FONT_PATH)
|
||||
and f["font_index"] == config.FONT_INDEX
|
||||
),
|
||||
0,
|
||||
)
|
||||
|
||||
selected = next((i for i, f in enumerate(prepared) if f["index"] == default), 0)
|
||||
if not sys.stdin.isatty():
|
||||
selected_index = prepared[selected]["index"]
|
||||
config.set_font_selection(font_index=selected_index)
|
||||
selected_font = prepared[selected]
|
||||
config.set_font_selection(
|
||||
font_path=selected_font["font_path"],
|
||||
font_index=selected_font["font_index"],
|
||||
)
|
||||
render.clear_font_cache()
|
||||
print(f" {G_DIM}> using face {selected_index}{RST}")
|
||||
print(
|
||||
f" {G_DIM}> using {selected_font['name']} ({selected_font['file_name']}){RST}"
|
||||
)
|
||||
time.sleep(0.8)
|
||||
print(CLR, end="")
|
||||
print(CURSOR_OFF, end="")
|
||||
@@ -179,11 +219,13 @@ def pick_font_face():
|
||||
finally:
|
||||
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
|
||||
|
||||
selected = prepared[selected]["index"]
|
||||
|
||||
config.set_font_selection(font_index=selected)
|
||||
selected_font = prepared[selected]
|
||||
config.set_font_selection(
|
||||
font_path=selected_font["font_path"],
|
||||
font_index=selected_font["font_index"],
|
||||
)
|
||||
render.clear_font_cache()
|
||||
print(f" {G_DIM}> using face {selected}{RST}")
|
||||
print(f" {G_DIM}> using {selected_font['name']} ({selected_font['file_name']}){RST}")
|
||||
time.sleep(0.8)
|
||||
print(CLR, end="")
|
||||
print(CURSOR_OFF, end="")
|
||||
|
||||
Reference in New Issue
Block a user