class Bindgen::ConfigReader::Parser
- Bindgen::ConfigReader::Parser
- YAML::Nodes::Parser
- YAML::Parser
- Reference
- Object
Overview
Pull parser for YAML configuration files, offering conditional branches and access to external dependencies.
If you want to read a configuration see ConfigReader.from_yaml
.
This is done by hooking into the pull parser, manually checking for the conditional fields, and applying them accordingly.
Apart from this logic, the configuration file is still valid YAML.
Note: Conditionals and dependencies are only supported in
mappings (Hash
in Crystal). Any such syntax encountered in something
other than a mapping will not trigger any special behaviour.
Condition syntax
YAML documents can define conditional parts in mappings by having a conditional key, with mapping value. If the condition matches, the mapping value will be transparently embedded. If it does not match, the value will be transparently skipped.
Condition keys look like if_X
or elsif_X
or else
. X
is the
condition, and it looks like Y_is_Z
or Y_match_Z
. You can also use
(one or more) spaces () instead of exactly one underscore (
_
) to
separate the words.
Y_is_Z
is true if the variable Y equals Z case-sensitively.Y_isnt_Z
is true if the variable Y doesn't equal Z case-sensitively.Y_match_Z
is true if the variable Y is matched by the regular expression inZ
. The regular expression is created case-sensitively.Y_newer_or_Z
is true when variable Y is newer or equals (>=) to Z, variables are treated as versions.Y_older_or_Z
is true when variable Y is older or equals (<=) to Z, variables are treated as versions.
A condition block is opened by the first if
. Later condition keys can
use elsif
or else
(or if
to open a new condition block).
Note: elsif
or else
without an if
will raise an exception.
Their behaviour is like in Crystal: if
starts a condition block, elsif
starts an alternative condition block, and else
is used if none of if
or
elsif
matched. It's possible to mix condition key-values with normal
key-values.
Note: Conditions can be used in every mapping, even in mappings of a conditional. Each mapping acts as its own scope.
Variables
Variables are set by the user of the class (Probably through
ConfigReader.from_yaml
). All variable values are strings.
Variable names are case-sensitive. A missing variable will be treated
as having an empty value (""
).
Examples
foo: # A normal mapping
bar: 1
# A condition: Matches if `platform` equals "arm".
if_platform_is_arm: # In Crystal: `if platform == "arm"`
company: ARM et al
# You can mix in values between conditionals. It won't "break" following
# elsif or else blocks.
not_a_condition: Hello
# An elsif: Matches if 1) the previous conditions didn't match
# 2) its own condition matches.
elsif_platform_match_x86: # In Crystal: `elsif platform =~ /x86/`
company: Many different
# An else: Matches if all previous conditions didn't match.
else:
company: No idea
# At any time, you can start a new if sequence.
"if today is friday": # You can use spaces instead of underscores too
hooray: true
Dependencies
To modularize the configuration, you can require ("merge") external yaml files from within your configuration.
This is triggered by using a key named <<
, and writing the file name as
value: <<: my_dependency.yml
. The file-extension can also be omitted:
<<: my_dependency
in which case an .yml
extension is assumed.
The dependency path is relative to the currently processed YAML file.
You can also require multiple dependencies into the same mapping:
types:
Something: true # You can mix dependencies with normal fields.
<<: simple_types.yml
<<: complex_types.yml
<<: ignores.yml
The dependency will be embedded into the open mapping: It's transparent to the client code.
It's perfectly possible to mix conditionals with dependencies:
if_os_is_windows:
<<: windows-specific.yml
Errors
An exception will be raised if any of the following occur:
- The maximum dependency depth of
10
(MAX_DEPTH
) is exceeded. - The dependency name contains a dot:
../foo.yml
won't work. - The dependency name is absolute:
/foo/bar.yml
won't work.
Defined in:
bindgen/config_reader/parser.crConstant Summary
-
MAX_DEPTH =
10
-
Maximum dependency load depth.
Constructors
Class Method Summary
-
.loader : Loader
Default loader for dependencies.
-
.loader=(loader : Loader)
Default loader for dependencies.
Instance Method Summary
-
#depth : Int32
Parser depth, bounded by
MAX_DEPTH
-
#evaluator : ConditionEvaluator
Evaluator for conditionals.
-
#loader : Loader
Instance local loader
-
#path : String
Path to the root YAML file.