ascii_table 0.9.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bb6b0e8f1e8883e91e280970a4a75134b7e14fb8
4
+ data.tar.gz: 06c5af666a7641975c73b04fbd53c3efc1a9cbe1
5
+ SHA512:
6
+ metadata.gz: ae1549f7b827d8d94e2de1269e3f8c9a2e055bd317b07e9d46b39a3676e4f85e98fa3c65e3e7384affc2ab125d748b785b1bbdea3b3f8d5757667e783c87d51c
7
+ data.tar.gz: 4df223cf10e81b60782ebb6bb63727173b9a59b103a088477499d097608441416143af4825fb07e57ee73862a5b3bdf7a072c967b2ccad3ff47dc27c856c65bb
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ascii_table.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Peter Suschlik
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,38 @@
1
+ # AsciiTable
2
+
3
+ Create ascii table from command line using [terminal-table](https://github.com/tj/terminal-table/)
4
+
5
+ ## Installation
6
+
7
+ Install it yourself as:
8
+
9
+ ```shell
10
+ gem install ascii_table
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```shell
16
+ $ ascii_table -h
17
+
18
+ Message: Help!
19
+
20
+ Usage: cat data.csv | ascii_table -H -d ";" [options]
21
+
22
+ -d, --delimiter DELIMITER Delimiter. Default: ;
23
+ -H, --header First line is header. Default: no
24
+ -A, --table-align POSITION Align all cells to POSITION. Default left
25
+ -a, --align COLUMN1=POSITION,... All specific cell to. Example 1=left,3=right,4=center
26
+ -s, --separator SEPARATOR Add a separator. Default: empty line
27
+ -h, --help Help
28
+
29
+ ```
30
+
31
+
32
+ ## Contributing
33
+
34
+ 1. Fork it ( https://github.com/neopoly/ascii_table/fork )
35
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
36
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
37
+ 4. Push to the branch (`git push origin my-new-feature`)
38
+ 5. Create a new Pull Request
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require "rake/testtask"
4
+ Rake::TestTask.new(:spec) do |test|
5
+ test.test_files = FileList.new('spec/**/*_spec.rb')
6
+ test.libs << 'spec'
7
+ test.verbose = true
8
+ end
9
+
10
+ task :default => :spec
@@ -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 'ascii_table/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ascii_table"
8
+ spec.version = AsciiTable::VERSION
9
+ spec.authors = ["Peter Suschlik"]
10
+ spec.email = ["ps@neopoly.de"]
11
+ spec.summary = %q{Create ascii table from command line}
12
+ spec.description = spec.summary
13
+ spec.homepage = "https://github.com/neopoly/ascii_table"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_runtime_dependency "terminal-table", "~> 1.4"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.7"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "minitest", "~> 5.5"
26
+ end
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'ascii_table'
5
+
6
+ begin
7
+ puts AsciiTable.new(ARGV, STDIN)
8
+ rescue AsciiTable::AbortError => e
9
+ puts e.message
10
+ end
@@ -0,0 +1,126 @@
1
+ require 'terminal-table'
2
+ require 'optparse'
3
+ require 'ostruct'
4
+
5
+ class AsciiTable
6
+
7
+ class AbortError < StandardError; end
8
+
9
+ attr_reader :options, :table, :parser
10
+
11
+ DELIMITER_MAP = {
12
+ "t" => "\t",
13
+ "0" => "\0",
14
+ "v" => "\v",
15
+ "r" => "\r"
16
+ }
17
+
18
+ def initialize(args, reader)
19
+ @table = nil
20
+ @parser = nil
21
+ @input = []
22
+ # defaults
23
+ @options = OpenStruct.new(
24
+ :delimiter => ";",
25
+ :headings => false,
26
+ :table_align => :left,
27
+ :cell_align => {},
28
+ :separator => ""
29
+ )
30
+
31
+ parse_options!(args)
32
+ read_input!(reader)
33
+ end
34
+
35
+ def to_s
36
+ generate_table! unless @table
37
+ @table.to_s
38
+ end
39
+
40
+ private
41
+
42
+ def generate_table!
43
+ @table = ::Terminal::Table.new
44
+ draw_header if @options.header
45
+ add_rows
46
+ align_rows
47
+ end
48
+
49
+ def draw_header
50
+ @table.headings = format_line(@input.shift)
51
+ end
52
+
53
+ def add_rows
54
+ @input.each do |line|
55
+ if @options.separator == line
56
+ @table.add_separator
57
+ else
58
+ @table.add_row format_line(line)
59
+ end
60
+ end
61
+ end
62
+
63
+ def align_rows
64
+ @table.number_of_columns.times do |i|
65
+ alignment = @options.cell_align[i + 1] || @options.table_align
66
+ @table.align_column(i, alignment)
67
+ end
68
+ end
69
+
70
+ def exit!(message)
71
+ message = "\nMessage: #{message}\n\n"
72
+ raise AbortError.new(message + @parser.help)
73
+ end
74
+
75
+ def format_line(line)
76
+ line.split(@options.delimiter)
77
+ end
78
+
79
+ def parse_options!(args)
80
+ OptionParser.new do |opts|
81
+ @parser = opts # HACK
82
+
83
+ opts.separator ""
84
+
85
+ opts.banner = %(Usage: cat data.csv | #{opts.program_name} -H -d ";" [options])
86
+
87
+ opts.on("-d", "--delimiter DELIMITER", "Delimiter. Default: ;") { |d| @options.delimiter = map_delimiter(d) }
88
+ opts.on("-H", "--header", "First line is header. Default: no") { @options.header = true }
89
+ opts.on("-A", "--table-align POSITION", "Align all cells to POSITION. Default left") { |a| @options.table_align = a.to_sym }
90
+ opts.on("-a", "--align COLUMN1=POSITION,...", "All specific cell to. Example 1=left,3=right,4=center") do |a|
91
+ a.split(/,/).each do |b|
92
+ column, position = b.split(/=/)
93
+ @options.cell_align[column.to_i] = position.to_sym
94
+ end
95
+ end
96
+ opts.on("-s", "--separator SEPARATOR", "Add a separator. Default: empty line") { |s| @options.separator = s }
97
+
98
+ opts.on("-h", "--help", "Help") { exit!("Help!") }
99
+
100
+ opts.separator ""
101
+ end
102
+
103
+ @parser.parse!(args)
104
+
105
+ rescue OptionParser::InvalidOption => e
106
+ exit!(e.message)
107
+ end
108
+
109
+ def map_delimiter(delimiter)
110
+ # TODO refactor
111
+ parts = delimiter.split(/\\/).reject { |part| part.empty? }.map do |part|
112
+ DELIMITER_MAP[part] || part
113
+ end
114
+ parts.join("")
115
+ end
116
+
117
+ def read_input!(reader)
118
+ exit!("Need input!") if reader.tty?
119
+
120
+ @input = reader.readlines.map { |l| l.chomp }
121
+
122
+ exit!("Empty input") if @input.empty?
123
+ exit!("Need rows!") if @options.header && @input.size == 1
124
+ end
125
+
126
+ end
@@ -0,0 +1,3 @@
1
+ class AsciiTable
2
+ VERSION = "0.9.0"
3
+ end
@@ -0,0 +1,161 @@
1
+ require "spec_helper"
2
+
3
+ describe AsciiTable do
4
+ describe "instance" do
5
+ describe "with default options" do
6
+ subject { ascii_table([]) }
7
+ let(:options) { subject.options }
8
+
9
+ it "has delimiter ;" do
10
+ assert_equal ";", options.delimiter
11
+ end
12
+
13
+ it "has no heading" do
14
+ assert_equal false, options.headings
15
+ end
16
+
17
+ it "has table aligment set to :left" do
18
+ assert_equal :left, options.table_align
19
+ end
20
+
21
+ it "has no cell aligments" do
22
+ assert_equal Hash.new, options.cell_align
23
+ end
24
+
25
+ it "has no separator" do
26
+ assert_equal "", options.separator
27
+ end
28
+ end
29
+
30
+ describe "parsing option" do
31
+ describe "help" do
32
+ it "parses short" do
33
+ assert_abort_with /Help/ do
34
+ ascii_table(%w(-h))
35
+ end
36
+ end
37
+
38
+ it "parses long" do
39
+ assert_abort_with /Help/ do
40
+ ascii_table(%w(---help))
41
+ end
42
+ end
43
+
44
+ it "help on invalid option" do
45
+ assert_abort_with /Help/ do
46
+ ascii_table(%w(---invalid-option))
47
+ end
48
+ end
49
+ end
50
+
51
+ describe "short" do
52
+ subject { ascii_table(%w(-d , -H -A right -a 1=left,2=right -s XXX)) }
53
+ let(:options) { subject.options }
54
+
55
+ it "parses delimiter" do
56
+ assert_equal ",", options.delimiter
57
+ end
58
+
59
+ it "parses header" do
60
+ assert_equal true, options.header
61
+ end
62
+
63
+ it "parses table_align" do
64
+ assert_equal :right, options.table_align
65
+ end
66
+
67
+ it "parses cell_align" do
68
+ assert_equal Hash[1 => :left, 2 => :right], options.cell_align
69
+ end
70
+
71
+ it "parses separator" do
72
+ assert_equal "XXX", options.separator
73
+ end
74
+ end
75
+
76
+ describe "long" do
77
+ subject { ascii_table(%w(--delimiter , --header --table-align right --align 1=left,2=right --separator XXX)) }
78
+ let(:options) { subject.options }
79
+
80
+ it "parses delimiter" do
81
+ assert_equal ",", options.delimiter
82
+ end
83
+
84
+ it "parses header" do
85
+ assert_equal true, options.header
86
+ end
87
+
88
+ it "parses table_align" do
89
+ assert_equal :right, options.table_align
90
+ end
91
+
92
+ it "parses cell_align" do
93
+ assert_equal Hash[1 => :left, 2 => :right], options.cell_align
94
+ end
95
+
96
+ it "parses separator" do
97
+ assert_equal "XXX", options.separator
98
+ end
99
+ end
100
+
101
+ describe "delimiter" do
102
+ attr_accessor :switches
103
+ subject { ascii_table(switches) }
104
+ let(:options) { subject.options }
105
+
106
+ it "parses tab" do
107
+ self.switches = %w(-d \t)
108
+ assert_equal "\t", options.delimiter
109
+ end
110
+
111
+ it "parses 2 tabs" do
112
+ self.switches = %w(-d \t\t)
113
+ assert_equal "\t\t", options.delimiter
114
+ end
115
+ end
116
+ end
117
+
118
+ describe "reading input" do
119
+ it "not bound to tty" do
120
+ assert_abort_with /Need input/ do
121
+ ascii_table([], FakeStdin[].tty!)
122
+ end
123
+ end
124
+
125
+ it "needs at least one row without headers" do
126
+ assert_abort_with /Empty input/ do
127
+ ascii_table([], FakeStdin[])
128
+ end
129
+ end
130
+
131
+ it "needs at least one row with header" do
132
+ assert_abort_with /Need rows/ do
133
+ ascii_table([%(-H)], FakeStdin[%w(a)])
134
+ end
135
+ end
136
+ end
137
+
138
+ describe "generating table" do
139
+ def self.generates(description, args, file)
140
+ it "generates #{description}" do
141
+ input = fixture("#{file}.csv")
142
+ expected = fixture("#{file}.txt").read.chomp
143
+
144
+ actual = ascii_table(args, input).to_s
145
+
146
+ assert_equal expected, actual
147
+ end
148
+ end
149
+
150
+ generates "without header", %w(), "without_header"
151
+ generates "with header", %w(-H), "with_header"
152
+ generates "with table_align", %w(-A right), "table_align"
153
+ generates "with cell_align", %w(-a 2=right,3=center,4=left), "cell_align"
154
+ generates "delimited", ["-d" "||"], "delimited"
155
+ generates "with tab delimited", ["-d", "\\t"], "tab_delimited"
156
+ generates "with separators", [], "separator"
157
+ end
158
+
159
+ end
160
+
161
+ end
@@ -0,0 +1,3 @@
1
+ xxxxxx;xxxxx;xxxxx;xxxxx
2
+ aaa;bbb;ccc;dddd
3
+ a;b;c;d
@@ -0,0 +1,5 @@
1
+ +--------+-------+-------+-------+
2
+ | xxxxxx | xxxxx | xxxxx | xxxxx |
3
+ | aaa | bbb | ccc | dddd |
4
+ | a | b | c | d |
5
+ +--------+-------+-------+-------+
@@ -0,0 +1,2 @@
1
+ a||b
2
+ c||d
@@ -0,0 +1,4 @@
1
+ +---+---+
2
+ | a | b |
3
+ | c | d |
4
+ +---+---+
@@ -0,0 +1,5 @@
1
+ 1;2
2
+ 3;4
3
+ 5;6
4
+
5
+ 8;12
@@ -0,0 +1,7 @@
1
+ +---+----+
2
+ | 1 | 2 |
3
+ | 3 | 4 |
4
+ | 5 | 6 |
5
+ +---+----+
6
+ | 8 | 12 |
7
+ +---+----+
@@ -0,0 +1,2 @@
1
+ a b
2
+ c d
@@ -0,0 +1,4 @@
1
+ +---+---+
2
+ | a | b |
3
+ | c | d |
4
+ +---+---+
@@ -0,0 +1,2 @@
1
+ aaa;bbb
2
+ c;d
@@ -0,0 +1,4 @@
1
+ +-----+-----+
2
+ | aaa | bbb |
3
+ | c | d |
4
+ +-----+-----+
@@ -0,0 +1,2 @@
1
+ Hätst
2
+ world
@@ -0,0 +1,2 @@
1
+ a;b
2
+ c;d
@@ -0,0 +1,5 @@
1
+ +---+---+
2
+ | a | b |
3
+ +---+---+
4
+ | c | d |
5
+ +---+---+
@@ -0,0 +1,2 @@
1
+ a;b
2
+ c;d
@@ -0,0 +1,4 @@
1
+ +---+---+
2
+ | a | b |
3
+ | c | d |
4
+ +---+---+
@@ -0,0 +1,36 @@
1
+ require "minitest/autorun"
2
+
3
+ require "ascii_table"
4
+
5
+ class FakeStdin < StringIO
6
+ def self.[](*args)
7
+ new(args.join("\n"))
8
+ end
9
+
10
+ def tty?
11
+ @tty ||= false
12
+ end
13
+
14
+ def tty!
15
+ @tty = true
16
+ self
17
+ end
18
+ end
19
+
20
+ Minitest::Spec.class_eval do
21
+ def ascii_table(args, stdin=FakeStdin[%w(a b)])
22
+ AsciiTable.new(Array(args), stdin)
23
+ end
24
+
25
+ def fixture(name)
26
+ name = File.join(File.dirname(__FILE__), "fixtures", name)
27
+ FakeStdin[File.read(name)]
28
+ end
29
+
30
+ def assert_abort_with(regexp)
31
+ e = assert_raises AsciiTable::AbortError do
32
+ yield
33
+ end
34
+ assert_match regexp, e.message
35
+ end
36
+ end
metadata ADDED
@@ -0,0 +1,144 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ascii_table
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ platform: ruby
6
+ authors:
7
+ - Peter Suschlik
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: terminal-table
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.7'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '5.5'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '5.5'
69
+ description: Create ascii table from command line
70
+ email:
71
+ - ps@neopoly.de
72
+ executables:
73
+ - ascii_table
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - ascii_table.gemspec
83
+ - bin/ascii_table
84
+ - lib/ascii_table.rb
85
+ - lib/ascii_table/version.rb
86
+ - spec/ascii_table_spec.rb
87
+ - spec/fixtures/cell_align.csv
88
+ - spec/fixtures/cell_align.txt
89
+ - spec/fixtures/delimited.csv
90
+ - spec/fixtures/delimited.txt
91
+ - spec/fixtures/separator.csv
92
+ - spec/fixtures/separator.txt
93
+ - spec/fixtures/tab_delimited.csv
94
+ - spec/fixtures/tab_delimited.txt
95
+ - spec/fixtures/table_align.csv
96
+ - spec/fixtures/table_align.txt
97
+ - spec/fixtures/umlaute.csv
98
+ - spec/fixtures/with_header.csv
99
+ - spec/fixtures/with_header.txt
100
+ - spec/fixtures/without_header.csv
101
+ - spec/fixtures/without_header.txt
102
+ - spec/spec_helper.rb
103
+ homepage: https://github.com/neopoly/ascii_table
104
+ licenses:
105
+ - MIT
106
+ metadata: {}
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubyforge_project:
123
+ rubygems_version: 2.2.2
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: Create ascii table from command line
127
+ test_files:
128
+ - spec/ascii_table_spec.rb
129
+ - spec/fixtures/cell_align.csv
130
+ - spec/fixtures/cell_align.txt
131
+ - spec/fixtures/delimited.csv
132
+ - spec/fixtures/delimited.txt
133
+ - spec/fixtures/separator.csv
134
+ - spec/fixtures/separator.txt
135
+ - spec/fixtures/tab_delimited.csv
136
+ - spec/fixtures/tab_delimited.txt
137
+ - spec/fixtures/table_align.csv
138
+ - spec/fixtures/table_align.txt
139
+ - spec/fixtures/umlaute.csv
140
+ - spec/fixtures/with_header.csv
141
+ - spec/fixtures/with_header.txt
142
+ - spec/fixtures/without_header.csv
143
+ - spec/fixtures/without_header.txt
144
+ - spec/spec_helper.rb