RFC-015: YaoXiang Configuration System Design
Acceptance Date: 2026-02-15
Prerequisite RFC: RFC-014: Package Manager Design
Summary
Design a unified configuration system for YaoXiang language, supporting user-level and project-level scopes, providing shared configuration infrastructure for components like package manager, compiler, REPL, and LSP.
Motivation
Why is this feature/change needed?
The YaoXiang toolchain consists of multiple components:
- Package manager (reads dependency configuration)
- Compiler frontend (reads i18n configuration)
- REPL (reads interactive configuration)
- LSP (reads fmt/lint/test configuration)
- Build system (reads build configuration)
Each component needs a unified configuration infrastructure.
Current Problems
- Configuration is scattered across components with no unified standard
- Users cannot manage their preferences in a unified way
- No clear hierarchy between project configuration and user configuration
Proposal
Core Design
Layered Architecture:
Configuration Priority (High → Low):
┌─────────────────────────────────────────────┐
│ 1. Project-level yaoxiang.toml │ ← Controlled by project team
├─────────────────────────────────────────────┤
│ 2. User-level ~/.config/yaoxiang/config.toml │ ← User preferences
├─────────────────────────────────────────────┤
│ 3. Compiler defaults │ ← Reasonable initial values
└─────────────────────────────────────────────┘Rule: Upper layers override lower layers; unset options fall back to lower layers.
Configuration Layer Restrictions
| Config Section | User-level | Project-level | Consumer |
|---|---|---|---|
[package].* | ❌ | ✅ | Package manager |
[yaoxiang] | ❌ | ✅ | Compiler |
[dependencies] | ❌ | ✅ | Package manager |
[dev-dependencies] | ❌ | ✅ | Package manager |
[bin] | ❌ | ✅ | Package manager |
[lib] | ❌ | ✅ | Package manager |
[build] | ✅ | ✅ | Build system |
[profile.*] | ✅ | ✅ | Build system |
[install] | ✅ | ❌ | Package manager |
[i18n] | ✅ | ✅ | Compiler |
[repl] | ✅ | ✅ | REPL |
[fmt] | ✅ | ✅ | LSP |
[lint] | ✅ | ✅ | LSP |
[test] | ✅ | ✅ | LSP |
[tasks] | ✅ | ✅ | CLI |
Examples
Project-level Configuration:
# yaoxiang.toml
[package]
name = "my-package"
version = "0.1.0"
[yaoxiang]
version = ">=0.1.0, <1.0.0"
[dependencies]
foo = "^1.0.0"
[build]
output = "dist/"
[tasks]
build = "yaoxiang build"
test = "yaoxiang test"User-level Configuration:
# ~/.config/yaoxiang/config.toml
[install]
dir = "~/.local/share/yaoxiang"
[i18n]
lang = "zh"
fallback = "en"
[repl]
history-size = 1000
prompt = "yx> "
colors = true
[fmt]
line-width = 120
indent-width = 4
[lint]
rules = ["recommended"]Detailed Design
Project-level-only Configuration
[package]
name = "my-package"
version = "0.1.0"
description = "A short description"
authors = ["Alice <alice@example.com>"]
license = "MIT"
repository = "https://github.com/alice/my-project"
[yaoxiang]
version = ">=0.1.0, <1.0.0"
[dependencies]
foo = "^1.0.0"
[dev-dependencies]
test-utils = "0.1.0"
[lib]
path = "src/lib.yx"
[[bin]]
name = "my-cli"
path = "src/cli.yx"
[exports]
"." = "src/lib.yx"
"./foo" = "src/foo.yx"
[build]
script = "build.yx"
output = "dist/"
[profile.release]
optimize = true
lto = true
[run]
main = "src/main.yx"
args = ["--quiet"]
[tasks]
build = "yaoxiang build"
test = "yaoxiang test"
lint = "yaoxiang fmt && yaoxiang check"User-level-only Configuration
[install]
dir = "~/.local/share/yaoxiang"Shared Configuration (Both Levels)
| Field | Type | Default | Description |
|---|---|---|---|
[i18n].lang | String | "en" | Language |
[i18n].fallback | String | "en" | Fallback language |
[repl].history-size | Number | 1000 | History entries |
[repl].history-file | Path | ~ | History file |
[repl].prompt | String | "yx> " | Prompt |
[repl].colors | Boolean | true | Syntax highlighting |
[repl].auto-imports | [String] | [] | Auto imports |
[fmt].line-width | Number | 120 | Line width |
[fmt].indent-width | Number | 4 | Indentation width |
[fmt].use-tabs | Boolean | false | Tab indentation |
[fmt].single-quote | Boolean | false | Single quotes |
[lint].rules | [String] | ["recommended"] | Rule set |
[lint].strict | Boolean | false | Strict mode |
[test].report | String | "console" | Test report |
[build].output | String | "dist/" | Output directory |
Command Line and Environment Variable Overrides
# Command line overrides
yaoxiang run main.yx --lang zh
yaoxiang fmt --config-indent-width=2
# Environment variables
export YAOXIANG_LANG=zh
export YAOXIANG_FMT_INDENT_WIDTH=2Priority: Command Line > Environment Variables > Config File
yaoxiang config Command
Provides CLI commands for configuration management:
# Initialize user-level configuration (with default options)
yaoxiang config init
# Edit user-level configuration (opens editor)
yaoxiang config edit
# Show current configuration (merged effective config)
yaoxiang config show
# Show configuration sources
yaoxiang config show --source
# Reset to default configuration
yaoxiang config resetFirst Run: When a user runs any yaoxiang command for the first time, the system automatically checks if user-level configuration exists. If not, it generates one with default options automatically.
Configuration File Locations:
- Project-level:
./yaoxiang.toml(project root directory) - User-level:
~/.config/yaoxiang/config.toml
Configuration Merge Semantics
Configurations from different layers are merged according to the following rules:
| Type | Strategy | Description |
|---|---|---|
| Scalar (String/Number/Boolean) | Replace | Project-level overrides user-level |
| Array | Replace | Project-level completely replaces user-level |
| Object | Deep merge | Field-by-field merge; undefined fields inherit from lower layer |
Example - Object Deep Merge:
# User-level
[lint]
rules = ["recommended"]
severity = "warn"
# Project-level
[lint]
strict = true
# Merged result
[lint]
rules = ["recommended"] # from user-level
severity = "warn" # from user-level
strict = true # from project-levelBackward Compatibility
- ✅ Existing no-config-file mode continues to be supported (all components use built-in defaults)
- ✅ New configuration items all have reasonable defaults
- ✅ Configuration is automatically generated with default options on first command run
- ✅ Configuration parsing failures display friendly errors with specific line numbers and error reasons
Trade-offs
Advantages
- Unified configuration infrastructure reduces duplicate code
- User preferences remain consistent across projects
- LSP/REPL/Compiler share the same configuration
- Incremental configuration, declare as needed
Disadvantages
- More configuration items, slightly increased learning curve
- Requires a unified configuration parser
Alternative Approaches
| Approach | Why Not Chosen |
|---|---|
| Independent config per component | Duplicate code, fragmented user experience |
| Command-line arguments only | Cannot persist user preferences |
| Environment variables only | Project configuration hard to version control |
Implementation Strategy
Phases
| Phase | Contents |
|---|---|
| Phase 1 | Basic config parser, toml support, project-level config, yaoxiang config init |
| Phase 2 | User-level config, config merge logic, yaoxiang config edit/show |
| Phase 3 | Command line/env var overrides, platform constraints, [tool.*] extensions |
Dependencies
- Depends on RFC-014 Package Manager System
Risks
| Risk | Mitigation |
|---|---|
| Too many config items | Provide reasonable defaults, invisible to users |
| Complex parser | Use existing toml library |
Open Issues
- [x]
featuresconditional compilation syntax? → Moved to separate RFC, depends on RFC-011 Generics System - [x]
workspaceworkspace design? → Moved to separate RFC, high complexity, needs independent design
Accepted Features (Phase 3)
platform Platform Constraints
Note: The following syntax is used in
yaoxiang.tomlconfiguration files, not in YaoXiang source code (.yxfiles). Users do not need to writecfg(...)in their code.
Supports platform-specific configuration based on target OS/architecture:
# yaoxiang.toml (config file)
[target.'cfg(windows)'.build]
output = "dist/win32"
[target.'cfg(unix)'.build]
output = "dist/unix"
[target.'cfg(target_arch = "x86_64")'.build]
rustflags = ["-C target-cpu=native"]Syntax: [target.'<condition>'.<config-section>]
Explanation:
- This syntax only appears in
yaoxiang.tomlconfiguration files - During build, corresponding configuration is selected based on
--targetparameter - Users do not need, and should not, write
cfg(...)syntax in.yxsource code
Supported Conditions:
cfg(os = "windows")- Windows systemscfg(os = "linux")- Linux systemscfg(os = "macos")- macOS systemscfg(target_arch = "x86_64")- 64-bit x86 architecturecfg(target_arch = "aarch64")- ARM 64-bit architecture
[tool.*] Third-party Tool Configuration Extensions
Allows third-party tools to store configuration under [tool.<name>]:
[tool.eslint]
extension = ["yx", "yxp"]
ignore = ["node_modules/", "dist/"]
[tool.prettier]
semi = false
singleQuote = trueBehavior:
- YaoXiang ignores unknown
[tool.*]sections but preserves them in the config file - Third-party tools can be integrated via
yaoxiang tool run <name>or accessed directly - Tool-specific configurations are not validated
