geo_pattern 1.3.2 → 1.4.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.
Files changed (132) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +58 -0
  3. data/.simplecov +25 -0
  4. data/.travis.yml +12 -0
  5. data/Gemfile +3 -1
  6. data/README.md +125 -23
  7. data/Rakefile +72 -9
  8. data/fixtures/generated_patterns/chevrons.svg +1 -0
  9. data/fixtures/generated_patterns/concentric_circles.svg +1 -0
  10. data/fixtures/generated_patterns/diamonds.svg +1 -0
  11. data/fixtures/generated_patterns/diamonds_with_base_color.svg +1 -0
  12. data/fixtures/generated_patterns/diamonds_with_color.svg +1 -0
  13. data/fixtures/generated_patterns/hexagons.svg +1 -0
  14. data/fixtures/generated_patterns/mosaic_squares.svg +1 -0
  15. data/fixtures/generated_patterns/nested_squares.svg +1 -0
  16. data/fixtures/generated_patterns/octagons.svg +1 -0
  17. data/fixtures/generated_patterns/overlapping_circles.svg +1 -0
  18. data/fixtures/generated_patterns/overlapping_rings.svg +1 -0
  19. data/fixtures/generated_patterns/plaid.svg +1 -0
  20. data/fixtures/generated_patterns/plus_signs.svg +1 -0
  21. data/fixtures/generated_patterns/sine_waves.svg +1 -0
  22. data/fixtures/generated_patterns/squares.svg +1 -0
  23. data/fixtures/generated_patterns/tessellation.svg +1 -0
  24. data/fixtures/generated_patterns/triangles.svg +1 -0
  25. data/fixtures/generated_patterns/xes.svg +1 -0
  26. data/geo_pattern.gemspec +8 -2
  27. data/lib/geo_pattern.rb +42 -20
  28. data/lib/geo_pattern/background.rb +25 -0
  29. data/lib/geo_pattern/background_generators/solid_generator.rb +52 -0
  30. data/lib/geo_pattern/color.rb +25 -0
  31. data/lib/geo_pattern/color_generators/base_color_generator.rb +55 -0
  32. data/lib/geo_pattern/color_generators/simple_generator.rb +27 -0
  33. data/lib/geo_pattern/color_preset.rb +26 -0
  34. data/lib/geo_pattern/errors.rb +7 -0
  35. data/lib/geo_pattern/geo_pattern_task.rb +59 -0
  36. data/lib/geo_pattern/helpers.rb +47 -0
  37. data/lib/geo_pattern/pattern.rb +84 -0
  38. data/lib/geo_pattern/pattern_generator.rb +33 -82
  39. data/lib/geo_pattern/pattern_helpers.rb +31 -2
  40. data/lib/geo_pattern/pattern_preset.rb +23 -0
  41. data/lib/geo_pattern/pattern_sieve.rb +36 -0
  42. data/lib/geo_pattern/pattern_store.rb +63 -0
  43. data/lib/geo_pattern/pattern_validator.rb +27 -0
  44. data/lib/geo_pattern/rake_task.rb +109 -0
  45. data/lib/geo_pattern/roles/comparable_metadata.rb +35 -0
  46. data/lib/geo_pattern/roles/named_generator.rb +13 -0
  47. data/lib/geo_pattern/seed.rb +21 -0
  48. data/lib/geo_pattern/structure.rb +25 -0
  49. data/lib/geo_pattern/structure_generators/base_generator.rb +85 -0
  50. data/lib/geo_pattern/structure_generators/chevrons_generator.rb +55 -0
  51. data/lib/geo_pattern/structure_generators/concentric_circles_generator.rb +56 -0
  52. data/lib/geo_pattern/structure_generators/diamonds_generator.rb +66 -0
  53. data/lib/geo_pattern/structure_generators/hexagons_generator.rb +67 -0
  54. data/lib/geo_pattern/structure_generators/mosaic_squares_generator.rb +85 -0
  55. data/lib/geo_pattern/structure_generators/nested_squares_generator.rb +60 -0
  56. data/lib/geo_pattern/structure_generators/octagons_generator.rb +44 -0
  57. data/lib/geo_pattern/structure_generators/overlapping_circles_generator.rb +55 -0
  58. data/lib/geo_pattern/structure_generators/overlapping_rings_generator.rb +55 -0
  59. data/lib/geo_pattern/structure_generators/plaid_generator.rb +55 -0
  60. data/lib/geo_pattern/structure_generators/plus_signs_generator.rb +62 -0
  61. data/lib/geo_pattern/structure_generators/sine_waves_generator.rb +43 -0
  62. data/lib/geo_pattern/structure_generators/squares_generator.rb +36 -0
  63. data/lib/geo_pattern/structure_generators/tessellation_generator.rb +103 -0
  64. data/lib/geo_pattern/structure_generators/triangles_generator.rb +61 -0
  65. data/lib/geo_pattern/structure_generators/xes_generator.rb +67 -0
  66. data/lib/geo_pattern/svg_image.rb +101 -0
  67. data/lib/geo_pattern/version.rb +1 -1
  68. data/script/bootstrap +30 -0
  69. data/script/console +8 -0
  70. data/script/test +21 -0
  71. data/spec/background_generators/solid_generator_spec.rb +50 -0
  72. data/spec/background_spec.rb +25 -0
  73. data/spec/color_generators/base_color_generator_spec.rb +31 -0
  74. data/spec/color_generators/simple_generator_spec.rb +12 -0
  75. data/spec/color_preset_spec.rb +53 -0
  76. data/spec/color_spec.rb +15 -0
  77. data/spec/geo_pattern_spec.rb +95 -24
  78. data/spec/helpers_spec.rb +65 -0
  79. data/spec/pattern_preset_spec.rb +41 -0
  80. data/spec/pattern_sieve_spec.rb +66 -0
  81. data/spec/pattern_spec.rb +72 -0
  82. data/spec/pattern_store_spec.rb +47 -0
  83. data/spec/pattern_validator_spec.rb +28 -0
  84. data/spec/seed_spec.rb +14 -0
  85. data/spec/spec_helper.rb +1 -6
  86. data/spec/structure_generators/chevrons_generator_spec.rb +5 -0
  87. data/spec/structure_generators/concentric_circles_generator_spec.rb +5 -0
  88. data/spec/structure_generators/diamonds_generator_spec.rb +5 -0
  89. data/spec/structure_generators/hexagons_generator_spec.rb +5 -0
  90. data/spec/structure_generators/mosaic_squares_generator_spec.rb +5 -0
  91. data/spec/structure_generators/nested_squares_generator_spec.rb +5 -0
  92. data/spec/structure_generators/octagons_generator_spec.rb +5 -0
  93. data/spec/structure_generators/overlapping_circles_generator_spec.rb +5 -0
  94. data/spec/structure_generators/overlapping_rings_generator_spec.rb +5 -0
  95. data/spec/structure_generators/plaid_generator_spec.rb +5 -0
  96. data/spec/structure_generators/plus_signs_generator_spec.rb +5 -0
  97. data/spec/structure_generators/sine_waves_generator_spec.rb +5 -0
  98. data/spec/structure_generators/squares_generator_spec.rb +5 -0
  99. data/spec/structure_generators/tessellation_generator_spec.rb +5 -0
  100. data/spec/structure_generators/triangles_generator_spec.rb +5 -0
  101. data/spec/structure_generators/xes_generator_spec.rb +5 -0
  102. data/spec/structure_spec.rb +38 -0
  103. data/spec/support/helpers/fixtures.rb +12 -0
  104. data/spec/support/kernel.rb +40 -0
  105. data/spec/support/matchers/image.rb +17 -0
  106. data/spec/support/matchers/name.rb +15 -0
  107. data/spec/support/rspec.rb +1 -1
  108. data/spec/support/shared_examples/generator.rb +46 -0
  109. data/spec/support/shared_examples/pattern.rb +31 -0
  110. data/spec/support/shared_examples/pattern_name.rb +7 -0
  111. data/spec/support/shared_examples/structure.rb +48 -0
  112. data/spec/svg_spec.rb +3 -3
  113. metadata +141 -25
  114. data/lib/geo_pattern/pattern/base_pattern.rb +0 -47
  115. data/lib/geo_pattern/pattern/chevron_pattern.rb +0 -45
  116. data/lib/geo_pattern/pattern/concentric_circles_pattern.rb +0 -47
  117. data/lib/geo_pattern/pattern/diamond_pattern.rb +0 -56
  118. data/lib/geo_pattern/pattern/hexagon_pattern.rb +0 -57
  119. data/lib/geo_pattern/pattern/mosaic_squares_pattern.rb +0 -76
  120. data/lib/geo_pattern/pattern/nested_squares_pattern.rb +0 -51
  121. data/lib/geo_pattern/pattern/octagon_pattern.rb +0 -35
  122. data/lib/geo_pattern/pattern/overlapping_circles_pattern.rb +0 -46
  123. data/lib/geo_pattern/pattern/overlapping_rings_pattern.rb +0 -46
  124. data/lib/geo_pattern/pattern/plaid_pattern.rb +0 -49
  125. data/lib/geo_pattern/pattern/plus_sign_pattern.rb +0 -53
  126. data/lib/geo_pattern/pattern/sine_wave_pattern.rb +0 -36
  127. data/lib/geo_pattern/pattern/square_pattern.rb +0 -27
  128. data/lib/geo_pattern/pattern/tessellation_pattern.rb +0 -93
  129. data/lib/geo_pattern/pattern/triangle_pattern.rb +0 -51
  130. data/lib/geo_pattern/pattern/xes_pattern.rb +0 -58
  131. data/lib/geo_pattern/svg.rb +0 -77
  132. data/spec/support/helpers.rb +0 -34
