evva 0.4.4 → 0.5.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.
data/Gemfile CHANGED
@@ -1,14 +1,16 @@
1
- source 'https://rubygems.org'
1
+ # frozen_string_literal: true
2
2
 
3
- gem 'colorize'
4
- gem 'safe_yaml'
3
+ source "https://rubygems.org"
4
+
5
+ gem "colorize"
6
+ gem "safe_yaml"
5
7
 
6
8
  group :test do
7
- gem 'rake'
8
- gem 'rspec'
9
- gem 'rspec-its'
10
- gem 'simplecov', require: false, group: :test
11
- gem 'simplecov-rcov', require: false
12
- gem 'webmock', '~> 1.20'
13
- gem 'rubocop'
9
+ gem "rake"
10
+ gem "rspec"
11
+ gem "rspec-its"
12
+ gem "rubocop"
13
+ gem "simplecov", require: false, group: :test
14
+ gem "simplecov-rcov", require: false
15
+ gem "webmock"
14
16
  end
data/Gemfile.lock CHANGED
@@ -1,61 +1,72 @@
1
1
  GEM
2
2
  remote: https://rubygems.org/
3
3
  specs:
4
- addressable (2.8.0)
5
- public_suffix (>= 2.0.2, < 5.0)
6
- ast (2.3.0)
7
- colorize (0.8.1)
8
- crack (0.4.3)
9
- safe_yaml (~> 1.0.0)
10
- diff-lcs (1.3)
11
- docile (1.1.5)
12
- hashdiff (0.3.7)
13
- json (2.3.0)
14
- parallel (1.12.0)
15
- parser (2.4.0.0)
16
- ast (~> 2.2)
17
- powerpack (0.1.1)
18
- public_suffix (4.0.6)
19
- rainbow (2.2.2)
20
- rake
21
- rake (12.3.3)
22
- rspec (3.7.0)
23
- rspec-core (~> 3.7.0)
24
- rspec-expectations (~> 3.7.0)
25
- rspec-mocks (~> 3.7.0)
26
- rspec-core (3.7.0)
27
- rspec-support (~> 3.7.0)
28
- rspec-expectations (3.7.0)
4
+ addressable (2.8.7)
5
+ public_suffix (>= 2.0.2, < 7.0)
6
+ ast (2.4.2)
7
+ bigdecimal (3.1.8)
8
+ colorize (1.1.0)
9
+ crack (1.0.0)
10
+ bigdecimal
11
+ rexml
12
+ diff-lcs (1.5.1)
13
+ docile (1.4.1)
14
+ hashdiff (1.1.1)
15
+ json (2.7.2)
16
+ language_server-protocol (3.17.0.3)
17
+ parallel (1.26.3)
18
+ parser (3.3.5.0)
19
+ ast (~> 2.4.1)
20
+ racc
21
+ public_suffix (6.0.1)
22
+ racc (1.8.1)
23
+ rainbow (3.1.1)
24
+ rake (13.2.1)
25
+ regexp_parser (2.9.2)
26
+ rexml (3.3.8)
27
+ rspec (3.13.0)
28
+ rspec-core (~> 3.13.0)
29
+ rspec-expectations (~> 3.13.0)
30
+ rspec-mocks (~> 3.13.0)
31
+ rspec-core (3.13.1)
32
+ rspec-support (~> 3.13.0)
33
+ rspec-expectations (3.13.3)
29
34
  diff-lcs (>= 1.2.0, < 2.0)
30
- rspec-support (~> 3.7.0)
31
- rspec-its (1.2.0)
35
+ rspec-support (~> 3.13.0)
36
+ rspec-its (1.3.0)
32
37
  rspec-core (>= 3.0.0)
33
38
  rspec-expectations (>= 3.0.0)
34
- rspec-mocks (3.7.0)
39
+ rspec-mocks (3.13.2)
35
40
  diff-lcs (>= 1.2.0, < 2.0)
36
- rspec-support (~> 3.7.0)
37
- rspec-support (3.7.0)
38
- rubocop (0.51.0)
41
+ rspec-support (~> 3.13.0)
42
+ rspec-support (3.13.1)
43
+ rubocop (1.67.0)
44
+ json (~> 2.3)
45
+ language_server-protocol (>= 3.17.0)
39
46
  parallel (~> 1.10)
