toml-rb-hs 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
[](http://badge.fury.io/rb/toml-rb)
|
5
|
+
[](https://travis-ci.org/emancu/toml-rb)
|
6
|
+
[](https://codeclimate.com/github/emancu/toml-rb)
|
7
|
+
[](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
|