RFC-015: Дизайн системы конфигурации YaoXiang
Дата принятия: 2026-02-15
Предшествующий RFC: RFC-014: Дизайн системы управления пакетами
Аннотация
Разработка унифицированной системы конфигурации для языка YaoXiang с двумя уровнями: пользовательским и проектным, обеспечивающей общую инфраструктуру конфигурации для менеджера пакетов, компилятора, REPL, LSP и других компонентов.
Мотивация
Зачем нужна эта возможность/изменение?
Инструментарий YaoXiang включает несколько компонентов:
- Менеджер пакетов (читает зависимости)
- Интерфейсный компилятор (читает i18n конфигурацию)
- REPL (читает интерактивную конфигурацию)
- LSP (читает fmt/lint/test конфигурацию)
- Система сборки (читает конфигурацию сборки)
Каждому компоненту необходима унифицированная инфраструктура конфигурации.
Текущие проблемы
- Конфигурации компонентов разрозненны, отсутствует единый стандарт
- Пользователи не могут централизованно управлять настройками
- Отсутствует чёткое разграничение между проектной и пользовательской конфигурацией
Предложение
Основной дизайн
Многоуровневая архитектура:
Приоритет конфигурации (высший → низший):
┌─────────────────────────────────────────────┐
│ 1. Проектный yaoxiang.toml │ ← Управление командой проекта
├─────────────────────────────────────────────┤
│ 2. Пользовательский ~/.config/yaoxiang/config.toml │ ← Пользовательские предпочтения
├─────────────────────────────────────────────┤
│ 3. Значения по умолчанию компилятора │ ← Разумные начальные значения
└─────────────────────────────────────────────┘Правило: верхний уровень переопределяет нижний, неуказанные параметры наследуются от нижнего уровня.
Ограничения уровней конфигурации
| Секция конфигурации | Пользовательский | Проектный | Потребитель |
|---|---|---|---|
[package].* | ❌ | ✅ | Менеджер пакетов |
[yaoxiang] | ❌ | ✅ | Компилятор |
[dependencies] | ❌ | ✅ | Менеджер пакетов |
[dev-dependencies] | ❌ | ✅ | Менеджер пакетов |
[bin] | ❌ | ✅ | Менеджер пакетов |
[lib] | ❌ | ✅ | Менеджер пакетов |
[build] | ✅ | ✅ | Система сборки |
[profile.*] | ✅ | ✅ | Система сборки |
[install] | ✅ | ❌ | Менеджер пакетов |
[i18n] | ✅ | ✅ | Компилятор |
[repl] | ✅ | ✅ | REPL |
[fmt] | ✅ | ✅ | LSP |
[lint] | ✅ | ✅ | LSP |
[test] | ✅ | ✅ | LSP |
[tasks] | ✅ | ✅ | CLI |
Примеры
Проектная конфигурация:
# 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"Пользовательская конфигурация:
# ~/.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"]Детальный дизайн
Конфигурация только для проекта
[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"Конфигурация только для пользователя
[install]
dir = "~/.local/share/yaoxiang"Конфигурация для обоих уровней
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
[i18n].lang | String | "en" | Язык |
[i18n].fallback | String | "en" | Резервный язык |
[repl].history-size | Number | 1000 | Размер истории |
[repl].history-file | Path | ~ | Файл истории |
[repl].prompt | String | "yx> " | Приглашение |
[repl].colors | Boolean | true | Подсветка синтаксиса |
[repl].auto-imports | [String] | [] | Автоимпорт |
[fmt].line-width | Number | 120 | Ширина строки |
[fmt].indent-width | Number | 4 | Отступ |
[fmt].use-tabs | Boolean | false | Табуляция |
[fmt].single-quote | Boolean | false | Одинарные кавычки |
[lint].rules | [String] | ["recommended"] | Набор правил |
[lint].strict | Boolean | false | Строгий режим |
[test].report | String | "console" | Отчёт о тестах |
[build].output | String | "dist/" | Выходной каталог |
Переопределение через командную строку и переменные окружения
# Переопределение через командную строку
yaoxiang run main.yx --lang zh
yaoxiang fmt --config-indent-width=2
# Переменные окружения
export YAOXIANG_LANG=zh
export YAOXIANG_FMT_INDENT_WIDTH=2Приоритет: Командная строка > Переменные окружения > Файл конфигурации
Команда yaoxiang config
CLI-команды для управления конфигурацией:
# Инициализировать пользовательскую конфигурацию (по умолчанию)
yaoxiang config init
# Редактировать пользовательскую конфигурацию (открыть редактор)
yaoxiang config edit
# Показать текущую конфигурацию (объединённую)
yaoxiang config show
# Показать источники конфигурации
yaoxiang config show --source
# Сбросить к конфигурации по умолчанию
yaoxiang config resetПервый запуск: При первом запуске любой команды yaoxiang автоматически проверяется наличие пользовательской конфигурации. Если она отсутствует, конфигурация генерируется автоматически с параметрами по умолчанию.
Расположение файлов конфигурации:
- Проектная:
./yaoxiang.toml(в корне проекта) - Пользовательская:
~/.config/yaoxiang/config.toml
Семантика слияния конфигурации
Конфигурации разных уровней сливаются по следующим правилам:
| Тип | Стратегия | Описание |
|---|---|---|
| Скаляр (String/Number/Boolean) | Замена | Проектный уровень переопределяет |
| Массив (Array) | Замена | Проектный полностью заменяет |
| Объект (Object) | Глубокое слияние | Поля объединяются, отсутствующие наследуются |
Пример — глубокое слияние объектов:
# Пользовательская
[lint]
rules = ["recommended"]
severity = "warn"
# Проектная
[lint]
strict = true
# Результат слияния
[lint]
rules = ["recommended"] # Из пользовательской
severity = "warn" # Из пользовательской
strict = true # Из проектнойОбратная совместимость
- ✅ Существующий режим без файла конфигурации сохраняется (все компоненты используют встроенные значения по умолчанию)
- ✅ Новые параметры конфигурации имеют разумные значения по умолчанию
- ✅ При первом запуске команды конфигурация генерируется автоматически с параметрами по умолчанию
- ✅ При ошибке парсинга конфигурации отображается понятное сообщение с указанием конкретной строки и причины ошибки
Компромиссы
Преимущества
- Унифицированная инфраструктура конфигурации, сокращение дублирования кода
- Пользовательские предпочтения единообразны между проектами
- LSP/REPL/компилятор используют единый набор конфигурации
- Постепенная настройка, объявление по мере необходимости
Недостатки
- Большое количество параметров конфигурации, несколько увеличивается кривая обучения
- Требуется унифицированный парсер конфигурации
Альтернативные решения
| Решение | Причина отклонения |
|---|---|
| Независимая конфигурация каждого компонента | Дублирование кода, фрагментированный UX |
| Только аргументы командной строки | Невозможность сохранения пользовательских предпочтений |
| Только переменные окружения | Конфигурация проекта сложно версионируется |
Стратегия реализации
Фазы
| Фаза | Содержание |
|---|---|
| Phase 1 | Базовый парсер конфигурации, поддержка toml, проектная конфигурация, yaoxiang config init |
| Phase 2 | Пользовательская конфигурация, логика слияния, yaoxiang config edit/show |
| Phase 3 | Переопределение через командную строку/переменные окружения, ограничения platform, расширение [tool.*] |
Зависимости
- Зависит от RFC-014 системы управления пакетами
Риски
| Риск | Меры снижения |
|---|---|
| Слишком много параметров | Разумные значения по умолчанию, прозрачно для пользователя |
| Сложный парсер | Использование существующей toml-библиотеки |
Открытые вопросы
- [x] Синтаксис
featuresдля условной компиляции? → Вынесен в отдельный RFC, зависит от RFC-011 системы generics - [x] Дизайн
workspaceрабочих пространств? → Вынесен в отдельный RFC, высокая сложность, требует отдельного дизайна
Принятые функции (третья фаза)
platform Ограничения платформы
Внимание: следующий синтаксис используется в файле конфигурации
yaoxiang.toml, не в исходном коде YaoXiang (файлы.yx). Пользователям не нужно писатьcfg(...)в коде.
Поддержка конфигурации, зависящей от целевой операционной системы/архитектуры:
# yaoxiang.toml (файл конфигурации)
[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"]Синтаксис: [target.'<условие>'.<секция_конфига>]
Описание:
- Этот синтаксис появляется только в файле конфигурации
yaoxiang.toml - При сборке выбирается соответствующая конфигурация на основе параметра
--target - Пользователям не нужно и не следует писать синтаксис
cfg(...)в исходном коде.yx
Поддерживаемые условия:
cfg(os = "windows")— Система Windowscfg(os = "linux")— Система Linuxcfg(os = "macos")— Система macOScfg(target_arch = "x86_64")— 64-битная архитектура x86cfg(target_arch = "aarch64")— 64-битная архитектура ARM
[tool.*] Расширение конфигурации сторонних инструментов
Разрешено сторонним инструментам хранить конфигурацию в секции [tool.<название>]:
[tool.eslint]
extension = ["yx", "yxp"]
ignore = ["node_modules/", "dist/"]
[tool.prettier]
semi = false
singleQuote = trueПоведение:
- YaoXiang игнорирует неизвестные секции
[tool.*], но сохраняет их в файле конфигурации - Сторонние инструменты могут интегрироваться через
yaoxiang tool run <название>или напрямую обращаться к конфигурации - Конфигурация, специфичная для инструментов, не валидируется
