toml-rb-hs 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/README.md +101 -0
- data/Rakefile +6 -0
- data/lib/toml-rb.rb +106 -0
- data/lib/toml-rb/array.rb +14 -0
- data/lib/toml-rb/dumper.rb +103 -0
- data/lib/toml-rb/errors.rb +17 -0
- data/lib/toml-rb/grammars/array.citrus +39 -0
- data/lib/toml-rb/grammars/document.citrus +40 -0
- data/lib/toml-rb/grammars/helper.citrus +17 -0
- data/lib/toml-rb/grammars/primitive.citrus +119 -0
- data/lib/toml-rb/inline_table.rb +72 -0
- data/lib/toml-rb/keygroup.rb +41 -0
- data/lib/toml-rb/keyvalue.rb +49 -0
- data/lib/toml-rb/parser.rb +36 -0
- data/lib/toml-rb/string.rb +68 -0
- data/lib/toml-rb/table_array.rb +50 -0
- data/test/dumper_test.rb +100 -0
- data/test/errors_test.rb +94 -0
- data/test/example-v0.4.0.toml +244 -0
- data/test/example.toml +49 -0
- data/test/grammar_test.rb +246 -0
- data/test/hard_example.toml +46 -0
- data/test/helper.rb +8 -0
- data/test/toml_examples.rb +203 -0
- data/test/toml_test.rb +131 -0
- data/toml-rb-hs.gemspec +24 -0
- metadata +142 -0
- metadata.gz.sig +1 -0
data.tar.gz.sig
ADDED
Binary file
|
data/README.md
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
toml-rb
|
2
|
+
=======
|
3
|
+
|
4
|
+
[![Gem Version](https://badge.fury.io/rb/toml-rb.svg)](http://badge.fury.io/rb/toml-rb)
|
5
|
+
[![Build Status](https://travis-ci.org/emancu/toml-rb.svg)](https://travis-ci.org/emancu/toml-rb)
|
6
|
+
[![Code Climate](https://codeclimate.com/github/emancu/toml-rb/badges/gpa.svg)](https://codeclimate.com/github/emancu/toml-rb)
|
7
|
+
[![Dependency Status](https://gemnasium.com/emancu/toml-rb.svg)](https://gemnasium.com/emancu/toml-rb)
|
8
|
+
|
9
|
+
A [TomlRB](https://github.com/toml-lang/toml) parser using [Citrus](http://mjackson.github.io/citrus) library.
|
10
|
+
|
11
|
+
TomlRB specs supported: `0.4.0`
|
12
|
+
|
13
|
+
Installation
|
14
|
+
------------
|
15
|
+
|
16
|
+
$ gem install toml-rb
|
17
|
+
|
18
|
+
Parser Usage
|
19
|
+
------------
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
require 'toml-rb'
|
23
|
+
|
24
|
+
# From a file!
|
25
|
+
path = File.join(File.dirname(__FILE__), 'path', 'to', 'file')
|
26
|
+
TomlRB.load_file(path)
|
27
|
+
|
28
|
+
# From a stream!
|
29
|
+
stream = <<-EOS
|
30
|
+
title = "wow!"
|
31
|
+
|
32
|
+
[awesome]
|
33
|
+
you = true
|
34
|
+
others = false
|
35
|
+
EOS
|
36
|
+
TomlRB.parse(stream)
|
37
|
+
# => {"title"=>"wow!", "awesome"=>{"you"=>true, "others"=>false}}
|
38
|
+
|
39
|
+
# You want symbols as your keys? No problem!
|
40
|
+
TomlRB.load_file(path, symbolize_keys: true)
|
41
|
+
# Works the same for TomlRB.parse
|
42
|
+
```
|
43
|
+
|
44
|
+
Dumper Usage
|
45
|
+
------------
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
require 'toml-rb'
|
49
|
+
|
50
|
+
# Simple example
|
51
|
+
TomlRB.dump( simple: true)
|
52
|
+
# => "simple = true\n"
|
53
|
+
|
54
|
+
|
55
|
+
# Complex example
|
56
|
+
hash = {
|
57
|
+
"title"=>"wow!",
|
58
|
+
"awesome"=> {
|
59
|
+
"you"=>true,
|
60
|
+
"others"=>false
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
TomlRB.dump(hash)
|
65
|
+
# => "title = \"wow!\"\n[awesome]\nothers = false\nyou = true\n"
|
66
|
+
```
|
67
|
+
|
68
|
+
Contributing
|
69
|
+
------------
|
70
|
+
|
71
|
+
1. Fork it
|
72
|
+
2. Bundle it `$ dep install` (install [dep](https://github.com/cyx/dep) if you don't have it)
|
73
|
+
3. Create your feature branch `git checkout -b my-new-feature`
|
74
|
+
4. Add tests and commit your changes `git commit -am 'Add some feature'`
|
75
|
+
5. Run tests `$ rake`
|
76
|
+
6. Push the branch `git push origin my-new-feature`
|
77
|
+
7. Create new Pull Request
|
78
|
+
|
79
|
+
License
|
80
|
+
-------
|
81
|
+
|
82
|
+
MIT License
|
83
|
+
|
84
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
85
|
+
a copy of this software and associated documentation files (the
|
86
|
+
"Software"), to deal in the Software without restriction, including
|
87
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
88
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
89
|
+
permit persons to whom the Software is furnished to do so, subject to
|
90
|
+
the following conditions:
|
91
|
+
|
92
|
+
The above copyright notice and this permission notice shall be
|
93
|
+
included in all copies or substantial portions of the Software.
|
94
|
+
|
95
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
96
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
97
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
98
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
99
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
100
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
101
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
data/lib/toml-rb.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'citrus'
|
2
|
+
|
3
|
+
unless defined? require_relative
|
4
|
+
def require_relative(path)
|
5
|
+
require path
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
require_relative "toml-rb/errors"
|
10
|
+
require_relative "toml-rb/array"
|
11
|
+
require_relative "toml-rb/string"
|
12
|
+
require_relative "toml-rb/table_array"
|
13
|
+
require_relative "toml-rb/inline_table"
|
14
|
+
require_relative "toml-rb/keyvalue"
|
15
|
+
require_relative "toml-rb/keygroup"
|
16
|
+
require_relative "toml-rb/parser"
|
17
|
+
require_relative "toml-rb/dumper"
|
18
|
+
|
19
|
+
ROOT = File.dirname(File.expand_path(__FILE__))
|
20
|
+
Citrus.load "#{ROOT}/toml-rb/grammars/helper.citrus"
|
21
|
+
Citrus.load "#{ROOT}/toml-rb/grammars/primitive.citrus"
|
22
|
+
Citrus.load "#{ROOT}/toml-rb/grammars/array.citrus"
|
23
|
+
Citrus.load "#{ROOT}/toml-rb/grammars/document.citrus"
|
24
|
+
|
25
|
+
module TomlRB
|
26
|
+
# Public: Returns a hash from *TomlRB* content.
|
27
|
+
#
|
28
|
+
# content - TomlRB string to be parsed.
|
29
|
+
# options - The Hash options used to refine the parser (default: {}):
|
30
|
+
# :symbolize_keys - true|false (optional).
|
31
|
+
#
|
32
|
+
#
|
33
|
+
# Examples
|
34
|
+
#
|
35
|
+
# TomlRB.parse('[group]')
|
36
|
+
# # => {"group"=>{}}
|
37
|
+
#
|
38
|
+
# TomlRB.parse('title = "TomlRB parser"')
|
39
|
+
# # => {"title"=>"TomlRB parser"}
|
40
|
+
#
|
41
|
+
# TomlRB.parse('[group]', symbolize_keys: true)
|
42
|
+
# # => {group: {}}
|
43
|
+
#
|
44
|
+
# TomlRB.parse('title = "TomlRB parser"', symbolize_keys: true)
|
45
|
+
# # => {title: "TomlRB parser"}
|
46
|
+
#
|
47
|
+
#
|
48
|
+
# Returns a Ruby hash representation of the content according to TomlRB spec.
|
49
|
+
# Raises ValueOverwriteError if a key is overwritten.
|
50
|
+
# Raises ParseError if the content has invalid TomlRB.
|
51
|
+
def self.parse(content, options = {})
|
52
|
+
Parser.new(content, options).hash
|
53
|
+
end
|
54
|
+
|
55
|
+
# Public: Returns a hash from a *TomlRB* file.
|
56
|
+
#
|
57
|
+
# path - TomlRB File path
|
58
|
+
# options - The Hash options used to refine the parser (default: {}):
|
59
|
+
# :symbolize_keys - true|false (optional).
|
60
|
+
#
|
61
|
+
#
|
62
|
+
# Examples
|
63
|
+
#
|
64
|
+
# TomlRB.load_file('/tmp/simple.toml')
|
65
|
+
# # => {"group"=>{}}
|
66
|
+
#
|
67
|
+
# TomlRB.load_file('/tmp/simple.toml', symbolize_keys: true)
|
68
|
+
# # => {group: {}}
|
69
|
+
#
|
70
|
+
#
|
71
|
+
# Returns a Ruby hash representation of the content.
|
72
|
+
# Raises ValueOverwriteError if a key is overwritten.
|
73
|
+
# Raises ParseError if the content has invalid TomlRB.
|
74
|
+
# Raises Errno::ENOENT if the file cannot be found.
|
75
|
+
# Raises Errno::EACCES if the file cannot be accessed.
|
76
|
+
def self.load_file(path, options = {})
|
77
|
+
TomlRB.parse(File.read(path), options)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Public: Returns a *TomlRB* string from a Ruby Hash.
|
81
|
+
#
|
82
|
+
# hash - Ruby Hash to be dumped into *TomlRB*
|
83
|
+
#
|
84
|
+
#
|
85
|
+
# Examples
|
86
|
+
#
|
87
|
+
# TomlRB.dump(title: 'TomlRB dump')
|
88
|
+
# # => "simple = true\n"
|
89
|
+
#
|
90
|
+
# hash = {
|
91
|
+
# "title"=>"wow!",
|
92
|
+
# "awesome"=> {
|
93
|
+
# "you"=>true,
|
94
|
+
# "others"=>false
|
95
|
+
# }
|
96
|
+
# }
|
97
|
+
#
|
98
|
+
# TomlRB.dump(hash)
|
99
|
+
# # => "title = \"wow!\"\n[awesome]\nothers = false\nyou = true\n"
|
100
|
+
#
|
101
|
+
#
|
102
|
+
# Returns a TomlRB string representing the hash.
|
103
|
+
def self.dump(hash)
|
104
|
+
Dumper.new(hash).toml_str
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module TomlRB
|
2
|
+
class Dumper
|
3
|
+
attr_reader :toml_str
|
4
|
+
|
5
|
+
def initialize(hash)
|
6
|
+
@toml_str = ''
|
7
|
+
|
8
|
+
visit(hash, [])
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def visit(hash, prefix, extra_brackets = false)
|
14
|
+
simple_pairs, nested_pairs, table_array_pairs = sort_pairs hash
|
15
|
+
|
16
|
+
if prefix.any? && (simple_pairs.any? || hash.empty?)
|
17
|
+
print_prefix prefix, extra_brackets
|
18
|
+
end
|
19
|
+
|
20
|
+
dump_pairs simple_pairs, nested_pairs, table_array_pairs, prefix
|
21
|
+
end
|
22
|
+
|
23
|
+
def sort_pairs(hash)
|
24
|
+
nested_pairs = []
|
25
|
+
simple_pairs = []
|
26
|
+
table_array_pairs = []
|
27
|
+
|
28
|
+
hash.keys.sort.each do |key|
|
29
|
+
val = hash[key]
|
30
|
+
element = [key, val]
|
31
|
+
|
32
|
+
if val.is_a? Hash
|
33
|
+
nested_pairs << element
|
34
|
+
elsif val.is_a?(Array) && val.first.is_a?(Hash)
|
35
|
+
table_array_pairs << element
|
36
|
+
else
|
37
|
+
simple_pairs << element
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
[simple_pairs, nested_pairs, table_array_pairs]
|
42
|
+
end
|
43
|
+
|
44
|
+
def dump_pairs(simple, nested, table_array, prefix = [])
|
45
|
+
# First add simple pairs, under the prefix
|
46
|
+
dump_simple_pairs simple
|
47
|
+
dump_nested_pairs nested, prefix
|
48
|
+
dump_table_array_pairs table_array, prefix
|
49
|
+
end
|
50
|
+
|
51
|
+
def dump_simple_pairs(simple_pairs)
|
52
|
+
simple_pairs.each do |key, val|
|
53
|
+
key = quote_key(key) unless bare_key? key
|
54
|
+
@toml_str << "#{key} = #{to_toml(val)}\n"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def dump_nested_pairs(nested_pairs, prefix)
|
59
|
+
nested_pairs.each do |key, val|
|
60
|
+
key = quote_key(key) unless bare_key? key
|
61
|
+
|
62
|
+
visit val, prefix + [key], false
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def dump_table_array_pairs(table_array_pairs, prefix)
|
67
|
+
table_array_pairs.each do |key, val|
|
68
|
+
key = quote_key(key) unless bare_key? key
|
69
|
+
aux_prefix = prefix + [key]
|
70
|
+
|
71
|
+
val.each do |child|
|
72
|
+
print_prefix aux_prefix, true
|
73
|
+
args = sort_pairs(child) << aux_prefix
|
74
|
+
|
75
|
+
dump_pairs(*args)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def print_prefix(prefix, extra_brackets = false)
|
81
|
+
new_prefix = prefix.join('.')
|
82
|
+
new_prefix = '[' + new_prefix + ']' if extra_brackets
|
83
|
+
|
84
|
+
@toml_str += "[" + new_prefix + "]\n"
|
85
|
+
end
|
86
|
+
|
87
|
+
def to_toml(obj)
|
88
|
+
if obj.is_a? Time
|
89
|
+
obj.strftime('%Y-%m-%dT%H:%M:%SZ')
|
90
|
+
else
|
91
|
+
obj.inspect
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def bare_key?(key)
|
96
|
+
!!key.to_s.match(/^[a-zA-Z0-9_-]*$/)
|
97
|
+
end
|
98
|
+
|
99
|
+
def quote_key(key)
|
100
|
+
'"' + key.gsub('"', '\\"') + '"'
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module TomlRB
|
2
|
+
# Parent class for all TomlRB errors
|
3
|
+
Error = Class.new(StandardError)
|
4
|
+
|
5
|
+
# Error related to parsing.
|
6
|
+
ParseError = Class.new(Error)
|
7
|
+
|
8
|
+
# Overwrite error
|
9
|
+
class ValueOverwriteError < Error
|
10
|
+
attr_accessor :key
|
11
|
+
|
12
|
+
def initialize(key)
|
13
|
+
@key = key
|
14
|
+
super "Key #{key.inspect} is defined more than once"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
grammar TomlRB::Arrays
|
2
|
+
include TomlRB::Primitive
|
3
|
+
|
4
|
+
rule array
|
5
|
+
("[" array_comments (elements)? space ","? array_comments "]" indent?) <TomlRB::ArrayParser>
|
6
|
+
end
|
7
|
+
|
8
|
+
rule array_comments
|
9
|
+
(indent? comment* indent?)
|
10
|
+
end
|
11
|
+
|
12
|
+
rule elements
|
13
|
+
float_array | string_array | array_array | integer_array | datetime_array | bool_array
|
14
|
+
end
|
15
|
+
|
16
|
+
rule float_array
|
17
|
+
((exponent | float) (space "," array_comments (exponent | float))*)
|
18
|
+
end
|
19
|
+
|
20
|
+
rule string_array
|
21
|
+
(string (space "," array_comments string)*)
|
22
|
+
end
|
23
|
+
|
24
|
+
rule array_array
|
25
|
+
(array (space "," array_comments array)*)
|
26
|
+
end
|
27
|
+
|
28
|
+
rule integer_array
|
29
|
+
(integer (space "," array_comments integer)*)
|
30
|
+
end
|
31
|
+
|
32
|
+
rule datetime_array
|
33
|
+
(datetime (space "," array_comments datetime)*)
|
34
|
+
end
|
35
|
+
|
36
|
+
rule bool_array
|
37
|
+
(bool (space "," array_comments bool)*)
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
grammar TomlRB::Document
|
2
|
+
include TomlRB::Primitive
|
3
|
+
include TomlRB::Arrays
|
4
|
+
|
5
|
+
rule document
|
6
|
+
(comment | table_array | keygroup | keyvalue | line_break)*
|
7
|
+
end
|
8
|
+
|
9
|
+
rule table_array
|
10
|
+
(space? '[[' stripped_key ("." stripped_key)* ']]' comment?) <TomlRB::TableArrayParser>
|
11
|
+
end
|
12
|
+
|
13
|
+
rule keygroup
|
14
|
+
(space? '[' stripped_key ("." stripped_key)* ']' comment?) <TomlRB::KeygroupParser>
|
15
|
+
end
|
16
|
+
|
17
|
+
rule keyvalue
|
18
|
+
(stripped_key '=' space? v:(toml_values) comment?) <TomlRB::KeyvalueParser>
|
19
|
+
end
|
20
|
+
|
21
|
+
rule inline_table
|
22
|
+
(space? '{' (keyvalue (',' keyvalue)*)? space? '}' ) <TomlRB::InlineTableParser>
|
23
|
+
end
|
24
|
+
|
25
|
+
rule inline_table_array
|
26
|
+
("[" array_comments inline_table_array_elements space ","? array_comments "]" indent?) <TomlRB::InlineTableArrayParser>
|
27
|
+
end
|
28
|
+
|
29
|
+
rule inline_table_array_elements
|
30
|
+
(inline_table (space "," array_comments inline_table)*)
|
31
|
+
end
|
32
|
+
|
33
|
+
rule toml_values
|
34
|
+
primitive | inline_table | array | inline_table_array
|
35
|
+
end
|
36
|
+
|
37
|
+
rule stripped_key
|
38
|
+
(space? key space?) { captures[:key].first.value }
|
39
|
+
end
|
40
|
+
end
|