40
- parser (>= 2.3.3.1, < 3.0)
41
- powerpack (~> 0.1)
42
- rainbow (>= 2.2.2, < 3.0)
47
+ parser (>= 3.3.0.2)
48
+ rainbow (>= 2.2.2, < 4.0)
49
+ regexp_parser (>= 2.4, < 3.0)
50
+ rubocop-ast (>= 1.32.2, < 2.0)
43
51
  ruby-progressbar (~> 1.7)
44
- unicode-display_width (~> 1.0, >= 1.0.1)
45
- ruby-progressbar (1.9.0)
46
- safe_yaml (1.0.4)
47
- simplecov (0.15.1)
48
- docile (~> 1.1.0)
49
- json (>= 1.8, < 3)
50
- simplecov-html (~> 0.10.0)
51
- simplecov-html (0.10.2)
52
- simplecov-rcov (0.2.3)
52
+ unicode-display_width (>= 2.4.0, < 3.0)
53
+ rubocop-ast (1.32.3)
54
+ parser (>= 3.3.1.0)
55
+ ruby-progressbar (1.13.0)
56
+ safe_yaml (1.0.5)
57
+ simplecov (0.22.0)
58
+ docile (~> 1.1)
59
+ simplecov-html (~> 0.11)
60
+ simplecov_json_formatter (~> 0.1)
61
+ simplecov-html (0.13.1)
62
+ simplecov-rcov (0.3.7)
53
63
  simplecov (>= 0.4.1)
54
- unicode-display_width (1.3.0)
55
- webmock (1.24.6)
56
- addressable (>= 2.3.6)
64
+ simplecov_json_formatter (0.1.4)
65
+ unicode-display_width (2.6.0)
66
+ webmock (3.24.0)
67
+ addressable (>= 2.8.0)
57
68
  crack (>= 0.3.2)
58
- hashdiff
69
+ hashdiff (>= 0.4.0, < 2.0.0)
59
70
 
60
71
  PLATFORMS
61
72
  ruby
@@ -69,7 +80,7 @@ DEPENDENCIES
69
80
  safe_yaml
70
81
  simplecov
71
82
  simplecov-rcov
72
- webmock (~> 1.20)
83
+ webmock
73
84
 
74
85
  BUNDLED WITH
