nestedtext 0.1.0
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.
- checksums.yaml +7 -0
- data/.editorconfig +24 -0
- data/.gitignore +19 -0
- data/.rubocop.yml +143 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +12 -0
- data/CONTRIBUTING.md +4 -0
- data/Gemfile +31 -0
- data/LICENSE.txt +21 -0
- data/OSSMETADATA +1 -0
- data/README.md +113 -0
- data/SECURITY.md +12 -0
- data/lib/nestedtext/constants.rb +5 -0
- data/lib/nestedtext/core_ext.rb +18 -0
- data/lib/nestedtext/decode.rb +33 -0
- data/lib/nestedtext/dumper.rb +177 -0
- data/lib/nestedtext/encode.rb +35 -0
- data/lib/nestedtext/encode_helpers.rb +24 -0
- data/lib/nestedtext/errors.rb +262 -0
- data/lib/nestedtext/helpers.rb +7 -0
- data/lib/nestedtext/parser.rb +287 -0
- data/lib/nestedtext/scanners.rb +161 -0
- data/lib/nestedtext/version.rb +5 -0
- data/lib/nestedtext.rb +8 -0
- data/nestedtext.gemspec +27 -0
- metadata +77 -0
@@ -0,0 +1,161 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "nestedtext/errors"
|
4
|
+
|
5
|
+
module NestedText
|
6
|
+
class LineScanner
|
7
|
+
def initialize(io)
|
8
|
+
@io = io
|
9
|
+
@next_line = nil
|
10
|
+
prepare_next_line
|
11
|
+
end
|
12
|
+
|
13
|
+
def empty?
|
14
|
+
@next_line.nil?
|
15
|
+
end
|
16
|
+
|
17
|
+
def read_next
|
18
|
+
raise Errors::LineScannerIsEmpty if empty?
|
19
|
+
|
20
|
+
line = @next_line
|
21
|
+
prepare_next_line
|
22
|
+
line.prev.prev = nil unless line.prev.nil? # GC: break the chain
|
23
|
+
line
|
24
|
+
end
|
25
|
+
|
26
|
+
def peek
|
27
|
+
@next_line
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def prepare_next_line
|
33
|
+
line = nil
|
34
|
+
loop do
|
35
|
+
linestr = @io.gets&.chomp
|
36
|
+
lineno = @io.lineno - 1 # Be 0-based
|
37
|
+
line = linestr.nil? ? nil : Line.new(linestr, lineno, @next_line)
|
38
|
+
break if line.nil? || !%i[blank comment].include?(line.tag)
|
39
|
+
end
|
40
|
+
@next_line = line
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class InlineScanner
|
45
|
+
attr_reader :line, :pos
|
46
|
+
|
47
|
+
def initialize(line)
|
48
|
+
@line = line
|
49
|
+
@pos = 0
|
50
|
+
end
|
51
|
+
|
52
|
+
def empty?
|
53
|
+
@pos >= @line.content.length
|
54
|
+
end
|
55
|
+
|
56
|
+
def remaining
|
57
|
+
@line.content[@pos..]
|
58
|
+
end
|
59
|
+
|
60
|
+
def read_next
|
61
|
+
raise Errors::InlineScannerIsEmpty if empty?
|
62
|
+
|
63
|
+
@pos += 1
|
64
|
+
@line.content[@pos - 1]
|
65
|
+
end
|
66
|
+
|
67
|
+
def peek
|
68
|
+
empty? ? nil : @line.content[@pos]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class Line
|
73
|
+
# Reference: https://nestedtext.org/en/latest/file_format.html
|
74
|
+
ALLOWED_LINE_TAGS = [
|
75
|
+
:comment, # a comment
|
76
|
+
:blank,
|
77
|
+
:list_item, # - item
|
78
|
+
:dict_item, # key: value (or value on next line)
|
79
|
+
:string_item, # > a string, can continue next line
|
80
|
+
:key_item, # : key on a line
|
81
|
+
:inline_dict, # {key1: value1, key2: value2}
|
82
|
+
:inline_list, # [value1, value2]
|
83
|
+
:unrecognized # could not be determined
|
84
|
+
]
|
85
|
+
|
86
|
+
attr_accessor :prev
|
87
|
+
attr_reader :tag, :content, :indentation, :attribs, :lineno
|
88
|
+
|
89
|
+
def initialize(content, lineno, prev_line)
|
90
|
+
@content = content
|
91
|
+
@lineno = lineno
|
92
|
+
@prev = prev_line
|
93
|
+
@attribs = Hash.new(nil)
|
94
|
+
@tag = nil
|
95
|
+
@indentation = 0
|
96
|
+
detect_line_tag_and_indentation
|
97
|
+
end
|
98
|
+
|
99
|
+
# def length
|
100
|
+
# @content.length
|
101
|
+
# end
|
102
|
+
|
103
|
+
# def [](index)
|
104
|
+
# @content[index]
|
105
|
+
# end
|
106
|
+
|
107
|
+
def tag=(tag)
|
108
|
+
@tag = tag
|
109
|
+
raise Errors::LineTagUnknown.new(self, tag) unless ALLOWED_LINE_TAGS.include?(@tag)
|
110
|
+
end
|
111
|
+
|
112
|
+
def to_s
|
113
|
+
"[##{@lineno}] #{" " * @indentation}#{@content}"
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
# TODO: this regex must unit tested.
|
119
|
+
PATTERN_DICT_ITEM = /^
|
120
|
+
(?<key>[^\s].*?) # Key must start with a non-whitespace character, and goes until first
|
121
|
+
\s*: # first optional space, or :-separator
|
122
|
+
(?: # Value part is optional
|
123
|
+
\p{Space} # Must have a space after :-separator
|
124
|
+
(?<value>.*) # Value is everything to the end of the line
|
125
|
+
)?
|
126
|
+
$/x
|
127
|
+
|
128
|
+
def detect_line_tag_and_indentation
|
129
|
+
@indentation += 1 while @indentation < @content.length && @content[@indentation] == " "
|
130
|
+
@content = @content[@indentation..]
|
131
|
+
|
132
|
+
if @content.length == 0
|
133
|
+
self.tag = :blank
|
134
|
+
elsif @content[0] == "#"
|
135
|
+
self.tag = :comment
|
136
|
+
elsif @content =~ /^:(?: |$)/
|
137
|
+
self.tag = :key_item
|
138
|
+
@attribs["key"] = @content[2..] || ""
|
139
|
+
elsif @content =~ /^-(?: |$)/
|
140
|
+
self.tag = :list_item
|
141
|
+
@attribs["value"] = @content[2..]
|
142
|
+
elsif @content =~ /^>(?: |$)/
|
143
|
+
self.tag = :string_item
|
144
|
+
@attribs["value"] = @content[2..] || ""
|
145
|
+
elsif @content[0] == "{"
|
146
|
+
self.tag = :inline_dict
|
147
|
+
elsif @content[0] == "["
|
148
|
+
# TODO: merge path of inline dict and list and just set :inline?
|
149
|
+
self.tag = :inline_list
|
150
|
+
elsif @content =~ PATTERN_DICT_ITEM
|
151
|
+
self.tag = :dict_item
|
152
|
+
@attribs["key"] = Regexp.last_match(:key)
|
153
|
+
@attribs["value"] = Regexp.last_match(:value)
|
154
|
+
else
|
155
|
+
# Don't raise error here, as this line might not have been consumed yet,
|
156
|
+
# thus could hide an error that we detect when parsing the previous line.
|
157
|
+
self.tag = :unrecognized
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
data/lib/nestedtext.rb
ADDED
data/nestedtext.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/nestedtext/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "nestedtext"
|
7
|
+
spec.version = NestedText::VERSION
|
8
|
+
spec.authors = ["Erik Westrup"]
|
9
|
+
spec.email = ["erik.westrup@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = "A ruby library for the human friendly data format NestedText https://nestedtext.org/"
|
12
|
+
spec.description = "A ruby implementation the NestedText data format. There is support for decoding a NestedText file or string to Ruby data structures, as well as encoding Ruby objects to a NestedText file or string. Furthermore there is support for serialization and deserialization of custom classes. Support for v3.2.1 of the data format will all official tests passing."
|
13
|
+
spec.homepage = "https://github.com/erikw/nestedtext-ruby/"
|
14
|
+
spec.license = "MIT"
|
15
|
+
spec.required_ruby_version = [">= 3.0", "< 4"]
|
16
|
+
|
17
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
18
|
+
spec.metadata["source_code_uri"] = "https://github.com/erikw/nestedtext-ruby/"
|
19
|
+
spec.metadata["changelog_uri"] = "https://github.com/erikw/nestedtext-ruby/blob/main/CHANGELOG.md"
|
20
|
+
|
21
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
22
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
23
|
+
f.match(%r{\A(?:test/|script/|\.github/|\.gitmodules|Rakefile|TODO\.txt|\.codeclimate\.yml|\.vimlocal|\.simplecov)})
|
24
|
+
end
|
25
|
+
end
|
26
|
+
spec.require_paths = ["lib"]
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nestedtext
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Erik Westrup
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-01-24 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A ruby implementation the NestedText data format. There is support for
|
14
|
+
decoding a NestedText file or string to Ruby data structures, as well as encoding
|
15
|
+
Ruby objects to a NestedText file or string. Furthermore there is support for serialization
|
16
|
+
and deserialization of custom classes. Support for v3.2.1 of the data format will
|
17
|
+
all official tests passing.
|
18
|
+
email:
|
19
|
+
- erik.westrup@gmail.com
|
20
|
+
executables: []
|
21
|
+
extensions: []
|
22
|
+
extra_rdoc_files: []
|
23
|
+
files:
|
24
|
+
- ".editorconfig"
|
25
|
+
- ".gitignore"
|
26
|
+
- ".rubocop.yml"
|
27
|
+
- ".ruby-version"
|
28
|
+
- CHANGELOG.md
|
29
|
+
- CONTRIBUTING.md
|
30
|
+
- Gemfile
|
31
|
+
- LICENSE.txt
|
32
|
+
- OSSMETADATA
|
33
|
+
- README.md
|
34
|
+
- SECURITY.md
|
35
|
+
- lib/nestedtext.rb
|
36
|
+
- lib/nestedtext/constants.rb
|
37
|
+
- lib/nestedtext/core_ext.rb
|
38
|
+
- lib/nestedtext/decode.rb
|
39
|
+
- lib/nestedtext/dumper.rb
|
40
|
+
- lib/nestedtext/encode.rb
|
41
|
+
- lib/nestedtext/encode_helpers.rb
|
42
|
+
- lib/nestedtext/errors.rb
|
43
|
+
- lib/nestedtext/helpers.rb
|
44
|
+
- lib/nestedtext/parser.rb
|
45
|
+
- lib/nestedtext/scanners.rb
|
46
|
+
- lib/nestedtext/version.rb
|
47
|
+
- nestedtext.gemspec
|
48
|
+
homepage: https://github.com/erikw/nestedtext-ruby/
|
49
|
+
licenses:
|
50
|
+
- MIT
|
51
|
+
metadata:
|
52
|
+
homepage_uri: https://github.com/erikw/nestedtext-ruby/
|
53
|
+
source_code_uri: https://github.com/erikw/nestedtext-ruby/
|
54
|
+
changelog_uri: https://github.com/erikw/nestedtext-ruby/blob/main/CHANGELOG.md
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options: []
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '3.0'
|
64
|
+
- - "<"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '4'
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
requirements: []
|
73
|
+
rubygems_version: 3.3.3
|
74
|
+
signing_key:
|
75
|
+
specification_version: 4
|
76
|
+
summary: A ruby library for the human friendly data format NestedText https://nestedtext.org/
|
77
|
+
test_files: []
|