metaheader 1.2.1 → 1.3beta1

Sign up to get free protection for your applications and to get access to all the features.
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