metaheader 1.2.1 → 1.3beta1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 072b809611c9fdd9b3cda179f3a755ddef92685f
4
- data.tar.gz: 0e68adce0f7675b27aa6ce58ce26f43de34f392e
3
+ metadata.gz: b2785ed7e70b818e49c72e9f8d8dfa868f382936
4
+ data.tar.gz: 69186b6be145a432dc9dc81efbc1d86f9c6b8c1c
5
5
  SHA512:
6
- metadata.gz: 64c0785eb124d9a096467f11b3449a6def1c5a7b65c8198b378c04cdcfd45c0c27297df386746c4f0e3d28e142a9d3fcce05e07287a7d5f0ad39cce3d9027a6a
7
- data.tar.gz: 15b1bd95e2fc1d4c8578e0d1eae8fa2a4a61e153ce307cbbc8fbe4526bfd2813995dc276ba557a5317350878d26f80e263f903e2db34101953530fad46e0f1ad
6
+ metadata.gz: 5cda458f1ad6a0a11c97018655aae2b66656b497316c35826d3f6567eabf7f84482f12a3591f8bd163ce80c40c332db3c211849f57e98afb7d7e8e901305e61b
7
+ data.tar.gz: 0bfe9167f00907300ceccadcc662287081036e70b251f637209c11048932f10fbe99fe09eaf7852c66a7bb5f67862a86400f72dd5b0f0dbecdb8380f7154aed1
@@ -1,4 +1,4 @@
1
1
  class MetaHeader
2
2
  # MetaHeader's version
3
- VERSION = '1.2.1'.freeze
3
+ VERSION = '1.3beta1'.freeze
4
4
  end
data/lib/metaheader.rb CHANGED
@@ -64,7 +64,6 @@ class MetaHeader
64
64
  @data = {}
65
65
 
66
66
  @last_key = nil
67
- @last_prefix = String.new
68
67
 
69
68
  input = input.encode universal_newline: true