@@ -0,0 +1,84 @@
1
+ module GeoPattern
2
+ class Pattern
3
+ private
4
+
5
+ attr_reader :svg_image
6
+
7
+ public
8
+
9
+ attr_accessor :background, :structure, :height, :width
10
+
11
+ def initialize(svg_image = SvgImage.new)
12
+ @svg_image = svg_image
13
+ end
14
+
15
+ # Check if string is included in pattern
16
+ #
17
+ # @param [String] string
18
+ # The checked string
19
+ def include?(string)
20
+ image.include?(string)
21
+ end
22
+
23
+ # Generate things for the pattern
24
+ #
25
+ # @param [#generate) generator
26
+ # The generator which should do things with this pattern - e.g. adding
27
+ # background or a structure
28
+ def generate_me(generator)
29
+ generator.generate self
30
+ end
31
+
32
+ # Convert pattern to svg
33
+ def to_svg
34
+ image.to_s
35
+ end
36
+ alias_method :to_s, :to_svg
37
+
38
+ # Convert to base64
39
+ def to_base64
40
+ Base64.strict_encode64(to_svg)
41
+ end
42
+
43
+ # Convert to data uri
44
+ def to_data_uri
45
+ "url(data:image/svg+xml;base64,#{to_base64});"
46
+ end
47
+
48
+ # @see #to_data_uri
49
+ # @deprecated
50
+ def uri_image
51
+ $stderr.puts 'Using "#uri_image" is deprecated as of 1.3.1. Please use "#to_data_uri" instead.'
52
+
53
+ to_data_uri
54
+ end
55
+
56
+ # @see #to_svg
57
+ # @deprecated
58
+ def svg_string
59
+ $stderr.puts 'Using "#svg_string" is deprecated as of 1.3.1. Please use "#to_svg" instead.'
60
+
61
+ to_svg
62
+ end
63
+
64
+ # @see #to_base64
65
+ # @deprecated
66
+ def base64_string
67
+ $stderr.puts 'Using "#base64_string" is deprecated as of 1.3.1. Please use "#to_base64" instead.'
68
+
69
+ to_base64
70
+ end
71
+
72
+ private
73
+
74
+ def image
75
+ svg_image.height = height
76
+ svg_image.width = width
77
+
78
+ svg_image << background.image if background
79
+ svg_image << structure.image if structure
80
+
81
+ svg_image
82
+ end
83
+ end
84
+ end
@@ -1,101 +1,52 @@
1
1
  module GeoPattern
