# 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:** ```bash export TYPEDIALOG_FRAGMENT_PATH="/path/to/fragments:/another/path" ``` **Windows:** ```cmd 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: 1. **Absolute path** → Use directly if provided 2. **Form's directory** (`base_dir`) → Backward compatible behavior 3. **Directories in TYPEDIALOG_FRAGMENT_PATH** → Search left to right 4. **First match wins** → Subsequent directories are not checked ### Example ```bash export TYPEDIALOG_FRAGMENT_PATH=".typedialog/ci/fragments:/usr/local/share/typedialog/fragments" ``` **Fragment reference:** `includes = ["user-auth.toml"]` **Search order:** ```text 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:** ```bash # System-wide fragments export TYPEDIALOG_FRAGMENT_PATH="/opt/company/typedialog/fragments" ``` **Directory structure:** ```text /opt/company/typedialog/fragments/ ├── user-auth.toml ├── database-config.toml ├── api-settings.toml └── logging.toml ``` **Form reference:** ```toml [[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:** ```bash export TYPEDIALOG_FRAGMENT_PATH=".typedialog/fragments:/opt/company/typedialog/fragments" ``` **Directory structure:** ```text project/ ├── .typedialog/ │ └── fragments/ │ └── user-auth.toml # ← Custom version └── form.toml ``` **Form reference:** ```toml [[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:** ```bash export TYPEDIALOG_FRAGMENT_PATH=".typedialog/fragments:~/team-fragments:/opt/company/fragments" ``` **Search priority:** 1. Project-specific (`.typedialog/fragments/`) 2. Team-shared (`~/team-fragments/`) 3. Company-wide (`/opt/company/fragments/`) **Benefit:** Flexible hierarchy for different scopes. ## Configuration ### direnv Integration Automatically load `TYPEDIALOG_FRAGMENT_PATH` when entering project directory. **Setup:** ```bash # 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 < 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) ```rust #[cfg(unix)] let separator = ':'; ``` **Windows:** `;` (semicolon) ```rust #[cfg(windows)] let separator = ';'; ``` ### Backward Compatibility - ✅ If `TYPEDIALOG_FRAGMENT_PATH` not set → works as before (uses `base_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:** ```text Error: Failed to load fragment 'user-fields.toml': No such file or directory ``` **Check:** ```bash # 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:** ```bash # 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: ```cmd set TYPEDIALOG_FRAGMENT_PATH="C:\Program Files\TypeDialog\fragments;D:\Custom Fragments" ``` ## Examples ### Example 1: Standard Setup **Project structure:** ```text project/ ├── form.toml ├── .envrc └── .typedialog/ └── fragments/ └── custom-field.toml ``` **.envrc:** ```bash export TYPEDIALOG_FRAGMENT_PATH=".typedialog/fragments:/usr/local/share/typedialog/fragments" ``` **form.toml:** ```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:** ```bash export TYPEDIALOG_FRAGMENT_PATH=".typedialog/fragments:$HOME/dev-fragments:/opt/fragments" ``` **Production:** ```bash export TYPEDIALOG_FRAGMENT_PATH="/opt/company/fragments" ``` **Result:** Development has local overrides, production uses only approved fragments. ## See Also - [Configuration Guide](./configuration.md) - Full TypeDialog configuration - [Fragment System](./fragments.md) - How to write fragments - [Environment Variables](./configuration.md#environment-variables) - All TypeDialog env vars --- **Last Updated:** 2025-12-26 **Feature:** TYPEDIALOG_FRAGMENT_PATH **Status:** ✅ Implemented in TypeDialog v0.1.0