70
69
  input.each_line {|line|
@@ -120,7 +119,7 @@ class MetaHeader
120
119
  # @param tag [Symbol] the tag to lookup
121
120
  # @return [Boolean]
122
121
  def has?(tag)
123
- @data.has_key? tag.to_sym
122
+ @data.has_key? tag
124
123
  end
125
124
 
126
125
  # Removes a given tag from the list.
@@ -158,8 +157,8 @@ class MetaHeader
158
157
  errors = Array.new
159
158
 
160
159
  if @strict
161
- @data.each_key {|key|
162
- errors << "unknown tag '%s'" % key unless rules.has_key? key
160
+ @data.each {|key, tag|
161
+ errors << "unknown tag '%s'" % tag.name unless rules.has_key? key
163
162
  }
164
163
  end
165
164
 
@@ -172,6 +171,28 @@ class MetaHeader
172
171
  errors unless errors.empty?
173
172
  end
174
173
 
174
+ # Rename one or more tags.
175
+ # @param old [Symbol, Hash]
176
+ # @param new [Symbol]
177
+ # @example
178
+ # mh.alias :old, :new
179
+ # mh.alias :old1, :old2, :new
180
+ # mh.alias [:old1, :old2], :new
181
+ # mh.alias old1: :new1, old2: :new2
182
+ def alias(*args)
183
+ raise ArgumentError, 'wrong number of arguments' unless args.size.between? 1, 2
184
+
185
+ tags, new = args
186
+
187
+ if args.size == 1
188
+ tags.each {|k, v| self.alias k, v }
189
+ else
190
+ Array(tags).each {|old|
191
+ @data[new] = delete old if has? old
192
+ }
193
+ end
194
+ end
195
+
175
196
  private
176
197
  # @api private
177
198
  Tag = Struct.new :name, :value
@@ -182,29 +203,19 @@ private
182
203
  \Z/x.freeze
183
204
 
184
205
  def parse(line)
185
- line.rstrip!
186
-
187
- # multiline value must have the same prefix
188
- if @last_key && line.index(@last_prefix) == 0
189
- # remove the line prefix
190
- mline = line[@last_prefix.size..-1]
191
- stripped = mline.strip
192
-
193
- indent_level = mline.index stripped
194
-
195
- if indent_level > 0
196
- tag = @data[@last_key]
197
-
198
- tag.value = @raw_value.to_s unless tag.value.is_a? String
199
- tag.value += "\n" unless tag.value.empty?
200
- tag.value += stripped
206
+ line.chomp!
201
207
 
208
+ # multiline value must have the same line prefix as the key
209
+ if @last_key && line.start_with?(@last_prefix.rstrip)
210
+ if append line
202
211
  return
203
212
  else
204
213
  @last_key = nil
205
214
  end
206
215
  end
207
216
 
217
+ line.rstrip!
218
+
208
219
  return unless match = REGEX.match(line)
209
220
 
210
221
  # single line
@@ -216,16 +227,41 @@ private
216
227
 
217
228
  @last_key = key.to_sym
218
229
  @data[@last_key] = Tag.new match[:key].freeze, value
230
+ @line_breaks = 0
219
231
  end
220
232
 
221
- def parse_value(key, value)
222
- value ||= true
233
+ def append(line)
234
+ if line.rstrip == @last_prefix.rstrip
235
+ @line_breaks += 1
236
+ return true # add the line break later
237
+ elsif line.start_with? @last_prefix
238
+ mline = line[@last_prefix.size..-1]
239
+ stripped = mline.lstrip
240
+ indent_level = mline.index stripped
241
+ return if indent_level < 1
242
+ else
243
+ return
244
+ end
245
+
246
+ tag = @data[@last_key]
247
+ tag.value = @raw_value.to_s unless tag.value.is_a? String
223
248
 
249
+ @line_breaks += 1 unless tag.value.empty?
250
+ tag.value += "\n" * @line_breaks
251
+ @line_breaks = 0
252
+
253
+ tag.value += stripped
254
+ stripped
255
+ end
256
+
257
+ def parse_value(key, value)
224
258
  case value
225
259
  when 'true'
226
260
  value = true
227
261
  when 'false'
228
262
  value = false
263
+ when nil
264
+ value = true
229
265
  when String
230
266
  value = nil if value.empty?
231
267
  end
data/test/test_parser.rb CHANGED
@@ -109,6 +109,11 @@ class TestParser < MiniTest::Test
109
109
  assert_equal 2, mh.size
110
110
  end
111
111
 
112
+ def test_trailing_whitespace
113
+ mh = MetaHeader.new '@hello world '
114
+ assert_equal 'world', mh[:hello]
115
+ end
116
+
112
117
  def test_multiline
113
118
  mh = MetaHeader.new <<-IN
114
119
  @test Lorem
@@ -137,8 +142,8 @@ class TestParser < MiniTest::Test
137
142
  test\x20
138
143
  IN
139
144
 
140
- assert_equal 'test', mh[:hello]
141
- assert_equal 'test', mh[:world]
145
+ assert_equal 'test ', mh[:hello]
146
+ assert_equal 'test ', mh[:world]
142
147
  end
143
148
 
144
149
  def test_multiline_prefix
@@ -182,6 +187,32 @@ class TestParser < MiniTest::Test
182
187
  assert_equal "true\ntest", mh[:test]
183
188
  end
184
189
 
190
+ def test_multiline_empty_line
191
+ mh = MetaHeader.new <<-IN
192
+ --@test
193
+ -- Hello
194
+ --
195
+ -- World
196
+ --
197
+ --@chunky
198
+ -- bacon
199
+ IN
200
+
201
+ assert_equal "Hello\n\nWorld", mh[:test]
202
+ assert_equal 'bacon', mh[:chunky] # no leading newline
203
+ end
204
+
205
+ def test_multiline_empty_line_space_prefix
206
+ mh = MetaHeader.new <<-IN
207
+ -- @test
208
+ -- Hello
209
+ --
210
+ -- World
211
+ IN
212
+
213
+ assert_equal "Hello\n\nWorld", mh[:test]
214
+ end
215
+
185
216
  def test_read_file
186
217
  path = File.expand_path '../input/basic_tag', __FILE__
187
218
  mh = MetaHeader.from_file path
@@ -271,5 +302,38 @@ class TestParser < MiniTest::Test
271
302
  def test_construct_from_instance
272
303
  mh = MetaHeader.new '@hello world'
273
304
  assert_same mh, MetaHeader.parse(mh)
305
+ assert_equal mh.to_h, MetaHeader.parse('@hello world').to_h
306
+ end
307
+
308
+ def test_alias
309
+ mh = MetaHeader.new '@a 1'
310
+ mh.alias :a, :b
311
+ refute mh.has?(:a)
312
+ assert_equal '1', mh[:b]
313
+
314
+ mh[:d] = '2'
315
+ mh.alias :c, :d
316
+ refute mh.has?(:c)
317
+ assert_equal '2', mh[:d]
318
+ end
319
+
320
+ def test_alias_hash
321
+ mh = MetaHeader.new "@a 1\n@b 2"
322
+ mh.alias a: :c, b: :d
323
+ assert_equal '1', mh[:c]
324
+ assert_equal '2', mh[:d]
325
+ end
326
+
327
+ def test_alias_array
328
+ mh = MetaHeader.new "@a 1\n@b 2"
329
+ mh.alias [:a, :b, :c], :d
330
+ assert [:a, :b, :c].none? {|t| mh.has? t }
331
+ assert_equal '2', mh[:d]
332
+ end
333
+
334
+ def test_alias_invalid_args
335
+ mh = MetaHeader.new "@a 1\n@b 2"
336
+ assert_raises(ArgumentError) { mh.alias }
337
+ assert_raises(ArgumentError) { mh.alias 1, 2, 3 }
274
338
  end
275
339
  end
@@ -6,11 +6,11 @@ class TestValidator < MiniTest::Test
6
6
  end
7
7
 
8
8
  def test_unknown_strict
9
- mh = MetaHeader.new "@hello\n@world"
9
+ mh = MetaHeader.new "@hello\n@WORLD"
10
10
  mh.strict = true
11
11
 
12
12
  actual = mh.validate Hash.new
13
- assert_equal ["unknown tag 'hello'", "unknown tag 'world'"], actual
13
+ assert_equal ["unknown tag 'hello'", "unknown tag 'WORLD'"], actual
14
14
  end
15
15
 
16
16
  def test_unknown_tolerant
@@ -107,4 +107,11 @@ class TestValidator < MiniTest::Test
107
107
  hello: MetaHeader::BOOLEAN
108
108
  assert_equal ["tag 'hello' cannot have a value"], actual
109
109
  end
110
+
111
+ def test_alias
112
+ mh = MetaHeader.new "@a"
113
+ mh.alias :a, :b
114
+ assert_equal ["missing value for tag 'a'"],
115
+ mh.validate(b: [MetaHeader::REQUIRED, MetaHeader::VALUE])
116
+ end
110
117
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metaheader
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.3beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - cfillion
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-07 00:00:00.000000000 Z
11
+ date: 2016-07-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -118,9 +118,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
118
118
  version: '2.3'
119
119
  required_rubygems_version: !ruby/object:Gem::Requirement
120
120
  requirements:
121
- - - ">="
121
+ - - ">"
122
122
  - !ruby/object:Gem::Version
123
- version: '0'
123
+ version: 1.3.1
124
124
  requirements: []
125
125
  rubyforge_project:
126
126
  rubygems_version: 2.5.1