squib 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +162 -133
  3. data/Gemfile +4 -4
  4. data/README.md +630 -550
  5. data/RELEASE TODO.md +18 -18
  6. data/Rakefile +99 -99
  7. data/lib/squib.rb +32 -32
  8. data/lib/squib/api/background.rb +20 -19
  9. data/lib/squib/api/data.rb +100 -99
  10. data/lib/squib/api/image.rb +90 -76
  11. data/lib/squib/api/save.rb +149 -103
  12. data/lib/squib/api/settings.rb +35 -37
  13. data/lib/squib/api/shapes.rb +230 -228
  14. data/lib/squib/api/text.rb +65 -66
  15. data/lib/squib/api/text_embed.rb +96 -66
  16. data/lib/squib/args/arg_loader.rb +138 -0
  17. data/lib/squib/args/box.rb +55 -0
  18. data/lib/squib/args/card_range.rb +32 -0
  19. data/lib/squib/args/color_validator.rb +12 -0
  20. data/lib/squib/args/coords.rb +33 -0
  21. data/lib/squib/args/dir_validator.rb +16 -0
  22. data/lib/squib/args/draw.rb +92 -0
  23. data/lib/squib/args/embed_adjust.rb +25 -0
  24. data/lib/squib/args/embed_key.rb +17 -0
  25. data/lib/squib/args/hand_special.rb +37 -0
  26. data/lib/squib/args/input_file.rb +37 -0
  27. data/lib/squib/args/paint.rb +44 -0
  28. data/lib/squib/args/paragraph.rb +115 -0
  29. data/lib/squib/args/save_batch.rb +60 -0
  30. data/lib/squib/args/scale_box.rb +53 -0
  31. data/lib/squib/args/sheet.rb +72 -0
  32. data/lib/squib/args/showcase_special.rb +38 -0
  33. data/lib/squib/args/svg_special.rb +37 -0
  34. data/lib/squib/args/transform.rb +25 -0
  35. data/lib/squib/args/typographer.rb +117 -117
  36. data/lib/squib/card.rb +67 -67
  37. data/lib/squib/conf.rb +117 -111
  38. data/lib/squib/constants.rb +178 -178
  39. data/lib/squib/deck.rb +113 -111
  40. data/lib/squib/graphics/cairo_context_wrapper.rb +99 -53
  41. data/lib/squib/graphics/gradient_regex.rb +46 -46
  42. data/lib/squib/graphics/hand.rb +42 -43
  43. data/lib/squib/graphics/image.rb +76 -73
  44. data/lib/squib/graphics/save_doc.rb +103 -137
  45. data/lib/squib/graphics/save_images.rb +33 -33
  46. data/lib/squib/graphics/shapes.rb +119 -152
  47. data/lib/squib/graphics/showcase.rb +85 -88
  48. data/lib/squib/graphics/text.rb +176 -216
  49. data/lib/squib/layout_parser.rb +91 -89
  50. data/lib/squib/layouts/economy.yml +85 -0
  51. data/lib/squib/layouts/fantasy.yml +101 -0
  52. data/lib/squib/layouts/hand.yml +62 -46
  53. data/lib/squib/layouts/playing-card.yml +35 -18
  54. data/lib/squib/project_template/config.yml +45 -40
  55. data/lib/squib/version.rb +10 -10
  56. data/samples/color_shortcuts.rb +6 -0
  57. data/samples/csv_import.rb +18 -18
  58. data/samples/custom-config.yml +5 -5
  59. data/samples/custom_config.rb +18 -18
  60. data/samples/draw_shapes.rb +45 -35
  61. data/samples/embed_text.rb +88 -90
  62. data/samples/hand.rb +24 -24
  63. data/samples/layouts.rb +62 -61
  64. data/samples/layouts_builtin.rb +51 -0
  65. data/samples/load_images.rb +78 -64
  66. data/samples/ranges.rb +64 -53
  67. data/samples/sample.csv +2 -2
  68. data/samples/text_options.rb +102 -94
  69. data/spec/api/api_data_spec.rb +57 -50
  70. data/spec/api/api_settings_spec.rb +37 -17
  71. data/spec/args/box_spec.rb +127 -0
  72. data/spec/args/draw_spec.rb +95 -0
  73. data/spec/args/embed_key_spec.rb +13 -0
  74. data/spec/args/input_file_spec.rb +21 -0
  75. data/spec/args/paint_spec.rb +22 -0
  76. data/spec/args/paragraph_spec.rb +153 -0
  77. data/spec/args/range_spec.rb +36 -0
  78. data/spec/args/save_batch_spec.rb +51 -0
  79. data/spec/args/scale_box_spec.rb +71 -0
  80. data/spec/args/sheet_spec.rb +58 -0
  81. data/spec/args/showcase_special_spec.rb +15 -0
  82. data/spec/data/samples/autoscale_font.rb.txt +84 -87
  83. data/spec/data/samples/basic.rb.txt +209 -203
  84. data/spec/data/samples/cairo_access.rb.txt +2 -2
  85. data/spec/data/samples/config_text_markup.rb.txt +72 -75
  86. data/spec/data/samples/csv_import.rb.txt +76 -80
  87. data/spec/data/samples/custom_config.rb.txt +48 -49
  88. data/spec/data/samples/draw_shapes.rb.txt +100 -42
  89. data/spec/data/samples/embed_text.rb.txt +283 -295
  90. data/spec/data/samples/excel.rb.txt +162 -171
  91. data/spec/data/samples/gradients.rb.txt +79 -67
  92. data/spec/data/samples/hand.rb.txt +538 -514
  93. data/spec/data/samples/hello_world.rb.txt +36 -38
  94. data/spec/data/samples/load_images.rb.txt +41 -5
  95. data/spec/data/samples/portrait-landscape.rb.txt +49 -51
  96. data/spec/data/samples/ranges.rb.txt +460 -429
  97. data/spec/data/samples/saves.rb.txt +801 -785
  98. data/spec/data/samples/showcase.rb.txt +5910 -5906
  99. data/spec/data/samples/text_options.rb.txt +1125 -981
  100. data/spec/data/samples/tgc_proofs.rb.txt +81 -79
  101. data/spec/data/samples/units.rb.txt +18 -12
  102. data/spec/data/xlsx/with_macros.xlsm +0 -0
  103. data/spec/graphics/cairo_context_wrapper_spec.rb +84 -75
  104. data/spec/graphics/graphics_images_spec.rb +94 -85
  105. data/spec/graphics/graphics_save_doc_spec.rb +67 -65
  106. data/spec/samples/expected/hand.png +0 -0
  107. data/spec/samples/expected/hand_pretty.png +0 -0
  108. data/spec/samples/expected/layout_00.png +0 -0
  109. data/spec/samples/expected/load_images_00.png +0 -0
  110. data/spec/samples/expected/ranges_00.png +0 -0
  111. data/spec/samples/expected/shape_00.png +0 -0
  112. data/spec/samples/expected/showcase.png +0 -0
  113. data/spec/samples/expected/showcase2.png +0 -0
  114. data/spec/samples/expected/showcase_individual_00.png +0 -0
  115. data/spec/samples/expected/showcase_individual_01.png +0 -0
  116. data/spec/samples/expected/showcase_individual_02.png +0 -0
  117. data/spec/samples/expected/showcase_individual_03.png +0 -0
  118. data/spec/samples/expected/text_00.png +0 -0
  119. data/spec/samples/expected/text_01.png +0 -0
  120. data/spec/samples/expected/text_02.png +0 -0
  121. data/spec/samples/samples_regression_spec.rb +82 -82
  122. data/spec/spec_helper.rb +3 -2
  123. data/squib.gemspec +48 -48
  124. data/squib.sublime-project +42 -36
  125. metadata +61 -33
  126. data/lib/squib/input_helpers.rb +0 -238
  127. data/spec/api/api_image_spec.rb +0 -38
  128. data/spec/api/api_text_spec.rb +0 -37
  129. data/spec/graphics/graphics_shapes_spec.rb +0 -85
  130. data/spec/graphics/graphics_text_spec.rb +0 -164
  131. data/spec/input_helpers_spec.rb +0 -238
  132. data/spec/samples/expected/embed_multi_00.png +0 -0
  133. data/spec/samples/expected/embed_multi_01.png +0 -0
  134. data/spec/samples/expected/embed_multi_02.png +0 -0
  135. data/spec/samples/expected/ranges_01.png +0 -0
  136. data/spec/samples/expected/ranges_02.png +0 -0
