8.3 KiB
Fragment Search Paths
TypeDialog supports loading form fragments from multiple directories using the TYPEDIALOG_FRAGMENT_PATH environment variable.
Overview
Fragment search paths enable:
- ✅ Centralized fragment libraries shared across projects
- ✅ Local overrides for project-specific customizations
- ✅ Zero duplication when using standard fragments
- ✅ Automatic updates when central library is updated
Environment Variable
TYPEDIALOG_FRAGMENT_PATH
Colon-separated list (semicolon on Windows) of directories to search for fragment files.
Unix/Linux/macOS:
export TYPEDIALOG_FRAGMENT_PATH="/path/to/fragments:/another/path"
Windows:
set TYPEDIALOG_FRAGMENT_PATH=C:\fragments;D:\other\fragments
Search Order
When a fragment is referenced (e.g., includes = ["fragments/user-fields.toml"]), TypeDialog searches in this order:
- Absolute path → Use directly if provided
- Form's directory (
base_dir) → Backward compatible behavior - Directories in TYPEDIALOG_FRAGMENT_PATH → Search left to right
- First match wins → Subsequent directories are not checked
Example
export TYPEDIALOG_FRAGMENT_PATH=".typedialog/ci/fragments:/usr/local/share/typedialog/fragments"
Fragment reference: includes = ["user-auth.toml"]
Search order:
1. ./user-auth.toml (form's directory)
2. .typedialog/ci/fragments/user-auth.toml (local)
3. /usr/local/share/typedialog/fragments/user-auth.toml (system)
Result: First existing file is loaded.
Use Cases
Case 1: Centralized Fragment Library
Organization maintains a shared library of standard fragments.
Setup:
# System-wide fragments
export TYPEDIALOG_FRAGMENT_PATH="/opt/company/typedialog/fragments"
Directory structure:
/opt/company/typedialog/fragments/
├── user-auth.toml
├── database-config.toml
├── api-settings.toml
└── logging.toml
Form reference:
[[item]]
type = "group"
includes = ["user-auth.toml", "database-config.toml"]
Benefit: All projects use same fragments → consistency across organization.
Case 2: Local Overrides
Project needs custom version of standard fragment.
Setup:
export TYPEDIALOG_FRAGMENT_PATH=".typedialog/fragments:/opt/company/typedialog/fragments"
Directory structure:
project/
├── .typedialog/
│ └── fragments/
│ └── user-auth.toml # ← Custom version
└── form.toml
Form reference:
[[item]]
type = "group"
includes = ["user-auth.toml"] # Uses local version
Result:
user-auth.toml→ loads from.typedialog/fragments/(local override)database-config.toml→ loads from/opt/company/...(standard)
Benefit: Override only what you need, rest stays synchronized.
Case 3: Multiple Fragment Sources
Combine fragments from different sources: company library, team library, local.
Setup:
export TYPEDIALOG_FRAGMENT_PATH=".typedialog/fragments:~/team-fragments:/opt/company/fragments"
Search priority:
- Project-specific (
.typedialog/fragments/) - Team-shared (
~/team-fragments/) - Company-wide (
/opt/company/fragments/)
Benefit: Flexible hierarchy for different scopes.
Configuration
direnv Integration
Automatically load TYPEDIALOG_FRAGMENT_PATH when entering project directory.
Setup:
# Install direnv
brew install direnv # macOS
# Or: apt install direnv # Linux
# Add to shell rc file (~/.bashrc, ~/.zshrc)
eval "$(direnv hook bash)" # or zsh, fish, etc.
# Create .envrc in project root
cat > .envrc <<EOF
export TYPEDIALOG_FRAGMENT_PATH=".typedialog/fragments:\$HOME/typedialog/fragments"
EOF
# Allow direnv to load .envrc
direnv allow
Result: TYPEDIALOG_FRAGMENT_PATH is automatically set when you cd into project.
Shell Profile
Set globally for all projects.
~/.bashrc or ~/.zshrc:
export TYPEDIALOG_FRAGMENT_PATH="$HOME/.typedialog/fragments:/usr/local/share/typedialog/fragments"
Per-Command
Override for single invocation.
TYPEDIALOG_FRAGMENT_PATH="/custom/path" typedialog form schema.toml
Implementation Details
Code Location
crates/typedialog-core/src/form_parser/parser.rs
Functions:
get_fragment_search_paths()- Parse environment variableresolve_fragment_path()- Search directories in order
Logic:
fn resolve_fragment_path(path: &str, base_dir: &Path) -> PathBuf {
// 1. Absolute path → use directly
if Path::new(path).is_absolute() {
return PathBuf::from(path);
}
// 2. Try base_dir (backward compatible)
let base_path = base_dir.join(path);
if base_path.exists() {
return base_path;
}
// 3. Try each search path
for search_dir in get_fragment_search_paths() {
let candidate = search_dir.join(path);
if candidate.exists() {
return candidate;
}
}
// 4. Return base_path for error reporting
base_path
}
Separator Detection
Unix/Linux/macOS: : (colon)
#[cfg(unix)]
let separator = ':';
Windows: ; (semicolon)
#[cfg(windows)]
let separator = ';';
Backward Compatibility
- ✅ If
TYPEDIALOG_FRAGMENT_PATHnot set → works as before (usesbase_dir) - ✅ Absolute paths → always work regardless of search paths
- ✅ Existing forms → no changes required
Best Practices
✅ DO
- Use relative paths in form definitions (
includes = ["fragment.toml"]) - Put local overrides first in search path (
.typedialog/fragments:/system/fragments) - Document custom fragments with comments explaining why local version exists
- Keep standard structure when overriding (match original fragment structure)
- Version control .envrc if project-specific paths are important
❌ DON'T
- Don't hardcode absolute paths in forms (defeats portability)
- Don't mix path separators (use
:on Unix,;on Windows) - Don't create deep hierarchies (2-3 levels max: local, team, system)
- Don't override without reason (consider if change should be upstream)
Troubleshooting
Fragment not found
Error:
Error: Failed to load fragment 'user-fields.toml': No such file or directory
Check:
# 1. Verify environment variable is set
echo $TYPEDIALOG_FRAGMENT_PATH
# 2. Check if file exists in any search path
ls .typedialog/fragments/user-fields.toml
ls /usr/local/share/typedialog/fragments/user-fields.toml
# 3. Check search order (add debug output)
export TYPEDIALOG_DEBUG=1 # If supported
Wrong version loaded
Symptom: Expected local override, but system version is used.
Check search order:
# Verify local path is FIRST
echo $TYPEDIALOG_FRAGMENT_PATH
# Should be: .typedialog/fragments:...
# Verify local file exists
ls -la .typedialog/fragments/fragment.toml
Windows path issues
Problem: Paths with spaces or special characters.
Solution: Use quotes in environment variable:
set TYPEDIALOG_FRAGMENT_PATH="C:\Program Files\TypeDialog\fragments;D:\Custom Fragments"
Examples
Example 1: Standard Setup
Project structure:
project/
├── form.toml
├── .envrc
└── .typedialog/
└── fragments/
└── custom-field.toml
.envrc:
export TYPEDIALOG_FRAGMENT_PATH=".typedialog/fragments:/usr/local/share/typedialog/fragments"
form.toml:
[[item]]
type = "group"
includes = [
"custom-field.toml", # Loads from .typedialog/fragments/
"standard-fields.toml" # Loads from /usr/local/share/.../
]
Example 2: Multi-Environment
Development:
export TYPEDIALOG_FRAGMENT_PATH=".typedialog/fragments:$HOME/dev-fragments:/opt/fragments"
Production:
export TYPEDIALOG_FRAGMENT_PATH="/opt/company/fragments"
Result: Development has local overrides, production uses only approved fragments.
See Also
- Configuration Guide - Full TypeDialog configuration
- Fragment System - How to write fragments
- Environment Variables - All TypeDialog env vars
Last Updated: 2025-12-26 Feature: TYPEDIALOG_FRAGMENT_PATH Status: ✅ Implemented in TypeDialog v0.1.0