ruby-ucl
Ruby bindings to the libucl library for parsing configuration files written in the Universal Configuration Language (UCL).
UCL is a configuration format inspired by nginx and JSON. It is a superset of JSON, so any valid JSON document is also valid UCL, while adding a more relaxed, human-friendly syntax (unquoted keys, comments, optional commas, multipliers, macros, …).
Parsed configurations are returned as plain Ruby objects (Hash,
Array, String, Integer, Float, true/false, nil), so no
special object model has to be learned.
Installation
gem install ucl
Or add it to your Gemfile:
gem 'ucl'
The extension binds to the native libucl library (version 0.8.2 or later). At build time it is located as follows:
- If a system-wide libucl is found (via
pkg-config, or under/optor/usr/local), it is used. - Otherwise libucl is downloaded and compiled from source automatically
(using mini_portile2 and CMake). This requires
cmakeand a C compiler to be available.
You can force the source build regardless of any system installation:
gem install ucl -- --enable-vendor-libucl
# or, with Bundler:
bundle config set build.ucl --enable-vendor-libucl
Debian/Ubuntu note: do not
apt install libucl-dev. That package is an unrelated UCL data-compression library that merely shares the name — it does not provideucl_parser_new. Since the configuration parser is not packaged for Debian, just installcmakeand a compiler and let the gem build libucl from source. (The parser is packaged on Fedora, Homebrew and FreeBSD ports aslibucl.)
Usage
require 'ucl'
# Parse a string of UCL data
UCL.parse(File.read('foo.conf'))
# Parse a file directly (enables file-relative variables such as $FILENAME)
UCL.load_file('foo.conf')
# Pass flags explicitly (combine them with a bitwise OR)
UCL.load_file('foo.conf', UCL::KEY_SYMBOL | UCL::KEY_LOWERCASE)
# Or set the default flags applied to every subsequent call
UCL.flags = UCL::KEY_SYMBOL
UCL.parse('name = value') #=> { :name => "value" }
Both parse and load_file accept an optional flags argument. When it
is omitted, the value of UCL.flags (default: no flag) is used.
On a malformed configuration, or if conversion of the parsed tree fails,
a UCL::Error is raised.
Given a configuration like:
# a sample configuration
name = example
timeout = 30s # parsed as a number of seconds
max_size = 10mb # size multipliers are understood
servers = [
{ host = a.example, port = 8080 },
{ host = b.example, port = 8081 },
]
logging {
level = info
enabled = yes
}
UCL.load_file returns:
{
"name" => "example",
"timeout" => 30.0,
"max_size" => 10485760,
"servers" => [ { "host" => "a.example", "port" => 8080 },
{ "host" => "b.example", "port" => 8081 } ],
"logging" => { "level" => "info", "enabled" => true },
}
Flags
| Flag | Effect |
|---|---|
KEY_SYMBOL |
Return object keys as Symbol instead of String. |
KEY_LOWERCASE |
Convert all keys to lower case. |
NO_TIME |
Do not parse time values; keep them as strings. |
DISABLE_MACRO |
Disable processing of macros (e.g. .include). |
NO_FILEVARS |
Do not predefine $FILENAME / $CURDIR (affects parse; load_file still sets them from the file). |
Type mapping
| UCL type | Ruby type |
|---|---|
| object | Hash |
| array | Array |
| string | String |
| integer | Integer |
| float | Float |
| time | Float (seconds) |
| boolean | true / false |
| null | nil |
Notes:
- The parser uses explicit (not implicit) arrays, so a key repeated several
times is collected into an
Arrayof its values:
UCL.parse("a = 1\na = 2") #=> { "a" => [1, 2] }
UCL.parse("a = 1") #=> { "a" => 1 }
Integers understand size multipliers (
1k→ 1000,1kb→ 1024,1mb→ 1048576), hexadecimal (0x1f→ 31) and JSON is accepted as-is.Returned strings carry their verbatim bytes but are tagged with the
ASCII-8BIT(binary) encoding; callString#force_encoding('UTF-8')if you need them as UTF-8.
Development
bundle install # install development dependencies
rake compile # build the C extension into ext/
rake test # compile and run the test suite
rake clobber # remove all generated files
rake test works with the development gems installed system-wide too; with
a Gemfile.lock present, prefix commands with bundle exec.
License
Released under the MIT License. See LICENSE.