rust-config-tree マニュアル
English | 中文 | 日本語 | 한국어 | Français | Deutsch | Español | Português | Svenska | Suomi | Nederlands
これは rust-config-tree の日本語マニュアルです。
概要、クイックスタート、または実行可能な サンプルから読み始めてください。
概要
English | 中文 | 日本語 | 한국어 | Français | Deutsch | Español | Português | Svenska | Suomi | Nederlands
rust-config-tree は、階層化された設定ファイルを使う Rust アプリケーション
向けに、再利用可能な設定ツリー読み込み機能と CLI 補助機能を提供します。
この crate は責務を小さく分けています。
confiqueは schema 定義、code default、validation、config template generation を担当します。figmentは runtime loading と runtime source metadata を担当します。rust-config-treeは recursive include traversal、include path resolution、.envloading、template target discovery、reusable clap command を担当します。
たとえば、次のような自然な設定ファイル layout を扱うときに便利です。
include:
- config/server.yaml
- config/database.yaml
log:
level: info
include された各 file は同じ schema shape を使えます。相対 include path は、
それを宣言した file から解決されます。最終的な config は通常の confique
schema value です。
主な機能
- recursive include traversal と cycle detection。
- 宣言元 file からの相対 include path resolution。
- environment provider 評価前の
.envloading。 - delimiter splitting を使わない schema-declared environment variables。
- runtime source tracking 向け Figment metadata。
tracingによる TRACE-level source tracking event。- editor completion と基本的な schema check 向け Draft 7 JSON Schema generation。
- application code で
#[config(validate = Self::validate)]として実装し、load_configまたはconfig-validateで実行する field value validation。 - YAML、TOML、JSON、JSON5 template generation。
- generated TOML template の
#:schema、YAML Language Server modeline、 JSON / JSON5 template の$schemafield。 x-tree-splitで mark した nested section の YAML template splitting。- config template、JSON Schema、shell completion 向け built-in clap subcommands。
confiqueを使わない caller 向けの lower-level tree API。
主な入口
多くの application では次の API を使います。
load_config::<S>(path)は最終 schema を読み込みます。load_config_with_figment::<S>(path)は schema を読み込み、source tracking に使う Figment graph も返します。write_config_templates::<S>(config_path, output_path)は root template と recursively discovered child template を書き出します。write_config_schemas::<S>(output_path)は root / section Draft 7 JSON Schema を書き出します。handle_config_command::<Cli, S>(command, config_path)は built-in clap config command を処理します。
confique なしで traversal primitive だけが必要な場合は load_config_tree
を使います。
クイックスタート
English | 中文 | 日本語 | 한국어 | Français | Deutsch | Español | Português | Svenska | Suomi | Nederlands
crate と、application が使う schema/runtime library を追加します。
[dependencies]
rust-config-tree = "0.1"
confique = { version = "0.4", features = ["yaml", "toml", "json5"] }
figment = { version = "0.10", features = ["yaml", "toml", "json", "env"] }
schemars = { version = "1", features = ["derive"] }
serde = { version = "1", features = ["derive"] }
clap = { version = "4", features = ["derive"] }
confique schema を定義し、root type に ConfigSchema を実装します。
#![allow(unused)]
fn main() {
use std::path::PathBuf;
use confique::Config;
use rust_config_tree::ConfigSchema;
#[derive(Debug, Config)]
struct AppConfig {
#[config(default = [])]
include: Vec<PathBuf>,
#[config(nested)]
server: ServerConfig,
}
#[derive(Debug, Config)]
struct ServerConfig {
#[config(default = "127.0.0.1")]
#[config(env = "APP_SERVER_BIND")]
bind: String,
#[config(default = 8080)]
#[config(env = "APP_SERVER_PORT")]
port: u16,
}
impl ConfigSchema for AppConfig {
fn include_paths(layer: &<Self as Config>::Layer) -> Vec<PathBuf> {
layer.include.clone().unwrap_or_default()
}
}
}
config を読み込みます。
#![allow(unused)]
fn main() {
use rust_config_tree::load_config;
let config = load_config::<AppConfig>("config.yaml")?;
println!("{config:#?}");
Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
}
root file は recursive include を持てます。
# config.yaml
include:
- config/server.yaml
# config/server.yaml
server:
bind: 0.0.0.0
port: 3000
default の load_config precedence は次の通りです。
environment variables
> config files, with later merged files overriding earlier files
> confique code defaults
high-level API で includes を読み込む場合、root file が最も高い file priority を持ちます。included files は lower-priority value を提供し、default や section-specific file として使えます。
command-line arguments は application-specific なので、load_config は自動で
読みません。application が config override flag を持つ場合は、
build_config_figment の後に CLI override を merge します。
CLI flag 名は application が選びます。自動的な a.b.c config path では
ありません。--server-port のような通常の clap flag を使い、nested override
structure へ map してください。どの config key を上書きするかは serialized
nested shape が決めます。
#![allow(unused)]
fn main() {
use figment::providers::Serialized;
use serde::Serialize;
use rust_config_tree::{build_config_figment, load_config_from_figment};
#[derive(Debug, Serialize)]
struct CliOverrides {
#[serde(skip_serializing_if = "Option::is_none")]
server: Option<CliServerOverrides>,
}
#[derive(Debug, Serialize)]
struct CliServerOverrides {
#[serde(skip_serializing_if = "Option::is_none")]
port: Option<u16>,
}
let cli_overrides = CliOverrides {
server: Some(CliServerOverrides { port: Some(9000) }),
};
let figment = build_config_figment::<AppConfig>("config.yaml")?
.merge(Serialized::defaults(cli_overrides));
let config = load_config_from_figment::<AppConfig>(&figment)?;
let _ = config;
Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
}
この形で CLI override を merge すると、完全な precedence は次の通りです。
command-line overrides
> environment variables
> config files
> confique code defaults
設定スキーマ
English | 中文 | 日本語 | 한국어 | Français | Deutsch | Español | Português | Svenska | Suomi | Nederlands
application schema は通常の confique config type です。root schema は
ConfigSchema を実装する必要があります。これにより rust-config-tree は
中間 confique layer から recursive include を見つけられます。
#![allow(unused)]
fn main() {
use std::path::PathBuf;
use confique::Config;
use schemars::JsonSchema;
use rust_config_tree::ConfigSchema;
#[derive(Debug, Config, JsonSchema)]
struct AppConfig {
#[config(default = [])]
include: Vec<PathBuf>,
#[config(nested)]
#[schemars(extend("x-tree-split" = true))]
database: DatabaseConfig,
}
#[derive(Debug, Config, JsonSchema)]
struct DatabaseConfig {
#[config(env = "APP_DATABASE_URL")]
url: String,
#[config(default = 16)]
#[config(env = "APP_DATABASE_POOL_SIZE")]
pool_size: u32,
}
impl ConfigSchema for AppConfig {
fn include_paths(layer: &<Self as Config>::Layer) -> Vec<PathBuf> {
layer.include.clone().unwrap_or_default()
}
}
}
Include Field
include field の名前は任意です。rust-config-tree は
ConfigSchema::include_paths を通してのみ include field を知ります。
通常、この field には empty default を付けます。
#![allow(unused)]
fn main() {
#[config(default = [])]
include: Vec<PathBuf>,
}
loader は各 file を partially loaded layer として受け取ります。これにより、 最終 schema の merge / validation より前に child config files を発見できます。
Nested Sections
structured section には #[config(nested)] を使います。nested section は runtime
loading では常に使われます。独立した *.yaml template と
<section>.schema.json schema も生成したい nested field には
#[schemars(extend("x-tree-split" = true))] を追加します。
#![allow(unused)]
fn main() {
#[derive(Debug, Config, JsonSchema)]
struct AppConfig {
#[config(nested)]
#[schemars(extend("x-tree-split" = true))]
server: ServerConfig,
}
}
自然な YAML shape は次の通りです。
server:
bind: 127.0.0.1
port: 8080
環境変数専用フィールド
値を環境変数からだけ渡し、生成される config file には出したくない leaf field には #[schemars(extend("x-env-only" = true))] を付けます。生成される YAML template と JSON Schema は env-only field を省略し、その結果空になった parent object も削除します.
#![allow(unused)]
fn main() {
#[config(env = "APP_SECRET")]
#[schemars(extend("x-env-only" = true))]
secret: String,
}
Field Value Validation
生成された *.schema.json file は IDE 補完と基本的な editor check のための
ものです。具体的な field value が application として合法かどうかは判断しません。
field value validation は code 側で #[config(validate = Self::validate)] として
実装します。final config を load_config で読み込むとき、または
config-validate で確認するときに、この runtime validation が実行されます。
Template Section Overrides
template source に include がない場合、crate は x-tree-split で mark した nested schema section から child
template file を導出できます。default の top-level path は
<section>.yaml です。
template_path_for_section で path を上書きできます。
#![allow(unused)]
fn main() {
impl ConfigSchema for AppConfig {
fn include_paths(layer: &<Self as Config>::Layer) -> Vec<PathBuf> {
layer.include.clone().unwrap_or_default()
}
fn template_path_for_section(section_path: &[&str]) -> Option<PathBuf> {
match section_path {
["database"] => Some(PathBuf::from("examples/database.yaml")),
_ => None,
}
}
}
}
ランタイム読み込み
English | 中文 | 日本語 | 한국어 | Français | Deutsch | Español | Português | Svenska | Suomi | Nederlands
runtime loading は Figment と confique に明確に分割されています。
figment:
runtime file loading
runtime environment loading
runtime source metadata
confique:
schema metadata
defaults
validation
config templates
main API は次の通りです。
#![allow(unused)]
fn main() {
use rust_config_tree::load_config;
let config = load_config::<AppConfig>("config.yaml")?;
Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
}
application が source metadata を必要とする場合は load_config_with_figment
を使います。
#![allow(unused)]
fn main() {
use rust_config_tree::load_config_with_figment;
let (config, figment) = load_config_with_figment::<AppConfig>("config.yaml")?;
let _ = (config, figment);
Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
}
Loading Steps
high-level loader は次の step を実行します。
- root config path を字句的に解決する。
- root config directory から上方向に最初の
.envfile を探して読み込む。 - 各 config file を partial layer として読み込み include を発見する。
- 発見した config files から Figment graph を構築する。
- file より高い priority で
ConfiqueEnvProviderを merge する。 - 必要に応じて application-specific CLI override を merge する。
- Figment から
confiquelayer を extract する。 confiquecode default を適用する。- 最終 schema を validate して構築する。
load_config と load_config_with_figment は step 1-5 と 7-9 を実行します。
step 6 は application-specific です。この crate は CLI flag と schema field の
対応を推測しません。
File Formats
runtime file provider は config path extension から選択されます。
.yamlと.ymlは YAML。.tomlは TOML。.jsonと.json5は JSON。- unknown extension または extension なしは YAML。
template generation は引き続き confique の YAML、TOML、JSON5-compatible template renderer を使います。
Include Priority
high-level loader は、included file が include した file より lower priority に なるように file provider を merge します。root config file は最も高い file priority を持ちます。
environment variables はすべての config file より高い priority を持ちます。
confique default は runtime provider が値を提供しない場合だけ使われます。
build_config_figment の後に CLI override を merge した場合、完全な
precedence は次の通りです。
command-line overrides
> environment variables
> config files
> confique code defaults
command-line syntax は rust-config-tree が定義しません。application が
--server-port を parse し、その値を nested serialized provider に map すれば
server.port を上書きできます。--server.port や a.b.c のような syntax は、
application が実装した場合だけ存在します。
#![allow(unused)]
fn main() {
use figment::providers::Serialized;
use serde::Serialize;
use rust_config_tree::{build_config_figment, load_config_from_figment};
#[derive(Debug, Serialize)]
struct CliOverrides {
#[serde(skip_serializing_if = "Option::is_none")]
server: Option<CliServerOverrides>,
}
#[derive(Debug, Serialize)]
struct CliServerOverrides {
#[serde(skip_serializing_if = "Option::is_none")]
port: Option<u16>,
}
let cli_overrides = CliOverrides {
server: Some(CliServerOverrides { port: Some(9000) }),
};
let figment = build_config_figment::<AppConfig>("config.yaml")?
.merge(Serialized::defaults(cli_overrides));
let config = load_config_from_figment::<AppConfig>(&figment)?;
let _ = config;
Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
}
環境変数
English | 中文 | 日本語 | 한국어 | Français | Deutsch | Español | Português | Svenska | Suomi | Nederlands
environment variable name は schema 内で confique により宣言します。
#![allow(unused)]
fn main() {
#[derive(Debug, Config)]
struct DatabaseConfig {
#[config(env = "APP_DATABASE_URL")]
url: String,
#[config(default = 16)]
#[config(env = "APP_DATABASE_POOL_SIZE")]
pool_size: u32,
}
}
rust-config-tree は confique::Config::META からこれらの名前を読み取り、
各 environment variable を正確な field path へ mapping する Figment provider
を構築します。
この crate の schema では delimiter-based Figment environment mapping を使いません。
#![allow(unused)]
fn main() {
// Do not use this pattern for rust-config-tree schemas.
Env::prefixed("APP_").split("_")
Env::prefixed("APP_").split("__")
}
split("_") は underscore を nested key separator として扱います。そのため
APP_DATABASE_POOL_SIZE は database.pool.size のような path になり、
pool_size のような Rust field name と衝突します。
ConfiqueEnvProvider では mapping は明示的です。
APP_DATABASE_POOL_SIZE -> database.pool_size
single underscore は environment variable name の一部として残ります。Figment は nesting rule を推測しません。
Dotenv Loading
runtime provider を評価する前に、loader は root config file の directory から
上方向に .env file を探します。
既存の process environment variables は保持されます。.env の値は missing
environment variable だけを埋めます。
例:
APP_SERVER_PORT=9000
APP_DATABASE_POOL_SIZE=64
schema が matching #[config(env = "...")] attribute を宣言している場合、
これらの variable は config file value を上書きします。
Parsing Values
bridge provider は Figment に environment value を parse させます。
confique の parse_env hook は呼びません。complex value は、Figment の
environment value syntax が型に十分合う場合を除き、config file に置いてください。
ソース追跡
English | 中文 | 日本語 | 한국어 | Français | Deutsch | Español | Português | Svenska | Suomi | Nederlands
runtime loading に使われた Figment graph を保持するには
load_config_with_figment を使います。
#![allow(unused)]
fn main() {
use rust_config_tree::load_config_with_figment;
let (config, figment) = load_config_with_figment::<AppConfig>("config.yaml")?;
let _ = config;
Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
}
返された Figment value は runtime value の source を問い合わせられます。
#![allow(unused)]
fn main() {
if let Some(metadata) = figment.find_metadata("database.pool_size") {
let source = metadata.interpolate(
&figment::Profile::Default,
&["database", "pool_size"],
);
println!("database.pool_size came from {source}");
}
}
ConfiqueEnvProvider から供給された値の場合、interpolation は schema で宣言
された native environment variable name を返します。
database.pool_size came from APP_DATABASE_POOL_SIZE
TRACE Events
loader は tracing::trace! で source tracking event を出力します。TRACE が
有効な場合だけ出力されます。
#![allow(unused)]
fn main() {
use rust_config_tree::{load_config_with_figment, trace_config_sources};
let (config, figment) = load_config_with_figment::<AppConfig>("config.yaml")?;
// If the tracing subscriber is initialized after config loading, emit the
// same source events again after installing the subscriber.
trace_config_sources::<AppConfig>(&figment);
let _ = config;
Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
}
各 event は rust_config_tree::config target を使い、次を含みます。
config_key: dotted config key。source: rendered source metadata。
confique default だけから来た値には Figment runtime metadata がありません。
その場合は confique default or unset optional field として報告されます。
テンプレート生成
English | 中文 | 日本語 | 한국어 | Français | Deutsch | Español | Português | Svenska | Suomi | Nederlands
template は runtime で使う同じ confique schema から生成されます。実際の
template content は confique が render し、doc comment、default、required
field、declared environment variable name を含みます。
write_config_templates を使います。
#![allow(unused)]
fn main() {
use rust_config_tree::write_config_templates;
write_config_templates::<AppConfig>("config.yaml", "config.example.yaml")?;
Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
}
root config と split nested section の Draft 7 JSON Schema を生成します。
#![allow(unused)]
fn main() {
use rust_config_tree::write_config_schemas;
write_config_schemas::<AppConfig>("schemas/myapp.schema.json")?;
Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
}
nested field を独立した *.yaml template と <section>.schema.json schema として
生成したい場合は #[schemars(extend("x-tree-split" = true))] を付けます。
mark していない nested field は parent template と parent schema に残ります。
#[schemars(extend("x-env-only" = true))] を leaf field に付けると、その値は環境変数からだけ渡すものとして扱われます。生成される template と JSON Schema は env-only field を省略し、その結果空になった parent object も削除します.
generated schemas は required constraint を省略します。IDE は補完を提供
できますが、log.yaml のような partial file で missing root field を
報告しません。root schema は root file に属する field だけを補完し、nested
section field は各 section schema が補完します。present field は type、enum、
unknown property などの基本的な editor check を受けられます。生成された
*.schema.json は具体的な field value が application として合法かどうかを
判断しません。field value validation は code 側で
#[config(validate = Self::validate)] として実装し、load_config または
config-validate で実行します。
generated TOML / YAML / JSON / JSON5 template から schema を bind する場合:
#![allow(unused)]
fn main() {
use rust_config_tree::write_config_templates_with_schema;
write_config_templates_with_schema::<AppConfig>(
"config.toml",
"config.example.toml",
"schemas/myapp.schema.json",
)?;
Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
}
TOML / YAML の root template は root schema に bind され、split child section
field を補完しません。split section YAML template は対応する section schema に
bind されます。JSON / JSON5 template は VS Code が認識できる root $schema
field を受け取ります。VS Code json.schemas は代替の bind 方法として残ります。
output format は output path から推定されます。
.yamlと.ymlは YAML。.tomlは TOML。.jsonと.json5は JSON5-compatible template。- unknown extension または extension なしは YAML。
Schema Bindings
schema path が schemas/myapp.schema.json の場合、generated root template は
次を使います。
#:schema ./schemas/myapp.schema.json
# yaml-language-server: $schema=./schemas/myapp.schema.json
generated section template は section schema を bind します。
# log.yaml
# yaml-language-server: $schema=./schemas/log.schema.json
生成された JSON / JSON5 template は VS Code が認識する root $schema field を書きます。editor settings は任意です:
{
"json.schemas": [
{
"fileMatch": [
"/config.json",
"/config.*.json"
],
"url": "./schemas/myapp.schema.json"
}
]
}
Template Source Selection
template generation は source tree を次の順序で選びます。
- Existing config path。
- Existing output template path。
- 新しい empty template tree として扱う output path。
Mirrored Include Trees
source file が include を宣言している場合、generated template は output directory 下に include path を mirror します。
# config.yaml
include:
- server.yaml
config.example.yaml を生成すると次を書きます。
config.example.yaml
server.yaml
relative include target は output file の parent directory 下に mirror されます。 absolute include target は absolute のままです。
Opt-in Section Splitting
source file に include がない場合、crate は nested schema section から include
target を導出できます。server section を持つ schema では、empty root template
source から次を生成できます。
config.example.yaml
server.yaml
root template は include block を受け取り、server.yaml は server
section だけを含みます。nested section は、その field も x-tree-split を持つ場合だけ recursive splitting されます。
IDE 補完
English | 中文 | 日本語 | 한국어 | Français | Deutsch | Español | Português | Svenska | Suomi | Nederlands
generated JSON Schema は TOML、YAML、JSON、JSON5 config file で使えます。
schema は confique が使う同じ Rust type から生成されます。
#![allow(unused)]
fn main() {
use confique::Config;
use schemars::JsonSchema;
#[derive(Debug, Config, JsonSchema)]
struct AppConfig {
#[config(nested)]
#[schemars(extend("x-tree-split" = true))]
server: ServerConfig,
}
}
生成します。
#![allow(unused)]
fn main() {
use rust_config_tree::write_config_schemas;
write_config_schemas::<AppConfig>("schemas/myapp.schema.json")?;
Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
}
これは root schema と schemas/server.schema.json のような section schema を
書きます。generated schemas は required constraint を省略するため、partial
config file に completion を出しながら missing-field diagnostic を出しません。
root schema は nested section property を省略するため、child section completion
は matching section schema を bind した file でだけ使えます。
x-env-only で mark した field は generated schema から省略されるため、環境変数だけで渡す secret などは IDE 補完に出ません。
IDE schema は補完と基本的な editor check のためのものです。type、enum、
unknown property check など、生成 schema が表せる範囲だけを扱います。
具体的な field value が application として合法かどうかは判断しません。
field value validation は code 側で #[config(validate = Self::validate)] として
実装し、load_config または config-validate で実行します。required field と
final merged config validation もこの runtime path で扱います。
TOML
TOML file は top-of-file #:schema directive で schema を bind します。
#:schema ./schemas/myapp.schema.json
[server]
bind = "0.0.0.0"
port = 3000
TOML で root $schema = "..." field は使わないでください。real config data
になり、runtime deserialization に影響する可能性があります。
write_config_templates_with_schema は TOML template に #:schema directive を
自動追加します。
YAML
YAML file は YAML Language Server modeline を使います。
# yaml-language-server: $schema=./schemas/myapp.schema.json
server:
bind: 0.0.0.0
port: 3000
write_config_templates_with_schema は YAML template にこの modeline を自動追加
します。split YAML template は section schema を bind します。たとえば
log.yaml は ./schemas/log.schema.json を bind します。
JSON
JSON / JSON5 file は root $schema field で schema を bind できます。write_config_templates_with_schema は generated JSON / JSON5 template に自動で追加します。
{
"$schema": "./schemas/myapp.schema.json"
}
file 内 binding を使わない project では editor settings も引き続き使えます。
{
"json.schemas": [
{
"fileMatch": [
"/config.json",
"/config.*.json",
"/deploy/*.json"
],
"url": "./schemas/myapp.schema.json"
}
]
}
YAML も VS Code settings で bind できます。
{
"yaml.schemas": {
"./schemas/myapp.schema.json": [
"config.yaml",
"config.*.yaml",
"deploy/*.yaml"
]
}
}
最終 layout:
schemas/myapp.schema.json:
root file の field のみ
schemas/server.schema.json:
server section schema
config.toml:
#:schema ./schemas/myapp.schema.json
config.yaml:
# yaml-language-server: $schema=./schemas/myapp.schema.json
server.yaml:
# yaml-language-server: $schema=./schemas/server.schema.json
config.json:
"$schema": "./schemas/myapp.schema.json"
References:
CLI 統合
English | 中文 | 日本語 | 한국어 | Français | Deutsch | Español | Português | Svenska | Suomi | Nederlands
ConfigCommand は reusable clap subcommands を提供します。
config-templateconfig-schemaconfig-validatecompletionsinstall-completionsuninstall-completions
これらの built-in subcommands は application-specific config override flags とは 別のものです。config override flags は runtime loading path で Figment provider として merge します。
config override flags は consuming application の CLI に属します。名前は dotted
config path に一致している必要はありません。たとえば application は
--server-port を parse し、それを nested server.port config key に map
できます。CliOverrides に map した flag だけが config value に影響します。
application command enum に flatten します。
- application 自身の
Parsertype を保つ。 - application 自身の
Subcommandenum を保つ。 - その enum に
#[command(flatten)] Config(ConfigCommand)を追加する。 - Clap は flattened
ConfigCommandvariants を application 自身の command と 同じ level に展開する。 Config(command)variant を match し、handle_config_commandに渡す。
use std::path::PathBuf;
use clap::{Parser, Subcommand};
use confique::Config;
use schemars::JsonSchema;
use rust_config_tree::{ConfigCommand, ConfigSchema, handle_config_command, load_config};
#[derive(Debug, Config, JsonSchema)]
struct AppConfig {
#[config(default = [])]
include: Vec<PathBuf>,
}
impl ConfigSchema for AppConfig {
fn include_paths(layer: &<Self as Config>::Layer) -> Vec<PathBuf> {
layer.include.clone().unwrap_or_default()
}
}
#[derive(Debug, Parser)]
#[command(name = "demo")]
struct Cli {
#[arg(long, default_value = "config.yaml")]
config: PathBuf,
#[command(subcommand)]
command: Command,
}
#[derive(Debug, Subcommand)]
enum Command {
Run,
#[command(flatten)]
Config(ConfigCommand),
}
fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let cli = Cli::parse();
match cli.command {
Command::Run => {
let config = load_config::<AppConfig>(&cli.config)?;
println!("{config:#?}");
}
Command::Config(command) => {
handle_config_command::<Cli, AppConfig>(command, &cli.config)?;
}
}
Ok(())
}
Config Templates
demo config-template
この command は config/<root_config_name>/ の下に template を書きます。
--output に path を渡した場合は file name だけを使います。output file name
がない場合は
config/<root_config_name>/<root_config_name>.example.yaml を書きます。
--schema schemas/myapp.schema.json を追加すると、generated TOML / YAML /
JSON / JSON5 template を generated JSON Schema に bind します。split YAML
template は matching section schema を bind します。JSON / JSON5 template は
VS Code が認識する $schema field を受け取ります。この command は root /
section schema も selected schema path に書きます。
demo config-template --output app_config.example.toml --schema schemas/myapp.schema.json
root / section JSON Schema を生成します。
demo config-schema
--output がない場合、config-schema は root schema を
config/<root_config_name>/<root_config_name>.schema.json に書きます。
完全な runtime config tree を validate します。
demo config-validate
generated editor schemas は split file で required-field diagnostic を避けるよう
に作られます。config-validate は includes を読み込み、defaults を適用し、
final confique validation を実行します。これには
#[config(validate = Self::validate)] で宣言した validator も含まれます。
生成された *.schema.json は IDE 補完と基本的な editor check のためのもので、
field value legality は判断しません。成功時は Configuration is ok を出力します。
Shell Completions
completion を stdout に出力します。
demo completions zsh
completion を install します。
demo install-completions zsh
completion を uninstall します。
demo uninstall-completions zsh
installer は Bash、Elvish、Fish、PowerShell、Zsh を support します。completion file を user home directory 以下に書き、必要な shell では startup file も更新 します。
既存の shell startup file、たとえば ~/.zshrc、~/.bashrc、Elvish rc file、
PowerShell profile を変更する前に、command は元ファイルの横に backup を書きます。
<rc-file>.backup.by.<program-name>.<timestamp>
サンプル
English | 中文 | 日本語 | 한국어 | Français | Deutsch | Español | Português | Svenska | Suomi | Nederlands
repository には、config tree loading、CLI overrides、built-in config commands、 template generation、lower-level tree API を扱う実行可能なサンプルが含まれます。
repository examples index:
repository root から実行します。
cargo run --example basic_loading
cargo run --example cli_overrides -- --server-port 9000
cargo run --example config_commands -- config-template
cargo run --example config_commands -- config-schema
cargo run --example config_commands -- config-validate
cargo run --example generate_templates
cargo run --example tree_api
Tree API
English | 中文 | 日本語 | 한국어 | Français | Deutsch | Español | Português | Svenska | Suomi | Nederlands
application が confique を使わない場合、または traversal result へ直接
アクセスしたい場合は lower-level tree API を使います。
#![allow(unused)]
fn main() {
use std::{
fs,
io,
path::{Path, PathBuf},
};
use rust_config_tree::{ConfigSource, load_config_tree};
fn load_source(path: &Path) -> io::Result<ConfigSource<String>> {
let content = fs::read_to_string(path)?;
let includes = content
.lines()
.filter_map(|line| line.strip_prefix("include: "))
.map(PathBuf::from)
.collect();
Ok(ConfigSource::new(content, includes))
}
let tree = load_config_tree("config.yaml", load_source)?;
for node in tree.nodes() {
println!("{}", node.path().display());
}
Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
}
Traversal Rules
tree loader は次を行います。
- source path を字句的に正規化する。
- empty include path を拒否する。
- relative include を宣言元 file から解決する。
- absolute include path を保持する。
- recursive include cycle を検出する。
- 別の include branch で既に読み込まれた file を skip する。
ConfigTreeOptions は sibling include traversal を reverse できます。
#![allow(unused)]
fn main() {
use rust_config_tree::{ConfigTreeOptions, IncludeOrder};
let options = ConfigTreeOptions::default().include_order(IncludeOrder::Reverse);
let _ = options;
}
Path Helpers
path helper は lexical only です。symbolic link を解決せず、path の存在も要求 しません。
absolutize_lexical(path)normalize_lexical(path)resolve_include_path(parent_path, include_path)
GitHub Pages
English | 中文 | 日本語 | 한국어 | Français | Deutsch | Español | Português | Svenska | Suomi | Nederlands
この repository は mdBook と GitHub Pages で manual を publish します。
各 language manual は独立した mdBook project です。各 language はそれぞれ
SUMMARY.md を持つため、left sidebar には current language の page だけが
表示されます。
manual/
en/
book.toml
SUMMARY.md
introduction.md
quick-start.md
...
zh/
book.toml
SUMMARY.md
introduction.md
quick-start.md
...
ja/
book.toml
SUMMARY.md
introduction.md
quick-start.md
...
ko/
fr/
de/
es/
pt/
sv/
fi/
nl/
local build:
scripts/publish-pages.sh
generated site は次に書かれます。
target/mdbook
Publishing Workflow
.github/workflows/pages.yml の workflow は main への push と manual dispatch
で実行されます。
- repository を checkout する。
- mdBook を install する。
scripts/publish-pages.shを実行する。target/mdbookを Pages artifact として upload する。- artifact を GitHub Pages に deploy する。
published URL:
https://developerworks.github.io/rust-config-tree/
Crate Release
commit、push、Pages deploy、crate publish の完全な flow:
scripts/release.sh --execute --message "Release 0.1.3"
repository root から crate release helper を使います。
scripts/publish-crate.sh
default mode は checks と cargo publish --dry-run を実行します。current version
が crates.io に既に存在する場合、script は patch version を自動的に bump
します。checks が通ったあと crates.io に publish します。
scripts/publish-crate.sh --execute
script usage は scripts/README.md にまとめています。