2
2
  class PatternGenerator
3
- DEFAULTS = {
4
- :base_color => '#933c3c'
5
- }
3
+ private
6
4
 
7
- PATTERNS = {
8
- 'chevrons' => ChevronPattern,
9
- 'concentric_circles' => ConcentricCirclesPattern,
10
- 'diamonds' => DiamondPattern,
11
- 'hexagons' => HexagonPattern,
12
- 'mosaic_squares' => MosaicSquaresPattern,
13
- 'nested_squares' => NestedSquaresPattern,
14
- 'octagons' => OctagonPattern,
15
- 'overlapping_circles' => OverlappingCirclesPattern,
16
- 'overlapping_rings' => OverlappingRingsPattern,
17
- 'plaid' => PlaidPattern,
18
- 'plus_signs' => PlusSignPattern,
19
- 'sine_waves' => SineWavePattern,
20
- 'squares' => SquarePattern,
21
- 'tessellation' => TessellationPattern,
22
- 'triangles' => TrianglePattern,
23
- 'xes' => XesPattern,
24
- }.freeze
5
+ attr_reader :background_generator, :structure_generator
25
6
 
26
- FILL_COLOR_DARK = "#222"
27
- FILL_COLOR_LIGHT = "#ddd"
28
- STROKE_COLOR = "#000"
29
- STROKE_OPACITY = 0.02
30
- OPACITY_MIN = 0.02
31
- OPACITY_MAX = 0.15
7
+ public
32
8
 