@@ -1,18 +1,18 @@
1
- Be sure to remember to do the following for releases. (Copy into a GitHub issue)
2
-
3
- - [ ] CHANGELOG is written for all new changes
4
- - [ ] README is updated
5
- - [ ] Samples are updated
6
- - [ ] `rake doc`
7
- - [ ] Check `sample_regression_spec.rb` regression tests are all enabled (i.e. `overwrite_sample` is commented out)
8
- - [ ] Bump version.rb
9
- - [ ] Do a full rake locally
10
- - [ ] `rake sanity`, and check visually
11
- - [ ] Travis is passing on dev branch
12
- - [ ] Merge master branch
13
- - [ ] Create GitHub release tag
14
- - [ ] `gem push pkg/squib-x.y.z.gem`
15
- - [ ] Github milestone closed
16
- - [ ] Push `rake doc` to website
17
- - [ ] Bump version.rb to the next alpha
18
- - [ ] Publish on BoardGameGeek thread
1
+ Be sure to remember to do the following for releases. (Copy into a GitHub issue)
2
+
3
+ - [ ] CHANGELOG is written for all new changes
4
+ - [ ] README is updated
5
+ - [ ] Samples are updated
6
+ - [ ] `rake doc`
7
+ - [ ] Check `sample_regression_spec.rb` regression tests are all enabled (i.e. `overwrite_sample` is commented out)
8
+ - [ ] Bump version.rb
9
+ - [ ] Do a full rake locally
10
+ - [ ] `rake sanity`, and check visually
11
+ - [ ] Travis is passing on dev branch
12
+ - [ ] Merge master branch
13
+ - [ ] Create GitHub release tag
14
+ - [ ] `gem push pkg/squib-x.y.z.gem`
15
+ - [ ] Github milestone closed
16
+ - [ ] Push `rake doc` to website
17
+ - [ ] Bump version.rb to the next alpha
18
+ - [ ] Publish on BoardGameGeek thread
data/Rakefile CHANGED
@@ -1,99 +1,99 @@
1
- require 'bundler/gem_tasks'
2
- require 'rspec/core/rake_task'
3
- require 'yard'
4
- require 'benchmark'
5
- require 'byebug'
6
-
7
- task default: [:install, :spec]
8
-
9
- # Useful for hooking up with SublimeText.
10
- # e.g. rake sample[basic.rb]
11
- task :run,[:file] => :install do |t, args|
12
- args.with_defaults(file: 'basic.rb')
13
- Dir.chdir('samples') do
14
- args[:file] << ".rb" unless args[:file].end_with? '.rb'
15
- puts "Running samples/#{args[:file]}"
16
- load args[:file]
17
- end
18
- end
19
-
20
-
21
- RSpec::Core::RakeTask.new(:spec)
22
-
23
- RSpec::Core::RakeTask.new(:spec_fastonly) do |t|
24
- t.rspec_opts = "--tag ~slow"
25
- end
26
-
27
- task doc: [:yarddoc, :apply_google_analytics]
28
-
29
- YARD::Rake::YardocTask.new(:yarddoc) do |t|
30
- t.files = ['lib/**/*.rb', 'samples/**/*.rb'] # optional
31
- #t.options = ['--any', '--extra', '--opts'] # optional
32
- end
33
-
34
- task benchmark: [:install] do
35
- require 'squib'
36
- Squib::logger.level = Logger::ERROR #silence warnings
37
- Dir.chdir('benchmarks') do
38
- Benchmark.bm(15) do |bm|
39
- Dir['*.rb'].each do | script |
40
- GC.start
41
- bm.report(script) { load script }
42
- end
43
- end
44
- end
45
- end
46
-
47
- task :sanity do
48
- require_relative 'spec/samples/sanity.rb'
49
- Sanity.new.run
50
- end
51
-
52
- task sanity_clean: [:install, :spec, :sanity]
53
-
54
- task :apply_google_analytics do
55
- # The string to replace in the html document. This is chosen to be the end
56
- # body </body> tag. So the script can be injected as the last thing in the
57
- # document body.
58
- string_to_replace = "</body>"
59
- # This is the string to replace with. It include the google analytics script
60
- # as well as the end </body> tag.
61
- string_to_replace_with = <<-EOF
62
- <script>
63
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
64
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
65
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
66
- })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
67
-
68
- ga('create', 'UA-54811605-1', 'auto');
69
- ga('send', 'pageview');
70
-
71
- </script>
72
- </body>
73
- EOF
74
-
75
- files = Dir.glob("doc/**/*.html")
76
-
77
- files.each do |html_file|
78
- puts "Processing file: #{html_file}"
79
- contents = ""
80
- # Read the file contents
81
- file = File.open(html_file)
82
- file.each { |line| contents << line }
83
- file.close
84
-
85
- # If the file already has google analytics tracking info, skip it.
86
- if contents.include?(string_to_replace_with)
87
- puts "Skipped..."
88
- next
89
- end
90
-
91
- # Apply google analytics tracking info to the html file
92
- contents.gsub!(string_to_replace, string_to_replace_with)
93
-
94
- # Write the contents with the google analytics info to the file
95
- file = File.open(html_file, "w")
96
- file.write(contents)
97
- file.close
98
- end
99
- end
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'yard'
4
+ require 'benchmark'
5
+ require 'byebug'
6
+
7
+ task default: [:install, :spec]
8
+
9
+ # Useful for hooking up with SublimeText.
10
+ # e.g. rake sample[basic.rb]
11
+ task :run,[:file] => :install do |t, args|
12
+ args.with_defaults(file: 'basic.rb')
13
+ Dir.chdir('samples') do
14
+ args[:file] << ".rb" unless args[:file].end_with? '.rb'
15
+ puts "Running samples/#{args[:file]}"
16
+ load args[:file]
17
+ end
18
+ end
19
+
20
+
21
+ RSpec::Core::RakeTask.new(:spec)
22
+
23
+ RSpec::Core::RakeTask.new(:spec_fastonly) do |t|
24
+ t.rspec_opts = "--tag ~slow"
25
+ end
26
+
27
+ task doc: [:yarddoc, :apply_google_analytics]
28
+
29
+ YARD::Rake::YardocTask.new(:yarddoc) do |t|
30
+ t.files = ['lib/**/*.rb', 'samples/**/*.rb'] # optional
31
+ #t.options = ['--any', '--extra', '--opts'] # optional
32
+ end
33
+
34
+ task benchmark: [:install] do
35
+ require 'squib'
36
+ Squib::logger.level = Logger::ERROR #silence warnings
37
+ Dir.chdir('benchmarks') do
38
+ Benchmark.bm(15) do |bm|
39
+ Dir['*.rb'].each do | script |
40
+ GC.start
41
+ bm.report(script) { load script }
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ task :sanity_only do
48
+ require_relative 'spec/samples/sanity.rb'
49
+ Sanity.new.run
50
+ end
51
+
52
+ task sanity: [:install, :spec, :sanity_only]
53
+
54
+ task :apply_google_analytics do
55
+ # The string to replace in the html document. This is chosen to be the end
56
+ # body </body> tag. So the script can be injected as the last thing in the
57
+ # document body.
58
+ string_to_replace = "</body>"
59
+ # This is the string to replace with. It include the google analytics script
60
+ # as well as the end </body> tag.
61
+ string_to_replace_with = <<-EOF
62
+ <script>
63
+ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
64
+ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
65
+ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
66
+ })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
67
+
68
+ ga('create', 'UA-54811605-1', 'auto');
69
+ ga('send', 'pageview');
70
+
71
+ </script>
72
+ </body>
73
+ EOF
74
+
75
+ files = Dir.glob("doc/**/*.html")
76
+
77
+ files.each do |html_file|
78
+ puts "Processing file: #{html_file}"
79
+ contents = ""
80
+ # Read the file contents
81
+ file = File.open(html_file)
82
+ file.each { |line| contents << line }
83
+ file.close
84
+
85
+ # If the file already has google analytics tracking info, skip it.
86
+ if contents.include?(string_to_replace_with)
87
+ puts "Skipped..."
88
+ next
89
+ end
90
+
91
+ # Apply google analytics tracking info to the html file
92
+ contents.gsub!(string_to_replace, string_to_replace_with)
93
+
94
+ # Write the contents with the google analytics info to the file
95
+ file = File.open(html_file, "w")
96
+ file.write(contents)
97
+ file.close
98
+ end
99
+ end
@@ -1,32 +1,32 @@
1
- require 'logger'
2
- require 'cairo'
3
- require 'pango'
4
- require 'rsvg2'
5
- require 'squib/version'
6
- require 'squib/commands/new'
7
- require 'squib/deck'
8
- require 'squib/card'
9
-
10
- module Squib
11
-
12
- # Access the internal logger that Squib uses. By default, Squib configure the logger to the WARN level
13
- # Use this to suppress or increase output levels.
14
- # @example
15
- # Squib.logger.level = Logger::DEBUG #show waaaay more information than you probably need, unless you're a dev
16
- # Squib.logger.level = Logger::ERROR #basically turns it off
17
- #
18
- # @return [Logger] the ruby logger
19
- # @api public
20
- def logger
21
- if @logger.nil?
22
- @logger = Logger.new($stdout);
23
- @logger.level = Logger::WARN;
24
- @logger.formatter = proc do |severity, datetime, m_progname, msg|
25
- "#{datetime} #{severity}: #{msg}\n"
26
- end
27
- end
28
- @logger
29
- end
30
- module_function :logger
31
-
32
- end
1
+ require 'logger'
2
+ require 'cairo'
3
+ require 'pango'
4
+ require 'rsvg2'
5
+ require 'squib/version'
6
+ require 'squib/commands/new'
7
+ require 'squib/deck'
8
+ require 'squib/card'
9
+
10
+ module Squib
11
+
12
+ # Access the internal logger that Squib uses. By default, Squib configure the logger to the WARN level
13
+ # Use this to suppress or increase output levels.
14
+ # @example
15
+ # Squib.logger.level = Logger::DEBUG #show waaaay more information than you probably need, unless you're a dev
16
+ # Squib.logger.level = Logger::ERROR #basically turns it off
17
+ #
18
+ # @return [Logger] the ruby logger
19
+ # @api public
20
+ def logger
21
+ if @logger.nil?
22
+ @logger = Logger.new($stdout)
23
+ @logger.level = Logger::WARN
24
+ @logger.formatter = proc do |severity, datetime, m_progname, msg|
25
+ "#{datetime} #{severity}: #{msg}\n"
26
+ end
27
+ end
28
+ @logger
29
+ end
30
+ module_function :logger
31
+
32
+ end
@@ -1,19 +1,20 @@
1
- module Squib
2
- class Deck
3
- # Fills the background with the given color
4
- # @example
5
- # background color: :white
6
- #
7
- # Options support Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion}
8
- #
9
- # @option opts range [Enumerable] (:all) the range of cards over which this will be rendered. See {file:README.md#Specifying_Ranges Specifying Ranges}
10
- # @option opts color [String] (:black) the color the font will render to. See {file:README.md#Specifying_Colors___Gradients Specifying Colors & Gradients}.
11
- # @return [nil] nothing
12
- # @api public
13
- def background(opts = {})
14
- opts = needs(opts,[:range, :color])
15
- opts[:range].each { |i| @cards[i].background(opts[:color][i]) }
16
- end
17
-
18
- end
19
- end
1
+ module Squib
2
+ class Deck
3
+ # Fills the background with the given color
4
+ # @example
5
+ # background color: :white
6
+ #
7
+ # Options support Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion}
8
+ #
9
+ # @option opts range [Enumerable] (:all) the range of cards over which this will be rendered. See {file:README.md#Specifying_Ranges Specifying Ranges}
10
+ # @option opts color [String] (:black) the color the font will render to. See {file:README.md#Specifying_Colors___Gradients Specifying Colors & Gradients}.
11
+ # @return [nil] nothing
12
+ # @api public
13
+ def background(opts = {})
14
+ range = Args::CardRange.new(opts[:range], deck_size: size)
15
+ draw = Args::Draw.new(custom_colors).load!(opts, expand_by: size, layout: layout, dpi: dpi)
16
+ range.each { |i| @cards[i].background(draw.color[i]) }
17
+ end
18
+
19
+ end
20
+ end
@@ -1,99 +1,100 @@
1
- require 'roo'
2
- require 'csv'
3
-
4
- module Squib
5
-
6
- # Pulls Excel data from `.xlsx` files into a column-based hash
7
- #
8
- # Pulls the data into a Hash of arrays based on the columns. First row is assumed to be the header row.
9
- # See the example `samples/excel.rb` in the [source repository](https://github.com/andymeneely/squib/tree/master/samples)
10
- #
11
- # @example
12
- # # Excel file looks like this:
13
- # # | h1 | h2 |
14
- # # ------------
15
- # # | 1 | 2 |
16
- # # | 3 | 4 |
17
- # data = xlsx file: 'data.xlsx', sheet: 0
18
- # {'h1' => [1,3], 'h2' => [2,4]}
19
- #
20
- # @option opts file [String] the file to open. Must end in `.xlsx`. Opens relative to the current directory.
21
- # @option opts sheet [Integer] (0) The zero-based index of the sheet from which to read.
22
- # @return [Hash] a hash of arrays based on columns in the spreadsheet
23
- # @api public
24
- def xlsx(opts = {})
25
- opts = Squib::SYSTEM_DEFAULTS.merge(opts)
26
- opts = Squib::InputHelpers.fileify(opts)
27
- s = Roo::Excelx.new(opts[:file])
28
- s.default_sheet = s.sheets[opts[:sheet]]
29
- data = {}
30
- s.first_column.upto(s.last_column) do |col|
31
- header = s.cell(s.first_row,col).to_s
32
- data[header] = []
33
- (s.first_row + 1).upto(s.last_row) do |row|
34
- cell = s.cell(row,col)
35
- # Roo hack for avoiding unnecessary .0's on whole integers (https://github.com/roo-rb/roo/issues/139)
36
- cell = s.excelx_value(row,col) if s.excelx_type(row,col) == [:numeric_or_formula, 'General']
37
- data[header] << cell
38
- end#row
39
- end#col
40
- data
41
- end#xlsx
42
- module_function :xlsx
43
-
44
- # Pulls CSV data from `.csv` files into a column-based hash
45
- #
46
- # Pulls the data into a Hash of arrays based on the columns. First row is assumed to be the header row.
47
- # See the example `samples/csv.rb` in the [source repository](https://github.com/andymeneely/squib/tree/master/samples)
48
- #
49
- # @example
50
- # # File data.csv looks like this (without the comment symbols)
51
- # # h1,h2
52
- # # 1,2
53
- # # 3,4
54
- # data = csv file: 'data.csv'
55
- # => {'h1' => [1,3], 'h2' => [2,4]}
56
- #
57
- # Parsing uses Ruby's CSV, with options `{headers: true, converters: :numeric}`
58
- # http://www.ruby-doc.org/stdlib-2.0/libdoc/csv/rdoc/CSV.html
59
- #
60
- # @option opts file [String] the CSV-formatted file to open. Opens relative to the current directory.
61
- # @return [Hash] a hash of arrays based on columns in the table
62
- # @api public
63
- def csv(opts = {})
64
- opts = Squib::SYSTEM_DEFAULTS.merge(opts)
65
- opts = Squib::InputHelpers.fileify(opts)
66
- table = CSV.read(opts[:file], headers: true, converters: :numeric)
67
- check_duplicate_csv_headers(table)
68
- hash = Hash.new
69
- table.headers.each do |header|
70
- hash[header.to_s] ||= table[header]
71
- end
72
- return hash
73
- end
74
- module_function :csv
75
-
76
- # Check if the given CSV table has duplicate columns, and throw a warning
77
- # @api private
78
- def check_duplicate_csv_headers(table)
79
- if table.headers.size != table.headers.uniq.size
80
- dups = table.headers.select{|e| table.headers.count(e) > 1 }
81
- Squib.logger.warn "CSV duplicated the following column keys: #{dups.join(',')}"
82
- end
83
- end
84
- module_function :check_duplicate_csv_headers
85
-
86
- class Deck
87
-
88
- # Convenience call on deck goes to the module function
89
- def xlsx(opts = {})
90
- Squib.xlsx(opts)
91
- end
92
-
93
- # Convenience call on deck goes to the module function
94
- def csv(opts = {})
95
- Squib.csv(opts)
96
- end
97
-
98
- end
99
- end
1
+ require 'roo'
2
+ require 'csv'
3
+ require 'squib/args/input_file'
4
+
5
+ module Squib
6
+
7
+ # Pulls Excel data from `.xlsx` files into a column-based hash
8
+ #
9
+ # Pulls the data into a Hash of arrays based on the columns. First row is assumed to be the header row.
10
+ # See the example `samples/excel.rb` in the [source repository](https://github.com/andymeneely/squib/tree/master/samples)
11
+ #
12
+ # @example
13
+ # # Excel file looks like this:
14
+ # # | h1 | h2 |
15
+ # # ------------
16
+ # # | 1 | 2 |
17
+ # # | 3 | 4 |
18
+ # data = xlsx file: 'data.xlsx', sheet: 0
19
+ # {'h1' => [1,3], 'h2' => [2,4]}
20
+ #
21
+ # @option opts file [String] the file to open. Must end in `.xlsx`. Opens relative to the current directory.
22
+ # @option opts sheet [Integer] (0) The zero-based index of the sheet from which to read.
23
+ # @return [Hash] a hash of arrays based on columns in the spreadsheet
24
+ # @api public
25
+ def xlsx(opts = {})
26
+ input = Args::InputFile.new(file: 'deck.xlsx').load!(opts)
27
+ s = Roo::Excelx.new(input.file[0])
28
+ s.default_sheet = s.sheets[input.sheet[0]]
29
+ data = {}
30
+ s.first_column.upto(s.last_column) do |col|
31
+ header = s.cell(s.first_row,col).to_s
32
+ data[header] = []
33
+ (s.first_row + 1).upto(s.last_row) do |row|
34
+ cell = s.cell(row,col)
35
+ # Roo hack for avoiding unnecessary .0's on whole integers (https://github.com/roo-rb/roo/issues/139)
36
+ cell = s.excelx_value(row,col) if s.excelx_type(row,col) == [:numeric_or_formula, 'General']
37
+ data[header] << cell
38
+ end#row
39
+ end#col
40
+ data
41
+ end#xlsx
42
+ module_function :xlsx
43
+
44
+ # Pulls CSV data from `.csv` files into a column-based hash
45
+ #
46
+ # Pulls the data into a Hash of arrays based on the columns. First row is assumed to be the header row.
47
+ # See the example `samples/csv.rb` in the [source repository](https://github.com/andymeneely/squib/tree/master/samples)
48
+ #
49
+ # @example
50
+ # # File data.csv looks like this (without the comment symbols)
51
+ # # h1,h2
52
+ # # 1,2
53
+ # # 3,4
54
+ # data = csv file: 'data.csv'
55
+ # => {'h1' => [1,3], 'h2' => [2,4]}
56
+ #
57
+ # Parsing uses Ruby's CSV, with options `{headers: true, converters: :numeric}`
58
+ # http://www.ruby-doc.org/stdlib-2.0/libdoc/csv/rdoc/CSV.html
59
+ #
60
+ # @option opts file [String] the CSV-formatted file to open. Opens relative to the current directory.
61
+ # @return [Hash] a hash of arrays based on columns in the table
62
+ # @api public
63
+ def csv(opts = {})
64
+ file = Args::InputFile.new(file: 'deck.csv').load!(opts).file[0]
65
+ opts = Squib::SYSTEM_DEFAULTS.merge(opts)
66
+ # opts = Squib::InputHelpers.fileify(opts)
67
+ table = CSV.read(file, headers: true, converters: :numeric)
68
+ check_duplicate_csv_headers(table)
69
+ hash = Hash.new
70
+ table.headers.each do |header|
71
+ hash[header.to_s] ||= table[header]
72
+ end
73
+ return hash
74
+ end
75
+ module_function :csv
76
+
77
+ # Check if the given CSV table has duplicate columns, and throw a warning
78
+ # @api private
79
+ def check_duplicate_csv_headers(table)
80
+ if table.headers.size != table.headers.uniq.size
81
+ dups = table.headers.select{|e| table.headers.count(e) > 1 }
82
+ Squib.logger.warn "CSV duplicated the following column keys: #{dups.join(',')}"
83
+ end
84
+ end
85
+ module_function :check_duplicate_csv_headers
86
+
87
+ class Deck
88
+
89
+ # Convenience call on deck goes to the module function
90
+ def xlsx(opts = {})
91
+ Squib.xlsx(opts)
92
+ end
93
+
94
+ # Convenience call on deck goes to the module function
95
+ def csv(opts = {})
96
+ Squib.csv(opts)
97
+ end
98
+
99
+ end
100
+ end