1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
//! Loads YAML configuration files (.yaml/.yml) into a structure for easy usage.
//!
//! # Basic usage:
//!
//! ```rust
//! #[macro_use]
//! extern crate amethyst_config;
//!
//! use amethyst_config::Element;
//! use std::path::Path;
//!
//! config! {
//!     struct MyConfig {
//!         pub amount: i32 = 50,
//!     }
//! }
//!
//! fn main() {
//!     let config = MyConfig::default();
//!     assert_eq!(config.amount, 50);
//! }
//! ```
//!
//! `Config` is the name of the rust struct that will be generated by the macro.
//! It can be anything as long as it would be a valid struct in its context,
//! e.g. no other structs by the same name.
//!
//! The inner fields of `Config` can be summed up as:
//!
//! ```ignore rust
//! name: type = default,
//! ```
//!
//! The field name will be looked up when attempting to load from a .yml/.yaml
//! file. If it is found, then the value will be converted from a YAML type to
//! a Rust type and assigned to the field.
//!
//! If a field is missing from the config file or has a value of a wrong type,
//! the Rust field will fall back to the `default` value.
//!
//! In addition to basic types, any struct created through the `config!` macro
//! will automatically implement the [`Element`](trait.Element.html) trait,
//! meaning you can nest configuration structs inside each other like so:
//!
//! ```rust
//! # #[macro_use] extern crate amethyst_config;
//! # use amethyst_config::Element;
//! # use std::path::Path;
//!
//! config! {
//!     struct NestedConfig {
//!         pub some_field: [i64; 3] = [1, 2, 3],
//!     }
//! }
//!
//! config! {
//!     struct Config {
//!         pub nested: NestedConfig = NestedConfig::default(),
//!     }
//! }
//! # fn main() { }
//! ```
//!
//! # External YAML files
//!
//! In the event that a config file is getting too long, you may define it in
//! the YAML file as an "extern" field. For example:
//!
//! ```yaml
//! display: "extern"
//! ```
//!
//! This works similarly to Rust's module system. It will first search for
//! "\\display\\config.yml" in the current context. If it cannot find it, then
//! it will look for "\\display.yml". If it cannot find either of these, then
//! the value will be defaulted in addition to `display` being overwritten if
//! you called `write_file()`.
//!
//! # Enums
//!
//! When `config!` is used on an enum type, it automatically implements the
//! `Element` trait. However, it does not provide possibilities for data holding
//! enums, only simple options list enums.
//!
//! ```rust
//! # #[macro_use] extern crate amethyst_config;
//! # use amethyst_config::Element;
//! # use std::path::Path;
//! config! {
//!     enum EnumName {
//!         Option1,
//!         Option2,
//!     }
//! }
//!
//! config! {
//!     struct Config {
//!         pub field: EnumName = EnumName::Option2,
//!     }
//! }
//!
//! fn main() {
//!     let config = Config::default();
//!     assert_eq!(config.field, EnumName::Option2);
//! }
//! ```
//!
//! # Documentation and commenting
//!
//! Normally when constructing a config, you might add a small description as to
//! what the fields will be used for and possibly their default values, if they
//! have any.
//!
//! ```rust
//! # #[macro_use]
//! # extern crate amethyst_config;
//! #
//! # use amethyst_config::Element;
//! # use std::path::Path;
//! config! {
//!     struct Config {
//!         /// Width and height of the window on initialization. Defaults to
//!         /// 1024x768.
//!         pub dimensions: [u16; 2] = [1024, 768],
//!     }
//! }
//! # fn main() { }
//! ```
//!
//! If the macro has problems expanding, then you may want to check whether you
//! have the documentation on the line before the field and that you have the
//! `pub` identifier before the field name.

#![crate_name = "amethyst_config"]
#![crate_type = "lib"]
#![doc(html_logo_url = "http://tinyurl.com/hgsb45k")]

extern crate yaml_rust;

#[macro_use]
mod definitions;
mod yaml;

use std::path::Path;

pub use definitions::{ConfigMeta, ConfigError};
pub use yaml::{Element, to_string};
pub use yaml_rust::Yaml;

config! {
    struct DisplayConfig {
        pub title: String = "Amethyst game".to_string(),
        pub brightness: f64 = 1.0,
        pub fullscreen: bool = false,
        pub dimensions: (u16, u16) = (1024, 768),
        pub min_dimensions: Option<(u16, u16)> = None,
        pub max_dimensions: Option<(u16, u16)> = None,
        pub vsync: bool = true,
        pub multisampling: u16 = 0,
        pub visibility: bool = true,
    }
}

config! {
    struct LoggingConfig {
        pub file_path: String = "new_project.log".to_string(),
        pub output_level: String = "warn".to_string(),
        pub logging_level: String = "debug".to_string(),
    }
}

config! {
    struct Config {
        /// Configuration for display and graphics
        pub display: DisplayConfig = DisplayConfig::default(),
        /// Configuration for output
        pub logging: LoggingConfig = LoggingConfig::default(),
    }
}