33
- attr_reader :opts, :hash, :svg
9
+ def initialize(string, generator: nil, patterns: nil, base_color: nil, color: nil)
10
+ $stderr.puts 'Using generator key is deprecated as of 1.3.1' if generator
34
11
 
35
- def initialize(string, opts={})
36
- @opts = DEFAULTS.merge(opts)
37
- @hash = Digest::SHA1.hexdigest string
38
- @svg = SVG.new
12
+ requested_patterns = (Array(generator) | Array(patterns)).flatten.compact
39
13
 
40
- generate_background
41
- generate_pattern
42
- end
14
+ pattern_preset = PatternPreset.new(
15
+ fill_color_dark: '#222',
16
+ fill_color_light: '#ddd',
17
+ stroke_color: '#000',
18
+ stroke_opacity: 0.02,
19
+ opacity_min: 0.02,
20
+ opacity_max: 0.15
21
+ )
43
22
 
44
- def svg_string
45
- svg.to_s
46
- end
47
- alias_method :to_s, :svg_string
23
+ color_preset = ColorPreset.new(
24
+ base_color: '#933c3c'
25
+ )
26
+ color_preset.color = color if color
27
+ color_preset.base_color = base_color if base_color
48
28
 
49
- def base64_string
50
- Base64.strict_encode64(svg_string)
51
- end
29
+ seed = Seed.new(string)
52
30
 
53
- def uri_image
54
- "url(data:image/svg+xml;base64,#{base64_string});"
55
- end
31
+ pattern_validator = PatternValidator.new
32
+ pattern_validator.validate(requested_patterns)
56
33
 
57
- def generate_background
58
- if opts[:color]
59
- rgb = Color::RGB.from_html(opts[:color])
60
- else
61
- hue_offset = PatternHelpers.map(PatternHelpers.hex_val(hash, 14, 3), 0, 4095, 0, 359)
62
- sat_offset = PatternHelpers.hex_val(hash, 17, 1)
63
- base_color = Color::RGB.from_html(opts[:base_color]).to_hsl
64
- base_color.hue = base_color.hue - hue_offset;
34
+ pattern_sieve = PatternSieve.new(requested_patterns, seed)
65
35
 
