Project Summary
- Built a lightweight templating tool in
Rust for modifying configuration files in-place.
- Implements a minimal inline templating language embedded within comments.
- Designed for dotfile theming and automation, enabling dynamic config updates without separate template files.
Technical Challenges
- Designing a minimal templating language that works within existing config syntax.
- Parsing inline comment-based instructions without interfering with file semantics.
- Ensuring safe, deterministic replacements using a fixed-length constraint.
- Managing multiple sequential transformations on a single line.
- Supporting flexible file formats with different comment styles.
Core Design
- Inline templating system:
- Template logic is written inside comments on the same line as the target config.
- Avoids separate template files, keeping configuration self-contained.
- Marker-Based Parsing:
- Each file defines a
marker_char (e.g: //, ;, %).
- Template code is detected when the marker is repeated
marker_repetition_num times.
- Pattern-Based Replacement:
- Uses
Regex patterns to locate target text.
- Replaces matched segments with values defined in config (
keyword).
Safety Model
- Enforces fixed-length replacements:
- Replacement text must match the length of the original.
- Prevents unintended shifts in file structure or formatting.
- Deterministic matching:
- Each function operates on a specific match index.
- Multiple functions on a line act on successive matches (
nth match based on their order).
Templating System
- Keyword-driven replacement:
- A
keyword maps to a value defined in the TOML config.
- Used to replace matched patterns in config files.
- Execution Model:
- Functions are parsed left-to-right on a line.
- Each function targets a specific match within the line.
Supported Functions
| Function |
Arguments |
Description |
@replace |
keyword pattern |
Replace first text which matches pattern with the keyword. |
@replace‑col |
keyword |
Replace first text which matches #[A‑Za‑z\d]{6} with the keyword. |
@replace‑pattern |
pattern_1 keyword pattern_2 |
Find first text which matches pattern_1, then find first match within this match based on pattern_2 and replace that with the keyword. |
@replace‑pattern‑col |
keyword pattern_2 |
Find first text which matches #[A‑Za‑z\d]{6}, then find first match within this match based on pattern_2 and replace that with the keyword. |
Configuration System
- Uses
TOML for configuration.
- Located at
$XDG_CONFIG_HOME/dotfile-templater/config.toml.
- Defines:
- Active theme.
- Marker behaviour (
marker_char, marker_repetition_num).
- Target files and their parsing rules.
- File configuration:
- Supports relative paths (from
.config/) and absolute paths.
- Each file must define its own
marker_char.
Example Config
theme = "purple-night"
marker_repetition_num = 3
files = [
{file = "eww/eww.scss", marker_char = "//"},
{file = "eww/bar/bar.yuck", marker_char = ";"},
{file = "wofi/style.css", marker_char = ";"},
{file = "hypr/hyprland.conf", marker_char = "%"},
]
[[themes]]
name = "purple-night"
primary_col = "#9549FF"
secondary_col = "#FF4958"
tertiary_col = "#B3FF49"
quaternary_col = "#49FFF0"
bg_col = "#1A1B26"
bg_col_light = "#24283B"
fg_col = "#A9B1D6"
[[themes]]
name = "blue-banana"
primary_col = "#48FFD1"
secondary_col = "#4876FF"
tertiary_col = "#FF4876"
quaternary_col = "#FFD148"
bg_col = "#0A0A40"
bg_col_light = "#11116C"
fg_col = "#9999F8"
Theme System
- Themes are defined as named sections in the config.
- Each theme:
- Must include a
name.
- Can define arbitrary variables (e.g: colours, strings).
- Enables:
- Centralised value management.
- Easy switching between configurations (e.g: colour schemes).
Example Usage
test = This will not be configured % Even if there are comments
$primary: rgb(9549FF); %%% @replace-pattern('rgb\([A-Za-z\d]{6}\)', primary_col, '[A-Za-z\d]{6}')
$secondary: #FF4958; %%% @replace-pattern-col(secondary_col, '[A-Za-z\d]{6}')
$tertiary: #B3FF49; #123456; %%% @replace-col(fg_col) @replace-col(bg_col)
$quaternary: #49FFF0; %%% @replace-col(quaternary_col)
$background: #1A1B26; %%% @replace-col(bg_col)
$background-lighter: #24283B; %%% @replace-col(bg_col_light)
$foreground: #A9B1D6; %%% @replace-col(fg_col)
Extensibility
- New template functions can be added without changing file format.
- Supports:
- Arbitrary regex-based transformations.
- Custom themes with user-defined variables.
- Multiple file types with different comment syntaxes.
- Suitable for:
- Dotfile management.
- Theming systems.
- Automated config generation.
Current Limitations
- Fixed-length replacement constraint limits flexibility.
- Regex-based approach may be brittle for complex syntax.
- No validation for malformed template expressions.
- Limited error feedback for failed matches or replacements.