From 61280e469554a3a58faf57a0f1af639be8f0c49d Mon Sep 17 00:00:00 2001 From: Jan Lindemann Date: Tue, 8 Sep 2026 21:45:22 +0200 Subject: [PATCH] cmds.projects.lib.templates: Don't replace escaped markers format_list_dict() substitutes {key} markers with str.replace(), which also matches the marker inside ${key} and {{key}}, mangling text meant to survive verbatim, e.g. the ${prefix} variable reference of a pkg-config file. The built-in pkg-config template works around that with doubled braces, which produces {/usr}-style output instead. Replace the markers with a regular expression that skips markers preceded by '$' or '{', and let the pkg-config template use the ${prefix} and ${exec_prefix} references pkg-config expects. Extend the unit tests with marker escaping, value escaping, quoting, indentation, and the rendering of the built-in templates. Assisted-by: unsloth/Qwen3.8-27B-GGUF:Q4_K_M with pi.dev v0.84.2 Signed-off-by: Jan Lindemann --- .../jw/pkg/cmds/projects/lib/templates.py | 24 ++++-- .../pkg/cmds/projects/lib/templates/test.py | 86 ++++++++++++++++++- 2 files changed, 100 insertions(+), 10 deletions(-) diff --git a/src/python/jw/pkg/cmds/projects/lib/templates.py b/src/python/jw/pkg/cmds/projects/lib/templates.py index bc9bf23c..ad55af2f 100644 --- a/src/python/jw/pkg/cmds/projects/lib/templates.py +++ b/src/python/jw/pkg/cmds/projects/lib/templates.py @@ -1,3 +1,4 @@ +import re import textwrap from typing import Any, Iterable, TypeAlias, TypeGuard @@ -95,12 +96,17 @@ def format_list_dict( parts = template.splitlines(keepends = True) for line in parts: - for key, value in fmt_dict.items(): - marker = '{' + key + '}' - if marker in line: - indent = line[:line.index(marker)] - value = str(value).replace('\n', '\n' + indent) - line = line.replace(marker, value) + for key, val in fmt_dict.items(): + # -- A marker preceded by '$' or '{' is literal text rather + # than a placeholder, so that e.g. ${prefix} survives as a + # pkg-config variable reference + rx = re.compile(r'(?