66
- if (sat_offset % 2 == 0)
67
- base_color.saturation = base_color.saturation + sat_offset
68
- else
69
- base_color.saturation = base_color.saturation - sat_offset
70
- end
71
- rgb = base_color.to_rgb
72
- end
73
- r = (rgb.r * 255).round
74
- g = (rgb.g * 255).round
75
- b = (rgb.b * 255).round
76
- svg.rect(0, 0, "100%", "100%", {"fill" => "rgb(#{r}, #{g}, #{b})"})
36
+ @background_generator = BackgroundGenerators::SolidGenerator.new(seed, color_preset)
37
+ @structure_generator = begin
38
+ generator_klass = pattern_sieve.fetch
39
+ generator_klass.new(seed, pattern_preset)
40
+ end
77
41
  end
78
42
 
79
- def generate_pattern
80
- unless opts[:generator].nil?
81
- if opts[:generator].is_a? String
82
- generator = PATTERNS[opts[:generator]]
83
- puts SVG.as_comment("String pattern references are deprecated as of 1.3.0")
84
- elsif opts[:generator] < BasePattern
85
- if PATTERNS.values.include? opts[:generator]
86
- generator = opts[:generator]
87
- else
88
- abort("Error: the requested generator is invalid")
89
- generator = nil
90
- end
91
- end
92
- end
43
+ def generate
44
+ pattern = Pattern.new
93
45
 
94
- generator ||= PATTERNS.values[[PatternHelpers.hex_val(hash, 20, 1), PATTERNS.length - 1].min]
46
+ pattern.generate_me background_generator
47
+ pattern.generate_me structure_generator
95
48
 
96
- # Instantiate the generator with the needed references
97
- # and render the pattern to the svg object
98
- generator.new(svg, hash).render_to_svg
49
+ pattern
99
50
  end
100
51
  end
101
52
  end
@@ -1,17 +1,46 @@
1
1
  module GeoPattern
2
2
  module PatternHelpers
3
- def self.hex_val(hash, index, length)
3
+ def hex_val(hash, index, length)
4
4
  hash[index, length || 1].to_i(16)
5
5
  end
6
6
 
7
7
  # Ruby implementation of Processing's map function
8
8
  # http://processing.org/reference/map_.html
9
- def self.map(value, v_min, v_max, d_min, d_max) # v for value, d for desired
9
+ def map(value, v_min, v_max, d_min, d_max) # v for value, d for desired
10
10
  v_value = value.to_f # so it returns float
11
11
 
12
12
  v_range = v_max - v_min
13
13
  d_range = d_max - d_min
14
14
  (v_value - v_min) * d_range / v_range + d_min
15
15
  end
16
+
17
+ def html_to_rgb(color)
18
+ generate_rgb_string(::Color::RGB.from_html(color))
19
+ end
20
+
21
+ def html_to_rgb_for_string(seed, base_color)
22
+ hue_offset = map(seed.to_i(14, 3), 0, 4095, 0, 359)
23
+ sat_offset = seed.to_i(17, 1)
24
+ base_color = ::Color::RGB.from_html(base_color).to_hsl
25
+ base_color.hue = base_color.hue - hue_offset
26
+
27
+ if (sat_offset % 2 == 0)
28
+ base_color.saturation = base_color.saturation + sat_offset
29
+ else
30
+ base_color.saturation = base_color.saturation - sat_offset
31
+ end
32
+
33
+ generate_rgb_string(base_color.to_rgb)
34
+ end
35
+
36
+ def generate_rgb_string(rgb)
37
+ r = (rgb.r * 255).round
38
+ g = (rgb.g * 255).round
39
+ b = (rgb.b * 255).round
40
+
41
+ format('rgb(%d, %d, %d)', r, g, b)
42
+ end
43
+
44
+ module_function :hex_val, :map, :html_to_rgb, :html_to_rgb_for_string, :generate_rgb_string
16
45
  end
17
46
  end