75
- 2.2.26
86
+ 2.5.21
data/README.md CHANGED
@@ -4,7 +4,7 @@ Evva
4
4
  [![Status](https://travis-ci.org/hole19/evva.svg?branch=master)](https://travis-ci.org/hole19/evva?branch=master)
5
5
  [![Gem](https://img.shields.io/gem/v/evva.svg?style=flat)](http://rubygems.org/gems/evva "View this project in Rubygems")
6
6
 
7
- Evva automatically generates code for triggering events based on a Google Sheets specification. It generated code for both iOS (Swift) and Android (Kotlin).
7
+ Evva automatically generates code for triggering events based on a Google Sheets specification. It generates code for both Swift (iOS) and Kotlin (Android).
8
8
 
9
9
  # Instalation
10
10
 
data/bin/evva CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'evva'
3
+ require "evva"
4
4
  Evva.run(ARGV)
data/changelog.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## [0.5.0] - 2024-10-16
6
+
7
+ - Update all dependencies
8
+
9
+ ### Breaking Changes
10
+ - Fix deprecation warnings
11
+ - Set minimum ruby version as 3.2
12
+ - Change `object` events in Kotlin to `data object` as an improvement brought by Kotlin 2.0
13
+
5
14
  ## [0.4.4] - 2024-10-16
6
15
 
7
16
  ### Breaking Changes
data/evva.gemspec CHANGED
@@ -1,21 +1,23 @@
1
- require_relative 'lib/evva/version'
1
+ require_relative "lib/evva/version"
2
2
 
3
3
  Gem::Specification.new do |s|
4
- s.name = 'evva'
4
+ s.name = "evva"
5
5
  s.version = Evva::VERSION
6
6
  s.date = Evva::VERSION_UPDATED_AT
7
- s.summary = 'An event generating service'
8
- s.description = 'Evva generates all the analytics event tracking functions for you'
9
- s.authors = ['RicardoTrindade']
10
- s.email = 'ricardo.trindade743@gmail.com'
11
- s.license = 'MIT'
12
- s.homepage = 'https://github.com/hole19/'
7
+ s.summary = "An event generating service"
8
+ s.description = "Evva generates all the analytics event tracking functions for you"
9
+ s.authors = ["André Andrade", "João Costa", "Ricardo Trindade"]
10
+ s.email = "ricardo.trindade743@gmail.com"
11
+ s.license = "MIT"
12
+ s.homepage = "https://github.com/hole19/"
13
13
 
14
14
  s.files = `git ls-files`.split("\n")
15
- s.require_paths = ['lib']
15
+ s.require_paths = ["lib"]
16
16
 
17
- s.executables << 'evva'
17
+ s.executables << "evva"
18
18
 
19
- s.add_runtime_dependency 'safe_yaml', '~> 1.0'
20
- s.add_runtime_dependency 'colorize', '~> 0.7'
19
+ s.required_ruby_version = ">= 3.2.0"
20
+
21
+ s.add_runtime_dependency "colorize", "~> 1.0"
22
+ s.add_runtime_dependency "safe_yaml", "~> 1.0"
21
23
  end
data/lib/evva/config.rb CHANGED
@@ -83,7 +83,7 @@ module Evva
83
83
  }.freeze
84
84
 
85
85
  DICTIONARY_STRUCT = {
86
- 'google_sheet' => GOOGLE_SHEET_STRUCT
86
+ "google_sheet" => GOOGLE_SHEET_STRUCT
87
87
  }.freeze
88
88
  end
89
89
  end
@@ -1,4 +1,4 @@
1
- require 'fileutils'
1
+ require "fileutils"
2
2
 
3
3
  module Evva
4
4
  class FileReader
@@ -1,18 +1,18 @@
1
- require 'net/https'
2
- require 'csv'
1
+ require "net/https"
2
+ require "csv"
3
3
 
4
4
  module Evva
5
5
  class GoogleSheet
6
- EVENT_NAME = 'Event Name'
7
- EVENT_PROPERTIES = 'Event Properties'
8
- EVENT_DESTINATION = 'Event Destination'
6
+ EVENT_NAME = "Event Name"
7
+ EVENT_PROPERTIES = "Event Properties"
8
+ EVENT_DESTINATION = "Event Destination"
9
9
 
10
- PROPERTY_NAME = 'Property Name'
11
- PROPERTY_TYPE = 'Property Type'
12
- PROPERTY_DESTINATION = 'Property Destination'
10
+ PROPERTY_NAME = "Property Name"
11
+ PROPERTY_TYPE = "Property Type"
12
+ PROPERTY_DESTINATION = "Property Destination"
13
13
 
14
- ENUM_NAME = 'Enum Name'
15
- ENUM_VALUES = 'Possible Values'
14
+ ENUM_NAME = "Enum Name"
15
+ ENUM_VALUES = "Possible Values"
16
16
 
17
17
  def initialize(events_url, people_properties_url, enum_classes_url)
18
18
  @events_url = events_url
@@ -29,7 +29,7 @@ module Evva
29
29
  @events ||= @events_csv.map do |row|
30
30
  event_name = row[EVENT_NAME]
31
31
  properties = hash_parser(row[EVENT_PROPERTIES])
32
- destinations = row[EVENT_DESTINATION]&.split(',')
32
+ destinations = row[EVENT_DESTINATION]&.split(",")
33
33
  Evva::AnalyticsEvent.new(event_name, properties, destinations || [])
34
34
  end
35
35
  end
@@ -43,7 +43,7 @@ module Evva
43
43
  @people_properties ||= @people_properties_csv.map do |row|
44
44
  property_name = row[PROPERTY_NAME]
45
45
  property_type = row[PROPERTY_TYPE]
46
- destinations = row[PROPERTY_DESTINATION]&.split(',')
46
+ destinations = row[PROPERTY_DESTINATION]&.split(",")
47
47
  Evva::AnalyticsProperty.new(property_name, property_type, destinations || [])
48
48
  end
49
49
  end
@@ -56,7 +56,7 @@ module Evva
56
56
 
57
57
  @enum_classes ||= @enum_classes_csv.map do |row|
58
58
  enum_name = row[ENUM_NAME]
59
- values = row[ENUM_VALUES].split(',')
59
+ values = row[ENUM_VALUES].split(",")
60
60
  Evva::AnalyticsEnum.new(enum_name, values)
61
61
  end
62
62
  end
@@ -65,7 +65,7 @@ module Evva
65
65
  @destinations ||= events.map(&:destinations).flatten.uniq
66
66
  end
67
67
 
68
- private
68
+ private
69
69
 
70
70
  def get_csv(url)
71
71
  data = get(url)
@@ -89,7 +89,7 @@ module Evva
89
89
  request = Net::HTTP::Get.new(uri.request_uri)
90
90
  response = http.request(request)
91
91
 
92
- return get(response['location'], max_redirects - 1) if response.is_a? Net::HTTPRedirection
92
+ return get(response["location"], max_redirects - 1) if response.is_a? Net::HTTPRedirection
93
93
 
94
94
  raise "Http Error #{response.body}" if response.code.to_i >= 400
95
95
 
@@ -99,8 +99,8 @@ module Evva
99
99
  def hash_parser(property_array)
100
100
  h = {}
101
101
  unless property_array.nil? || property_array.empty?
102
- property_array.split(',').each do |prop|
103
- split_prop = prop.split(':')
102
+ property_array.split(",").each do |prop|
103
+ split_prop = prop.split(":")
104
104
  prop_name = split_prop[0].to_sym
105
105
  prop_type = split_prop[1].to_s
106
106
  h[prop_name] = prop_type
@@ -1,5 +1,5 @@
1
1
  module Evva
2
- class AndroidGenerator
2
+ class KotlinGenerator
3
3
  attr_accessor :package_name
4
4
 
5
5
  def initialize(package_name)
@@ -32,7 +32,7 @@ module Evva
32
32
  value_fetcher = param_name
33
33
 
34
34
  if is_special_property?(type)
35
- if type.end_with?('?')
35
+ if type.end_with?("?")
36
36
  # optional value, we need ? to access a parameter
37
37
  value_fetcher += "?"
38
38
  end
@@ -142,7 +142,7 @@ module Evva
142
142
  end
143
143
  end
144
144
 
145
- private
145
+ private
146
146
 
147
147
  def header_footer_wrapper
148
148
  package_name = @package_name
@@ -156,10 +156,8 @@ module Evva
156
156
  def template_from(path)
157
157
  file = File.read(path)
158
158
 
159
- # - 2nd argument (nil) changes nothing
160
- # - 3rd argument activates trim mode using "-" so that you can decide to
161
- # not include a line (useful on loops and if statements)
162
- ERB.new(file, nil, '-')
159
+ # trim mode using "-" so that you can decide to not include a line (useful on loops and if statements)
160
+ ERB.new(file, trim_mode: "-")
163
161
  end
164
162
 
165
163
  # extracted from Rails' ActiveSupport
@@ -174,16 +172,16 @@ module Evva
174
172
  end
175
173
 
176
174
  def constantize(string)
177
- string.tr(' ', '_').upcase
175
+ string.tr(" ", "_").upcase
178
176
  end
179
177
 
180
178
  def native_type(type)
181
179
  type
182
- .gsub('Date','String')
180
+ .gsub("Date","String")
183
181
  end
184
182
 
185
183
  def is_special_property?(type)
186
- !NATIVE_TYPES.include?(type.chomp('?'))
184
+ !NATIVE_TYPES.include?(type.chomp("?"))
187
185
  end
188
186
  end
189
187
  end
data/lib/evva/logger.rb CHANGED
@@ -1,5 +1,5 @@
1
- require 'singleton'
2
- require 'colorize'
1
+ require "singleton"
2
+ require "colorize"
3
3
 
4
4
  module Evva
5
5
  module Logger
@@ -27,11 +27,11 @@ module Evva
27
27
 
28
28
  def print_summary
29
29
  if @levels[:warn] > 0 || @levels[:error] > 0
30
- info ''
31
- info 'Finished with:'
30
+ info ""
31
+ info "Finished with:"
32
32
  info " #{@levels[:warn]} warnings" if @levels[:warn] > 0
33
33
  info " #{@levels[:error]} errors" if @levels[:error] > 0
34
- info ''
34
+ info ""
35
35
  end
36
36
  end
37
37
 
@@ -39,7 +39,7 @@ module Evva
39
39
  @silent_mode = value
40
40
  end
41
41
 
42
- private
42
+ private
43
43
 
44
44
  @levels = { info: 0, warn: 0, error: 0 }
45
45
  @silent_mode = false
@@ -13,7 +13,7 @@ Object.class_eval do
13
13
  def validate_structure!(structure, error_prefix = [])
14
14
  return if nil? && structure[:optional]
15
15
 
16
- prepend_error = error_prefix.empty? ? '' : (['self'] + error_prefix + [': ']).join
16
+ prepend_error = error_prefix.empty? ? "" : (["self"] + error_prefix + [": "]).join
17
17
 
18
18
  unless is_a? structure[:type]
19
19
  raise ArgumentError, "#{prepend_error}Expected #{structure[:type]}, got #{self.class}"
@@ -1,4 +1,4 @@
1
- require 'erb'
1
+ require "erb"
2
2
 
3
3
  module Evva
4
4
  class SwiftGenerator
@@ -21,7 +21,7 @@ module Evva
21
21
  value_fetcher = k.to_s
22
22
 
23
23
  if is_special_property?(type)
24
- if type.end_with?('?')
24
+ if type.end_with?("?")
25
25
  # optional value, we need ? to access a parameter
26
26
  value_fetcher += "?"
27
27
  end
@@ -100,7 +100,7 @@ module Evva
100
100
  end
101
101
  end
102
102
 
103
- private
103
+ private
104
104
 
105
105
  def header_footer_wrapper
106
106
  content = yield
@@ -113,24 +113,22 @@ module Evva
113
113
  def template_from(path)
114
114
  file = File.read(path)
115
115
 
116
- # - 2nd argument (nil) changes nothing
117
- # - 3rd argument activates trim mode using "-" so that you can decide to
118
- # not include a line (useful on loops and if statements)
119
- ERB.new(file, nil, '-')
116
+ # trim mode using "-" so that you can decide to not include a line (useful on loops and if statements)
117
+ ERB.new(file, trim_mode: "-")
120
118
  end
121
119
 
122
120
  def native_type(type)
123
121
  type
124
- .gsub('Boolean','Bool')
125
- .gsub('Long', 'Int')
122
+ .gsub("Boolean","Bool")
123
+ .gsub("Long", "Int")
126
124
  end
127
125
 
128
126
  def is_special_property?(type)
129
- !NATIVE_TYPES.include?(type.chomp('?'))
127
+ !NATIVE_TYPES.include?(type.chomp("?"))
130
128
  end
131
129
 
132
130
  def camelize(term)
133
- string = term.to_s.tr(' ', '_').downcase
131
+ string = term.to_s.tr(" ", "_").downcase
134
132
  string = string.sub(/^(?:#{@acronym_regex}(?=\b|[A-Z_])|\w)/) { |match| match.downcase }
135
133
  string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" }
136
134
  string.gsub!("/".freeze, "::".freeze)
@@ -7,7 +7,7 @@ sealed class <%= class_name %>(
7
7
 
8
8
  <%- events.each_with_index do |e, index| -%>
9
9
  <%- if e[:properties].count == 0 -%>
10
- object <%= e[:class_name] %> : <%= class_name %>(
10
+ data object <%= e[:class_name] %> : <%= class_name %>(
11
11
  <%- else -%>
12
12
  data class <%= e[:class_name] %>(
13
13
  <%- e[:properties].each_with_index do |p, index| -%>
data/lib/evva/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Evva
2
- VERSION = '0.4.4'.freeze
3
- VERSION_UPDATED_AT = '2024-10-16'.freeze
2
+ VERSION = "0.5.0".freeze
3
+ VERSION_UPDATED_AT = "2024-10-16".freeze
4
4
  end
data/lib/evva.rb CHANGED
@@ -1,24 +1,24 @@
1
- require 'optparse'
2
- require 'yaml'
1
+ require "optparse"
2
+ require "yaml"
3
3
 
4
- require 'evva/logger'
5
- require 'evva/google_sheet'
6
- require 'evva/config'
7
- require 'evva/file_reader'
8
- require 'evva/analytics_event'
9
- require 'evva/analytics_enum'
10
- require 'evva/analytics_property'
11
- require 'evva/object_extension'
12
- require 'evva/version'
13
- require 'evva/android_generator'
14
- require 'evva/swift_generator'
4
+ require "evva/logger"
5
+ require "evva/google_sheet"
6
+ require "evva/config"
7
+ require "evva/file_reader"
8
+ require "evva/analytics_event"
9
+ require "evva/analytics_enum"
10
+ require "evva/analytics_property"
11
+ require "evva/object_extension"
12
+ require "evva/version"
13
+ require "evva/kotlin_generator"
14
+ require "evva/swift_generator"
15
15
 
16
16
  module Evva
17
17
  extend self
18
18
  def run(options)
19
19
  file_reader = Evva::FileReader.new
20
20
  options = command_line_options(options)
21
- unless config_file = file_reader.open_file('evva_config.yml', 'r', true)
21
+ unless config_file = file_reader.open_file("evva_config.yml", "r", true)
22
22
  Logger.error("Could not open evva_config.yml")
23
23
  return
24
24
  end
@@ -26,12 +26,12 @@ module Evva
26
26
  config = Evva::Config.new(hash: YAML.safe_load(config_file))
27
27
  bundle = analytics_data(config: config.data_source)
28
28
  case config.type.downcase
29
- when 'android'
30
- generator = Evva::AndroidGenerator.new(config.package_name)
31
- evva_write(bundle, generator, config, 'kt')
32
- when 'ios'
29
+ when "android"
30
+ generator = Evva::KotlinGenerator.new(config.package_name)
31
+ evva_write(bundle, generator, config, "kt")
32
+ when "ios"
33
33
  generator = Evva::SwiftGenerator.new
34
- evva_write(bundle, generator, config, 'swift')
34
+ evva_write(bundle, generator, config, "swift")
35
35
  end
36
36
  Evva::Logger.print_summary
37
37
  end
@@ -40,7 +40,7 @@ module Evva
40
40
  path = "#{configuration.out_path}/#{configuration.event_file_name}.#{extension}"
41
41
  write_to_file(path, generator.events(bundle[:events], configuration.event_file_name, configuration.event_enum_file_name, configuration.destinations_file_name))
42
42
 
43
- unless configuration.type.downcase == 'ios'
43
+ unless configuration.type.downcase == "ios"
44
44
  path = "#{configuration.out_path}/#{configuration.event_enum_file_name}.#{extension}"
45
45
  write_to_file(path, generator.event_enum(bundle[:events], configuration.event_enum_file_name))
46
46
  end
@@ -48,7 +48,7 @@ module Evva
48
48
  path = "#{configuration.out_path}/#{configuration.people_file_name}.#{extension}"
49
49
  write_to_file(path, generator.people_properties(bundle[:people], configuration.people_file_name, configuration.people_enum_file_name, configuration.destinations_file_name))
50
50
 
51
- unless configuration.type.downcase == 'ios'
51
+ unless configuration.type.downcase == "ios"
52
52
  path = "#{configuration.out_path}/#{configuration.people_enum_file_name}.#{extension}"
53
53
  write_to_file(path, generator.people_properties_enum(bundle[:people], configuration.people_enum_file_name))
54
54
  end
@@ -63,7 +63,7 @@ module Evva
63
63
  def analytics_data(config:)
64
64
  source =
65
65
  case config[:type]
66
- when 'google_sheet'
66
+ when "google_sheet"
67
67
  Evva::GoogleSheet.new(config[:events_url], config[:people_properties_url], config[:enum_classes_url])
68
68
  end
69
69
  events_bundle = {}
@@ -78,12 +78,12 @@ module Evva
78
78
  opts_hash = {}
79
79
 
80
80
  opts_parser = OptionParser.new do |opts|
81
- opts.on_tail('-h', '--help', 'Show this message') do
81
+ opts.on_tail("-h", "--help", "Show this message") do
82
82
  puts opts
83
83
  exit
84
84
  end
85
85
 
86
- opts.on_tail('-v', '--version', 'Show version') do
86
+ opts.on_tail("-v", "--version", "Show version") do
87
87
  puts Evva::VERSION
88
88
  exit
89
89
  end