mrtable 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 96ed9a18eb27745d6768ec317b07556ae131eb54
4
+ data.tar.gz: 98d67db991cb936f04c70eb43b018a60245b01bc
5
+ SHA512:
6
+ metadata.gz: b9dbcbdb67aecd85089041986b2f29a7aac7b4676e68cb31e65a175ed5ba08fcf5d725bd89599118fc7ba4667ffc99e07045fbc086109d3b333ef72d18eb4fee
7
+ data.tar.gz: e8e1c9ccc929859fe482469c7d0850a5d15146af4c132caa6d7a5d746390572ca308baf18b80ed6c25148546c9170873697f86f7c9f20053ee04e0191ac0ff6b
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ # Bundler
2
+
3
+ /.bundle/
4
+ /Gemfile.lock
5
+ /vendor/
6
+ /pkg/
7
+
8
+ # Emacs
9
+
10
+ *~
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mrtable.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,23 @@
1
+ # Mrtable
2
+
3
+ Machine readable table.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'mrtable'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install mrtable
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :test
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "mrtable"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install --path=vendor/bundle
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,3 @@
1
+ module Mrtable
2
+ VERSION = "0.0.1"
3
+ end
data/lib/mrtable.rb ADDED
@@ -0,0 +1,217 @@
1
+ # coding: utf-8
2
+
3
+ require "mrtable/version"
4
+ require "json"
5
+
6
+ module Mrtable
7
+ class Table
8
+ attr_reader :rows, :header_cols
9
+
10
+ def initialize(header_cols, rows)
11
+ @header_cols = header_cols
12
+ @rows = rows
13
+ end
14
+
15
+ # ci: column index
16
+ # @return new table
17
+ def map_col_with_ci
18
+ new_rows = @rows.map { |cols|
19
+ new_cols = []
20
+ cols.each_with_index { |col, ci|
21
+ new_cols << yield(col, ci)
22
+ }
23
+ new_cols
24
+ }
25
+
26
+ new_header_cols = []
27
+ @header_cols.each_with_index { |col, ci|
28
+ new_header_cols << yield(col, ci)
29
+ }
30
+
31
+ Table.new new_header_cols, new_rows
32
+ end
33
+
34
+ def calc_maxlens
35
+ num_cols = @rows[0].size
36
+ maxlens = (0...num_cols).map { |ci|
37
+ cols_at_ci = @rows.map { |cols| cols[ci] }
38
+ if @header_cols
39
+ cols_at_ci << @header_cols[ci]
40
+ end
41
+ cols_at_ci.map { |col|
42
+ Mrtable.col_len(col)
43
+ }.max
44
+ }
45
+
46
+ # compatibility for GFM
47
+ min_len = 3
48
+ maxlens.map { |len| [len, min_len].max }
49
+ end
50
+ end
51
+
52
+ def self.int?(s)
53
+ /^\-?[\d,]+$/ =~ s
54
+ end
55
+
56
+ def self.pad_col(col, maxlen)
57
+ if int? col
58
+ pad_left col, maxlen
59
+ else
60
+ pad_right col, maxlen
61
+ end
62
+ end
63
+
64
+ def self.col_len(col)
65
+ (0...col.size).inject(0) { |sum, i|
66
+ sum + (hankaku?(col[i]) ? 1 : 2)
67
+ }
68
+ end
69
+
70
+ def self.pad_right(s, n)
71
+ rest = n - col_len(s)
72
+ if rest <= 0
73
+ return s
74
+ end
75
+ s + (" " * rest)
76
+ end
77
+
78
+ def self.pad_left(s, n)
79
+ rest = n - col_len(s)
80
+ if rest <= 0
81
+ return s
82
+ end
83
+ (" " * rest) + s
84
+ end
85
+
86
+ def self.serealize_col(col)
87
+ if col.nil?
88
+ return ""
89
+ elsif col == ""
90
+ return '""'
91
+ end
92
+
93
+ ret = json_encode(col)
94
+ if /^\s+/ =~ ret || /\s+$/ =~ ret || /^\-+$/ =~ ret
95
+ '"' + ret + '"'
96
+ else
97
+ ret.gsub("|", "\\|")
98
+ end
99
+ end
100
+
101
+ def self.to_table_row(cols)
102
+ "| " + cols.join(" | ") + " |"
103
+ end
104
+
105
+ # 32-126(0x20-0x7E), 65377-65439(0xFF61-0xFF9F)
106
+ def self.hankaku?(c)
107
+ (/^[ -~。-゚]$/ =~ c) ? true : false
108
+ end
109
+
110
+ def self.json_encode(val)
111
+ json = JSON.generate([val])
112
+ if /^\["(.*)"\]$/ =~ json
113
+ $1
114
+ elsif /^\[(.+)\]$/ =~ json
115
+ $1
116
+ else
117
+ json
118
+ end
119
+ end
120
+
121
+ def self.json_decode(str)
122
+ if /^".*"$/ =~ str
123
+ JSON.parse('[' + str + ']')[0]
124
+ else
125
+ JSON.parse('["' + str + '"]')[0]
126
+ end
127
+ end
128
+
129
+ def self.parse_col(col)
130
+ if col == ''
131
+ nil
132
+ elsif col == '""'
133
+ ""
134
+ else
135
+ json_decode(col)
136
+ end
137
+ end
138
+
139
+ def self.split_row(line)
140
+ line2 = line + " "
141
+ cols = []
142
+ buf = ""
143
+ pos = 2
144
+ pos_delta = nil
145
+
146
+ num_repeat_max = line2.size
147
+ num_repeat_max.times do
148
+ break if pos >= line2.size
149
+ pos_delta = 1
150
+ rest = line2[pos..-1]
151
+ if /^ \| / =~ rest
152
+ cols << buf; buf = ""
153
+ pos_delta = 3
154
+ elsif /^\\/ =~ rest
155
+ if rest[1] == "|"
156
+ buf += rest[1]
157
+ pos_delta = 2
158
+ else
159
+ buf += rest[0..1]
160
+ pos_delta = 2
161
+ end
162
+ else
163
+ buf += rest[0]
164
+ end
165
+ pos += pos_delta
166
+ end
167
+
168
+ cols
169
+ end
170
+
171
+ def self.parse(text)
172
+ lines = text.split(/\r?\n/)
173
+ lines2 = lines.reject { |line|
174
+ /^\s*$/ =~ line ||
175
+ /^\| \-\-\-+ \|/ =~ line
176
+ }
177
+ rows = lines2.map { |line|
178
+ split_row(line)
179
+ }
180
+ raw = Table.new rows[0], rows[1..-1]
181
+
182
+ stripped = raw.map_col_with_ci { |col, _|
183
+ col.strip
184
+ }
185
+
186
+ parsed = stripped.map_col_with_ci { |col, _|
187
+ parse_col col
188
+ }
189
+
190
+ {
191
+ :header_cols => parsed.header_cols,
192
+ :rows => parsed.rows
193
+ }
194
+ end
195
+
196
+ def self.generate(header_cols, rows)
197
+ table = Table.new(header_cols, rows)
198
+
199
+ serealized = table.map_col_with_ci { |col, _|
200
+ serealize_col col
201
+ }
202
+
203
+ maxlens = serealized.calc_maxlens()
204
+
205
+ padded = serealized.map_col_with_ci { |col, ci|
206
+ pad_col col, maxlens[ci]
207
+ }
208
+
209
+ lines = []
210
+ lines << to_table_row(padded.header_cols)
211
+ lines << to_table_row(maxlens.map { |len| "-" * len })
212
+ lines += padded.rows.map { |cols|
213
+ to_table_row(cols)
214
+ }
215
+ lines.map { |line| line + "\n" }.join("")
216
+ end
217
+ end
data/mrtable.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mrtable/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "mrtable"
8
+ spec.version = Mrtable::VERSION
9
+ spec.authors = ["sonota88"]
10
+ spec.email = ["yosiot8753@gmail.com"]
11
+
12
+ spec.summary = %q{machine readable table}
13
+ spec.description = %q{machine readable table}
14
+ spec.homepage = "https://github.com/sonota88/mrtable"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.13"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "minitest", "~> 5.0"
26
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mrtable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - sonota88
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-10-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.13'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.13'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ description: machine readable table
56
+ email:
57
+ - yosiot8753@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - Gemfile
64
+ - README.md
65
+ - Rakefile
66
+ - bin/console
67
+ - bin/setup
68
+ - lib/mrtable.rb
69
+ - lib/mrtable/version.rb
70
+ - mrtable.gemspec
71
+ homepage: https://github.com/sonota88/mrtable
72
+ licenses: []
73
+ metadata: {}
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubyforge_project:
90
+ rubygems_version: 2.6.8
91
+ signing_key:
92
+ specification_version: 4
93
+ summary: machine readable table
94
+ test_files: []