nodaire 0.2.0 → 0.3.0

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
  SHA256:
3
- metadata.gz: 57dbe680f2640d6fff1c929cc8b953a7bcb99bd173d207193231a752e50dfdfa
4
- data.tar.gz: b90ac2968b5ee9d26391228d1f1460a763bd409f879881991113e3286c68e542
3
+ metadata.gz: e9b7c87d8f3775b1d06a7cf203296efcf40bf95904ba9ed7e8a1f09d0d946e21
4
+ data.tar.gz: 2185bc3eea0363808665f4dbc6f6a04c7cb483544c92698dfd00200eee61673f
5
5
  SHA512:
6
- metadata.gz: c5606db3b3c3f5574024476681b5c5053d23274107dd88faa92211bade14d35acd3e9d5f1adc088681d6174ebe24ce66f2165138a864aa5d56efe89dfb20246d
7
- data.tar.gz: 0bb05b71c821062ce5bc5314491a3fa11b7b80f0aedef704c66a0fc7d972676a71e64da4fc72a21665e09acb3338e8396b29ce71454550cf740d02987b0b163d
6
+ metadata.gz: ac327bc203d061ee6bef827b3d43b5c3c6e8cd6f754c5e4cce9bf63dac8996452de348de057218c27da87170d45db9e8ca81f3d52ac25df8106136944940d867
7
+ data.tar.gz: '06508af2ec0ea395bc4b45c59c77d0b41490c6abf8cbc7ff565e86195b855e6bf24c4bcb2243d73a3da17f2e1b780ec04c50618709b41b0f098680503b148677'
data/README.md CHANGED
@@ -1,84 +1,91 @@
1
- # Nodaire
1
+ # Nodaire [![Gem Version](https://badge.fury.io/rb/nodaire.svg)](https://rubygems.org/gems/nodaire) [![Build Status](https://travis-ci.org/slisne/nodaire.svg?branch=master)](https://travis-ci.org/slisne/nodaire)
2
2
 
3
- Ruby parsers for text file formats. Work in progress.
3
+ Nodaire is a collection of text file parsers.
4
+ It supports Ruby 2.5.0 or greater.
4
5
 