@@ -0,0 +1,23 @@
1
+ module GeoPattern
2
+ class PatternPreset
3
+ private
4
+
5
+ attr_accessor :options
6
+
7
+ public
8
+
9
+ def initialize(options)
10
+ @options = options
11
+ end
12
+
13
+ [:fill_color_dark, :fill_color_light, :stroke_color, :stroke_opacity, :opacity_min, :opacity_max].each do |m|
14
+ define_method m do
15
+ options[m]
16
+ end
17
+ end
18
+
19
+ def update(opts)
20
+ options.merge! opts
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,36 @@
1
+ module GeoPattern
2
+ class PatternSieve
3
+ private
4
+
5
+ attr_reader :pattern_store, :requested_patterns, :seed, :available_patterns, :index
6
+
7
+ public
8
+
9
+ def initialize(requested_patterns, seed, pattern_store = PatternStore.new)
10
+ @requested_patterns = requested_patterns
11
+ @seed = seed
12
+ @pattern_store = pattern_store
13
+
14
+ @available_patterns = determine_available_patterns
15
+ @index = determine_index
16
+ end
17
+
18
+ def fetch
19
+ available_patterns[index]
20
+ end
21
+
22
+ private
23
+
24
+ def determine_index
25
+ [seed.to_i(20, 1), available_patterns.length - 1].min
26
+ end
27
+
28
+ def determine_available_patterns
29
+ patterns = Array(requested_patterns).compact
30
+
31
+ return pattern_store.all if patterns.empty?
32
+
33
+ patterns.map { |p| pattern_store[p] }.compact
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,63 @@
1
+ module GeoPattern
2
+ # rubocop:disable Style/ConstantName
3
+ ChevronPattern = :chevrons
4
+ ConcentricCirclesPattern = :concentric_circles
5
+ DiamondPattern = :diamonds
6
+ HexagonPattern = :hexagons
7
+ MosaicSquaresPattern = :mosaic_squares
8
+ NestedSquaresPattern = :nested_squares
9
+ OctagonPattern = :octagons
10
+ OverlappingCirclesPattern = :overlapping_circles
11
+ OverlappingRingsPattern = :overlapping_rings
12
+ PlaidPattern = :plaid
13
+ PlusSignPattern = :plus_signs
14
+ SineWavePattern = :sine_waves
15
+ SquarePattern = :squares
16
+ TessellationPattern = :tessellation
17
+ TrianglePattern = :triangles
18
+ XesPattern = :xes
19
+ # rubocop:enable Style/ConstantName
20
+
21
+ class PatternStore
22
+ private
23
+
24
+ attr_reader :store
25
+
26
+ public
27
+
28
+ def initialize
29
+ @store = {
30
+ chevrons: StructureGenerators::ChevronsGenerator,
31
+ concentric_circles: StructureGenerators::ConcentricCirclesGenerator,
32
+ diamonds: StructureGenerators::DiamondsGenerator,
33
+ hexagons: StructureGenerators::HexagonsGenerator,
34
+ mosaic_squares: StructureGenerators::MosaicSquaresGenerator,
35
+ nested_squares: StructureGenerators::NestedSquaresGenerator,
36
+ octagons: StructureGenerators::OctagonsGenerator,
37
+ overlapping_circles: StructureGenerators::OverlappingCirclesGenerator,
38
+ overlapping_rings: StructureGenerators::OverlappingRingsGenerator,
39
+ plaid: StructureGenerators::PlaidGenerator,
40
+ plus_signs: StructureGenerators::PlusSignsGenerator,
41
+ sine_waves: StructureGenerators::SineWavesGenerator,
42
+ squares: StructureGenerators::SquaresGenerator,
43
+ tessellation: StructureGenerators::TessellationGenerator,
44
+ triangles: StructureGenerators::TrianglesGenerator,
45
+ xes: StructureGenerators::XesGenerator
46
+ }
47
+ end
48
+
49
+ def [](pattern)
50
+ $stderr.puts 'String pattern references are deprecated as of 1.3.0' if pattern.is_a?(String)
51
+
52
+ store[pattern.to_s.to_sym]
53
+ end
54
+
55
+ def all
56
+ store.values
57
+ end
58
+
59
+ def known?(pattern)
60
+ store.key?(pattern.to_s.to_sym)
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,27 @@
1
+ module GeoPattern
2
+ class PatternValidator
3
+ private
4
+
5
+ attr_reader :pattern_store
6
+
7
+ public
8
+
9
+ def initialize(pattern_store = PatternStore.new)
10
+ @pattern_store = pattern_store
11
+ end
12
+
13
+ def validate(requested_patterns)
14
+ message = "Error: At least one of the requested patterns \"#{requested_patterns.join(', ')}\" is invalid"
15
+
16
+ fail InvalidPatternError, message unless valid?(requested_patterns)
17
+
18
+ self
19
+ end
20
+
21
+ private
22
+
23
+ def valid?(requested_patterns)
24
+ requested_patterns.all? { |p| pattern_store.known? p }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,109 @@
1
+ require 'rake'
2
+ require 'rake/tasklib'
3
+ require 'logger'
4
+
5
+ module GeoPattern
6
+ # Rake Task
7
+ #
8
+ # This task can be used to generate pattern files
9
+ class RakeTask < ::Rake::TaskLib
10
+ include ::Rake::DSL if defined?(::Rake::DSL)
11
+
12
+ # @!attribute [r] name
13
+ # Name of task.
14
+ attr_reader :name
15
+
16
+ # @!attribute [r] description
17
+ # A description for the task
18
+ attr_reader :description
19
+
20
+ # @!attribute [r] verbose (true)
21
+ # Use verbose output. If this is set to true, the task will print the
22
+ # executed spec command to stdout.
23
+ attr_reader :verbose
24
+
25
+ private
26
+
27
+ attr_reader :task_arguments, :task_block, :logger, :working_directory
28
+
29
+ # Create task instance
30
+ #
31
+ # @param [String] description
32
+ # A description for the task
33
+ #
34
+ # @param [String] name
35
+ # The name for the task (including namespace), e.g. namespace1:task1
36
+ #
37
+ # @param [Array] arguments
38
+ # Arguments for the task. Look
39
+ # [here](http://viget.com/extend/protip-passing-parameters-to-your-rake-tasks)
40
+ # for a better description on how to use arguments in rake tasks
41
+ #
42
+ # @yield
43
+ # A block which is called before the "run_task"-method is called. The
44
+ # parameters it taskes depends on the number of parameters the block
45
+ # can take. If the block is defined which two parameters, it takes two
46
+ # parameters from the paramter 'arguments'.
47
+ def initialize(opts = {}, &task_block)
48
+ @options = {
49
+ description: nil,
50
+ name: GeoPattern::Helpers.underscore(self.class.to_s.split(/::/).slice(-2..-1).join(':').gsub(/Task$/, '')),
51
+ arguments: [],
52
+ logger: ::Logger.new($stderr),
53
+ working_directory: Dir.getwd
54
+ }.merge opts
55
+
56
+ before_initialize
57
+
58
+ fail ArgumentError, :description if @options[:description].nil?
59
+
60
+ @description = @options[:description]
61
+ @task_arguments = Array(@options[:arguments])
62
+ @task_block = task_block
63
+ @logger = @options[:logger]
64
+ @working_directory = @options[:working_directory]
65
+ @name = @options[:name]
66
+
67
+ after_initialize
68
+
69
+ define_task
70
+ end
71
+
72
+ private
73
+
74
+ # Run code after initialize
75
+ def after_initialize; end
76
+
77
+ # Run code before initialize
78
+ def before_initialize; end
79
+
80
+ # Define task
81
+ def define_task
82
+ desc description unless ::Rake.application.last_comment
83
+
84
+ task name, *task_arguments do |_, task_args|
85
+ RakeFileUtils.__send__(:verbose, verbose) do
86
+ instance_exec(*[self, task_args].slice(0, task_block.arity), &task_block) if task_block.respond_to? :call
87
+ run_task verbose
88
+ end
89
+ end
90
+ end
91
+
92
+ # Run code if task is executed
93
+ def run_task(_verbose); end
94
+
95
+ public
96
+
97
+ # Binding to instance
98
+ def instance_binding
99
+ binding
100
+ end
101
+
102
+ # Include module in instance
103
+ def include(modules)
104
+ modules = Array(modules)
105
+
106
+ modules.each { |m| self.class.include m }
107
+ end
108
+ end
109
+ end