5
- [![Gem Version](https://badge.fury.io/rb/nodaire.svg)](https://rubygems.org/gems/nodaire)
6
+ __Note__: This is a new gem, and the interface is not yet stable.
7
+ Expect breaking API changes before v1.0.0 is released.
6
8
 
7
9
  ## File formats
8
10
 
9
- - [Oscean](https://wiki.xxiivv.com/#oscean) file formats by Devine Lu Linvega:
10
- - [__Indental__](https://wiki.xxiivv.com/#indental) (.ndtl)
11
- - [__Tablatal__](https://wiki.xxiivv.com/#tablatal) (.tbtl)
11
+ Nodaire currently supports the following text file formats:
12
12
 
13
- ## Examples
13
+ - __Indental__ — <https://wiki.xxiivv.com/#indental>
14
+ - __Tablatal__ — <https://wiki.xxiivv.com/#tablatal>
15
+
16
+ ## Install
17
+
18
+ Install `nodaire` from [RubyGems](https://rubygems.org/gems/nodaire):
19
+
20
+ ```sh
21
+ gem install nodaire
22
+ ```
23
+
24
+ ## Documentation
25
+
26
+ [Code documentation](https://slisne.github.io/nodaire/) is available.
27
+
28
+ Keep reading below for examples of how to use Nodaire.
29
+
30
+ ## Usage examples
14
31
 
15
32
  ### Indental
16
33
 
17
34
  ```ruby
18
- > input = <<~NDTL
35
+ require 'nodaire/indental'
36
+
37
+ doc = Nodaire::Indental.parse! <<~NDTL
19
38
  NAME
20
39
  KEY : VALUE
21
40
  LIST
22
41
  ITEM1
23
42
  ITEM2
24
- NDTL
43
+ NDTL
25
44
 
26
- > indental = Nodaire::Indental.parse(input)
27
-
28
- > indental.data
29
- # {
30
- # name: {
31
- # key: 'VALUE',
32
- # list: ['ITEM1', 'ITEM2'],
33
- # },
34
- # }
35
-
36
- > indental.valid?
37
- # true
38
-
39
- > indental = Nodaire::Indental.parse(input, preserve_keys: true)
40
-
41
- > indental.to_json
42
- # {"NAME":{"KEY":"VALUE","LIST":["ITEM1","ITEM2"]}}
45
+ doc.valid? # true
46
+ doc.categories # ["NAME"]
47
+ doc.to_h # {"NAME"=>{"KEY"=>"VALUE", "LIST"=>["ITEM1", "ITEM2"]}}
48
+ doc.to_json # '{"NAME":{"KEY":"VALUE","LIST":["ITEM1","ITEM2"]}}'
43
49
  ```
44
50
 
45
51
  ### Tablatal
46
52
 
47
53
  ```ruby
48
- > input = <<~TBTL
54
+ require 'nodaire/tablatal'
55
+
56
+ doc = Nodaire::Tablatal.parse! <<~TBTL
49
57
  NAME AGE COLOR
50
58
  Erica 12 Opal
51
59
  Alex 23 Cyan
52
60
  Nike 34 Red
53
61
  Ruca 45 Grey
54
- TBTL
62
+ TBTL
55
63
 
56
- > tablatal = Nodaire::Tablatal.parse(input)
57
-
58
- > tablatal.data
59
- # [
60
- # { name: 'Erica', age: '12', color: 'Opal' },
61
- # { name: 'Alex', age: '23', color: 'Cyan' },
62
- # { name: 'Nike', age: '34', color: 'Red' },
63
- # { name: 'Ruca', age: '45', color: 'Grey' },
64
- # ]
64
+ doc.valid? # true
65
+ doc.keys # ["NAME", "AGE", "COLOR"]
66
+ doc.to_a.last # {"NAME"=>"Ruca", "AGE"=>"45", "COLOR"=>"Grey"}
67
+ doc.to_csv # "NAME,AGE,COLOR\nErica,12,Opal\nAlex,23,..."
68
+ ```
65
69
 
66
- > tablatal.valid?
67
- # true
70
+ ## Development
68
71
 
69
- > tablatal = Nodaire::Tablatal.parse(input, preserve_keys: true)
72
+ To run the latest source code, check out the
73
+ [Git repository](https://github.com/slisne/nodaire):
70
74
 
71
- > tablatal.to_csv
72
- # NAME,AGE,COLOR
73
- # Erica,12,Opal
74
- # Alex,23,Cyan
75
- # Nike,34,Red
76
- # Ruca,45,Grey
75
+ ```sh
76
+ git clone https://github.com/slisne/nodaire.git
77
77
  ```
78
78
 
79
- ## Testing
79
+ Install the dependencies using Bundler:
80
80
 
81
+ ```sh
82
+ gem install bundler
83
+ bundle install
81
84
  ```
82
- bundle install --with test
85
+
86
+ Analyse the code and run unit tests using Bundler:
87
+
88
+ ```sh
89
+ bundle exec rubocop
83
90
  bundle exec rspec
84
91
  ```
data/lib/nodaire.rb CHANGED
@@ -1,12 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- ##
4
- # Nodaire is a collection of text file parsers.
5
- #
6
- module Nodaire
7
- end
8
-
9
- require_relative 'nodaire/formats'
10
-
3
+ require_relative 'nodaire/base'
11
4
  require_relative 'nodaire/errors'
12
- require_relative 'nodaire/version'
5
+
6
+ require_relative 'nodaire/indental'
7
+ require_relative 'nodaire/tablatal'
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ require_relative '../parsers/indental_parser'
6
+
7
+ ##
8
+ # Interface for documents in _Indental_ format.
9
+ #
10
+ # _Indental_ is a 'dictionary-type database format' by Devine Lu Linvega.
11
+ # See: https://wiki.xxiivv.com/#indental
12
+ #
13
+ # require 'nodaire/indental'
14
+ #
15
+ # doc = Nodaire::Indental.parse! <<~NDTL
16
+ # NAME
17
+ # KEY : VALUE
18
+ # LIST
19
+ # ITEM1
20
+ # ITEM2
21
+ # NDTL
22
+ #
23
+ # doc.valid? # true
24
+ # doc.categories # ["NAME"]
25
+ # doc.to_h # {"NAME"=>{"KEY"=>"VALUE", "LIST"=>["ITEM1", "ITEM2"]}}
26
+ # doc.to_json # '{"NAME":{"KEY":"VALUE","LIST":["ITEM1","ITEM2"]}}'
27
+ #
28
+ # @since 0.2.0
29
+ #
30
+ class Nodaire::Indental
31
+ # A hash containing the data parsed from the source.
32
+ # @return [Hash]
33
+ attr_reader :data
34
+ # An array of category names.
35
+ # @since 0.3.0
36
+ # @return [Array<String>]
37
+ attr_reader :categories
38
+ # An array of error messages.
39
+ # @return [Array<String>]
40
+ attr_reader :errors
41
+
42
+ alias_method :to_h, :data
43
+
44
+ ##
45
+ # Parse the document +source+.
46
+ #
47
+ # @param [String] source The document source to parse.
48
+ # @param [Boolean] symbolize_names
49
+ # If true, normalize category and key names and convert them to
50
+ # lowercase symbols.
51
+ #
52
+ # @return [Indental]
53
+ #
54
+ def self.parse(source, symbolize_names: false)
55
+ parser = Parser.new(source, false, symbolize_names: symbolize_names)
56
+
57
+ new(parser)
58
+ end
59
+
60
+ ##
61
+ # Parse the document +source+, raising an exception if a parser error occurs.
62
+ #
63
+ # @param [String] source The document source to parse.
64
+ # @param [boolean] symbolize_names
65
+ # If true, normalize category and key names and convert them to
66
+ # lowercase symbols.
67
+ #
68
+ # @raise [ParserError]
69
+ # @return [Indental]
70
+ #
71
+ def self.parse!(source, symbolize_names: false)
72
+ parser = Parser.new(source, true, symbolize_names: symbolize_names)
73
+
74
+ new(parser)
75
+ end
76
+
77
+ ##
78
+ # A boolean indicating whether the source was parsed without errors.
79
+ #
80
+ # @return [Boolean]
81
+ #
82
+ def valid?
83
+ @errors.empty?
84
+ end
85
+
86
+ ##
87
+ # Convert the document to JSON.
88
+ #
89
+ # @return [String]
90
+ #
91
+ def to_json(*_args)
92
+ JSON.generate(data)
93
+ end
94
+
95
+ private
96
+
97
+ def initialize(parser)
98
+ @data = parser.data
99
+ @errors = parser.errors
100
+
101
+ @categories = data.keys
102
+ end
103
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'csv'
4
+
5
+ require_relative '../parsers/tablatal_parser'
6
+
7
+ ##
8
+ # Interface for documents in _Tablatal_ format.
9
+ #
10
+ # _Tablatal_ is a 'list-type database format' by Devine Lu Linvega.
11
+ # See: https://wiki.xxiivv.com/#tablatal
12
+ #
13
+ # require 'nodaire/tablatal'
14
+ #
15
+ # doc = Nodaire::Tablatal.parse! <<~TBTL
16
+ # NAME AGE COLOR
17
+ # Erica 12 Opal
18
+ # Alex 23 Cyan
19
+ # Nike 34 Red
20
+ # Ruca 45 Grey
21
+ # TBTL
22
+ #
23
+ # doc.valid? # true
24
+ # doc.keys # ["NAME", "AGE", "COLOR"]
25
+ # doc.to_a.last # {"NAME"=>"Ruca", "AGE"=>"45", "COLOR"=>"Grey"}
26
+ # doc.to_csv # "NAME,AGE,COLOR\nErica,12,Opal\nAlex,23,..."
27
+ #
28
+ # @since 0.1.0
29
+ #
30
+ class Nodaire::Tablatal
31
+ # An array of hashes containing the data parsed from the source.
32
+ # @return [Array<Hash>]
33
+ attr_reader :data
34
+ # An array of keys parsed from the source header line.
35
+ # @return [Array]
36
+ attr_reader :keys
37
+ # An array of error message strings.
38
+ # @since 0.2.0
39
+ # @return [Array<String>]
40
+ attr_reader :errors
41
+
42
+ alias_method :to_a, :data
43
+
44
+ ##
45
+ # Parse the document +source+.
46
+ #
47
+ # @param [String] source The document source to parse.
48
+ # @param [Boolean] symbolize_names
49
+ # If true, normalize key names and convert them to lowercase symbols.
50
+ #
51
+ # @since 0.2.0
52
+ # @return [Tablatal]
53
+ #
54
+ def self.parse(source, symbolize_names: false)
55
+ parser = Parser.new(source, false, symbolize_names: symbolize_names)
56
+
57
+ new(parser)
58
+ end
59
+
60
+ ##
61
+ # Parse the document +source+, raising an exception if a parser error occurs.
62
+ #
63
+ # @param [String] source The document source to parse.
64
+ # @param [Boolean] symbolize_names
65
+ # If true, normalize key names and convert them to lowercase symbols.
66
+ #
67
+ # @since 0.2.0
68
+ # @raise [ParserError]
69
+ # @return [Tablatal]
70
+ #
71
+ def self.parse!(source, symbolize_names: false)
72
+ parser = Parser.new(source, true, symbolize_names: symbolize_names)
73
+
74
+ new(parser)
75
+ end
76
+
77
+ ##
78
+ # A boolean indicating whether the source was parsed without errors.
79
+ #
80
+ # @since 0.2.0
81
+ # @return [Boolean]
82
+ #
83
+ def valid?
84
+ @errors.empty?
85
+ end
86
+
87
+ ##
88
+ # Convert the document to CSV.
89
+ #
90
+ # @return [String]
91
+ #
92
+ def to_csv
93
+ CSV.generate do |csv|
94
+ csv << keys
95
+ data.each do |row|
96
+ csv << keys.map { |key| row[key] }
97
+ end
98
+ end
99
+ end
100
+
101
+ private
102
+
103
+ def initialize(parser)
104
+ @data = parser.data
105
+ @keys = parser.keys
106
+ @errors = parser.errors
107
+ end
108
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # Nodaire is a collection of text file parsers.
5
+ #
6
+ module Nodaire
7
+ # The version number.
8
+ VERSION = '0.3.0'
9
+ # The date when this version was released.
10
+ DATE = '2019-08-18'
11
+ end
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nodaire
4
+ ##
5
+ # This exception is raised if a parser error occurs.
6
+ #
4
7
  class ParserError < StandardError; end
5
8
  end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+ require_relative 'api/indental'
@@ -1,30 +1,47 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../errors'
3
+ require_relative 'parser'
4
4
 
5
5
  class Nodaire::Indental
6
- class ParserError < Nodaire::ParserError; end
7
-
8
- class Parser
9
- attr_reader :data, :errors
6
+ # @private
7
+ class Parser < Nodaire::Parser
8
+ attr_reader :data
10
9
 
11
10
  def initialize(string, strict, options = {})
12
- @strict = strict
13
- @preserve_keys = options.fetch(:preserve_keys, false)
11
+ super(strict, options)
14
12
 
13
+ @symbolize_names = option(:symbolize_names, false)
15
14
  @data = {}
16
- @errors = []
15
+ @category_ids = {}
16
+ @category = nil
17
17
 
18
18
  parse! string
19
19
  end
20
20
 
21
21
  private
22
22
 
23
+ Category = Struct.new(:name, :key_ids, :list_id, keyword_init: true)
24
+
25
+ attr_accessor :category
26
+ attr_reader :symbolize_names, :category_ids
27
+
23
28
  def parse!(string)
29
+ lines = lines_to_parse(string)
30
+ lines = lines[1...-1] if js_wrapper?(lines)
31
+ lines.each { |line, num| parse_line! line, num }
32
+ end
33
+
34
+ def lines_to_parse(string)
24
35
  (string || '')
25
36
  .split("\n").each_with_index
26
37
  .reject { |line, _| line.match(/^\s*(;.*)?$/) }
27
- .each { |line, idx| parse_line! line, idx + 1 }
38
+ .map { |line, idx| [line, idx + 1] }
39
+ end
40
+
41
+ def js_wrapper?(lines)
42
+ !lines.empty? &&
43
+ lines.first[0].match(/=\s*`\s*$/) &&
44
+ lines.last[0].strip == '`'
28
45
  end
29
46
 
30
47
  def parse_line!(line, num)
@@ -37,67 +54,76 @@ class Nodaire::Indental
37
54
  end
38
55
 
39
56
  def parse_category!(cat, num)
40
- cat = symbolize_key(cat)
41
- if data.include?(cat)
42
- @cat_id = nil
43
- @list_id = nil
57
+ id = normalize_sym(cat)
58
+
59
+ if category_ids.include?(id)
44
60
  oops! 'Duplicate category', num
61
+ self.category = nil
45
62
  else
46
- @data[cat] = {}
47
- @cat_id = cat
48
- @list_id = nil
63
+ self.category = Category.new(
64
+ name: symbolize_names ? id : normalize_text(cat),
65
+ key_ids: {},
66
+ list_id: nil
67
+ )
68
+ data[category.name] = {}
69
+ category_ids[id] = category.name
49
70
  end
50
71
  end
51
72
 
52
73
  def parse_key_or_list!(line, num)
53
- return oops!('No category specified', num) unless @cat_id
74
+ return oops!('No category specified', num) if category.nil?
54
75
 
55
76
  if line.include?(' : ')
56
77
  key, value = line.split(' : ', 2)
57
- parse_key_value!(key.strip, value.strip, num)
78
+ parse_key_value!(key, value, num)
58
79
  else
59
80
  parse_list!(line, num)
60
81
  end
61
82
  end
62
83
 
63
84
  def parse_key_value!(key, value, num)
64
- key = symbolize_key(key)
65
- if @data[@cat_id].include?(key)
66
- @list_id = nil
85
+ id = normalize_sym(key)
86
+ key_name = symbolize_names ? id : normalize_text(key)
87
+
88
+ if category.key_ids.include?(id)
67
89
  oops! 'Duplicate key', num
68
90
  else
69
- @data[@cat_id][key] = value.strip
70
- @list_id = nil
91
+ data[category.name][key_name] = normalize_text(value)
92
+ category.key_ids[id] = key_name
71
93
  end
94
+
95
+ category.list_id = nil
72
96
  end
73
97
 
74
98
  def parse_list!(key, num)
75
- key = symbolize_key(key)
76
- if @data[@cat_id].include?(key)
77
- @list_id = nil
78
- oops! 'Duplicate key', num
99
+ id = normalize_sym(key)
100
+ list_name = symbolize_names ? id : normalize_text(key)
101
+
102
+ if category.key_ids.include?(id)
103
+ oops! 'Duplicate key for list', num
104
+ category.list_id = nil
79
105
  else
80
- @data[@cat_id][key] = []
81
- @list_id = key
106
+ data[category.name][list_name] = []
107
+ category.key_ids[id] = list_name
108
+ category.list_id = id
82
109
  end
83
110
  end
84
111
 
85
112
  def parse_list_item!(item, num)
86
- if @list_id.nil?
113
+ if category.nil? || category.list_id.nil?
87
114
  oops! 'No list specified', num
88
115
  else
89
- @data[@cat_id][@list_id] << item
116
+ list_name = category.key_ids[category.list_id]
117
+ data[category.name][list_name] << normalize_text(item)
90
118
  end
91
119
  end
92
120
 
93
- def oops!(message, line_num)
94
- message = "#{message} on line #{line_num}"
95
- @errors << message
96
- raise ParserError, message if @strict
121
+ def normalize_text(string)
122
+ string.split.join(' ')
97
123
  end
98
124
 
99
- def symbolize_key(key)
100
- @preserve_keys ? key : key.downcase.split.join('_').to_sym
125
+ def normalize_sym(key)
126
+ key.downcase.gsub(/[\s_-]+/, ' ').split.join('_').to_sym
101
127
  end
102
128
  end
103
129
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../errors'
4
+
5
+ # @private
6
+ class Nodaire::Parser
7
+ attr_reader :errors, :options
8
+
9
+ def initialize(strict, options = {})
10
+ @strict = strict
11
+ @options = options
12
+ @errors = []
13
+ end
14
+
15
+ def strict?
16
+ @strict
17
+ end
18
+
19
+ def option(name, default = nil)
20
+ @options.fetch(name, default)
21
+ end
22
+
23
+ def oops!(message, line_num)
24
+ message = "#{message} on line #{line_num}" unless line_num.nil?
25
+ errors << message
26
+ raise Nodaire::ParserError, message if strict?
27
+ end
28
+ end
@@ -1,28 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../errors'
3
+ require_relative 'parser'
4
4
 
5
5
  class Nodaire::Tablatal
6
- class ParserError < Nodaire::ParserError; end
7
-
8
- class Parser
9
- attr_reader :data, :errors
6
+ # @private
7
+ class Parser < Nodaire::Parser
8
+ attr_reader :data
10
9
 
11
10
  def initialize(string, strict, options = {})
12
- @strict = strict
13
- @preserve_keys = options.fetch(:preserve_keys, false)
11
+ super(strict, options)
12
+
13
+ @symbolize_names = option(:symbolize_names, false)
14
14
 
15
- @errors = []
15
+ @data = []
16
+ @keys = []
17
+ @key_ids = {}
16
18
 
17
19
  parse! string
18
20
  end
19
21
 
20
22
  def keys
21
- @keys.map(&:name) if @keys
23
+ @keys.map(&:name)
22
24
  end
23
25
 
24
26
  private
25
27
 
28
+ attr_reader :symbolize_names, :key_ids
29
+
26
30
  Key = Struct.new(:name, :range, keyword_init: true)
27
31
 
28
32
  def parse!(string)
@@ -31,20 +35,23 @@ class Nodaire::Tablatal
31
35
  return if lines.empty?
32
36
 
33
37
  @keys = make_keys(lines.shift.scan(/(\S+\s*)/).flatten)
34
- @data = lines.map { |line, num| make_line(line, num) }.compact
38
+ @data = lines.map { |line| make_line(line) }.compact
35
39
  end
36
40
 
37
41
  def make_keys(segs)
38
42
  [].tap do |keys|
39
43
  start = 0
40
44
  segs.each_with_index do |seg, idx|
41
- key = symbolize_key(seg.strip)
42
45
  len = seg.size if idx < segs.size - 1
46
+ id = normalize_sym(seg)
47
+ key_name = symbolize_names ? id : normalize_text(seg)
43
48
 
44
- if keys.any? { |k| key == k.name }
45
- oops! "Duplicate key #{key}", 1
49
+ if key_ids.include?(id)
50
+ oops! "Duplicate key #{key_name}", 1
46
51
  else
47
- keys << Key.new(name: key, range: start...(len && start + len))
52
+ range_end = len ? start + len - 1 : -1
53
+ key_ids[id] = key_name
54
+ keys << Key.new(name: key_name, range: start..range_end)
48
55
  end
49
56
 
50
57
  start += len if len
@@ -52,18 +59,16 @@ class Nodaire::Tablatal
52
59
  end
53
60
  end
54
61
 
55
- def make_line(line, num)
56
- @keys.map { |key| [key.name, (line[key.range] || '').strip] }.to_h
62
+ def make_line(line)
63
+ @keys.map { |key| [key.name, normalize_text(line[key.range])] }.to_h
57
64
  end
58
65
 
59
- def oops!(message, line_num)
60
- message = "#{message} on line #{line_num}"
61
- @errors << message
62
- raise ParserError, message if @strict
66
+ def normalize_text(string)
67
+ string ? string.split.join(' ') : ''
63
68
  end
64
69
 
65
- def symbolize_key(key)
66
- @preserve_keys ? key : key.downcase.to_sym
70
+ def normalize_sym(key)
71
+ key.downcase.gsub(/[_-]+/, ' ').split.join('_').to_sym
67
72
  end
68
73
  end
69
74
  end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+ require_relative 'api/tablatal'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nodaire
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Liam Cooke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-17 00:00:00.000000000 Z
11
+ date: 2019-08-18 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Nodaire is a collection of text file parsers.
14
14
  email: nodaire@liamcooke.com
@@ -19,22 +19,24 @@ files:
19
19
  - LICENSE
20
20
  - README.md
21
21
  - lib/nodaire.rb
22
+ - lib/nodaire/api/indental.rb
23
+ - lib/nodaire/api/tablatal.rb
24
+ - lib/nodaire/base.rb
22
25
  - lib/nodaire/errors.rb
23
- - lib/nodaire/formats.rb
24
- - lib/nodaire/formats/indental.rb
25
- - lib/nodaire/formats/tablatal.rb
26
+ - lib/nodaire/indental.rb
26
27
  - lib/nodaire/parsers/indental_parser.rb
28
+ - lib/nodaire/parsers/parser.rb
27
29
  - lib/nodaire/parsers/tablatal_parser.rb
28
- - lib/nodaire/version.rb
29
- homepage: https://github.com/ljcooke/nodaire
30
+ - lib/nodaire/tablatal.rb
31
+ homepage: https://github.com/slisne/nodaire
30
32
  licenses:
31
33
  - MIT
32
34
  metadata:
33
- bug_tracker_uri: https://github.com/ljcooke/nodaire/issues
34
- changelog_uri: https://github.com/ljcooke/nodaire/blob/master/CHANGELOG.md
35
- documentation_uri: https://github.com/ljcooke/nodaire
36
- homepage_uri: https://github.com/ljcooke/nodaire
37
- source_code_uri: https://github.com/ljcooke/nodaire
35
+ bug_tracker_uri: https://github.com/slisne/nodaire/issues
36
+ changelog_uri: https://github.com/slisne/nodaire/blob/master/CHANGELOG.md
37
+ documentation_uri: https://slisne.github.io/nodaire/
38
+ homepage_uri: https://github.com/slisne/nodaire
39
+ source_code_uri: https://github.com/slisne/nodaire
38
40
  post_install_message:
39
41
  rdoc_options: []
40
42
  require_paths:
@@ -43,14 +45,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
43
45
  requirements:
44
46
  - - ">="
45
47
  - !ruby/object:Gem::Version
46
- version: '0'
48
+ version: 2.5.0
47
49
  required_rubygems_version: !ruby/object:Gem::Requirement
48
50
  requirements:
49
51
  - - ">="
50
52
  - !ruby/object:Gem::Version
51
53
  version: '0'
52
54
  requirements: []
53
- rubygems_version: 3.0.3
55
+ rubyforge_project:
56
+ rubygems_version: 2.7.3
54
57
  signing_key:
55
58
  specification_version: 4
56
59
  summary: Text file parsers.
@@ -1,4 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'formats/indental'
4
- require_relative 'formats/tablatal'
@@ -1,58 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'json'
4
-
5
- require_relative '../parsers/indental_parser'
6
-
7
- ##
8
- # Interface for the Indental file format.
9
- #
10
- # Indental is (c) Devine Lu Linvega (MIT License).
11
- #
12
- class Nodaire::Indental
13
- attr_reader :data, :errors
14
- alias_method :to_h, :data
15
-
16
- ##
17
- # Parse a string in Indental format.
18
- #
19
- # Ignores or attempts to work around errors.
20
- #
21
- def self.parse(string, preserve_keys: false)
22
- parser = Parser.new(string, false, preserve_keys: preserve_keys)
23
-
24
- new(parser)
25
- end
26
-
27
- ##
28
- # Parse a string in Indental format.
29
- #
30
- # Raises an exception if there are errors.
31
- #
32
- def self.parse!(string, preserve_keys: false)
33
- parser = Parser.new(string, true, preserve_keys: preserve_keys)
34
-
35
- new(parser)
36
- end
37
-
38
- ##
39
- # Returns whether the input was parsed without errors.
40
- #
41
- def valid?
42
- @errors.empty?
43
- end
44
-
45
- ##
46
- # Return a string in JSON format.
47
- #
48
- def to_json
49
- JSON.generate(data)
50
- end
51
-
52
- private
53
-
54
- def initialize(parser)
55
- @data = parser.data
56
- @errors = parser.errors
57
- end
58
- end
@@ -1,64 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'csv'
4
-
5
- require_relative '../parsers/tablatal_parser'
6
-
7
- ##
8
- # Interface for the Tablatal file format.
9
- #
10
- # Tablatal is (c) Devine Lu Linvega (MIT License).
11
- #
12
- class Nodaire::Tablatal
13
- attr_reader :data, :keys, :errors
14
- alias_method :to_a, :data
15
-
16
- ##
17
- # Parse a string in Tablatal format.
18
- #
19
- # Ignores or attempts to work around errors.
20
- #
21
- def self.parse(string, preserve_keys: false)
22
- parser = Parser.new(string, false, preserve_keys: preserve_keys)
23
-
24
- new(parser)
25
- end
26
-
27
- ##
28
- # Parse a string in Tablatal format.
29
- #
30
- # Raises an exception if there are errors.
31
- #
32
- def self.parse!(string, preserve_keys: false)
33
- parser = Parser.new(string, true, preserve_keys: preserve_keys)
34
-
35
- new(parser)
36
- end
37
-
38
- ##
39
- # Returns whether the input was parsed without errors.
40
- #
41
- def valid?
42
- @errors.empty?
43
- end
44
-
45
- ##
46
- # Return a string in CSV format.
47
- #
48
- def to_csv
49
- CSV.generate do |csv|
50
- csv << keys
51
- data.each do |row|
52
- csv << keys.map { |key| row[key] }
53
- end
54
- end
55
- end
56
-
57
- private
58
-
59
- def initialize(parser)
60
- @data = parser.data
61
- @keys = parser.keys
62
- @errors = parser.errors
63
- end
64
- end
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nodaire
4
- module Version
5
- STRING = '0.2.0'
6
- DATE = '2019-08-17'
7
- end
8
- end