evoke 0.1.2 → 0.1.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 46a11e1fe28465d778a34db82f633bff896279f3
4
- data.tar.gz: 3e1fa45b6a7ba1759eb1c968388797f5ec7f0e4a
3
+ metadata.gz: 469f902eb78d1d43894adf316bd4ec3e428a1d3e
4
+ data.tar.gz: 257b7371196e71be263e7fda29a6e319cfc4177c
5
5
  SHA512:
6
- metadata.gz: 2d9ad91ede3f0176a1641b2da5e8a486065f9f354433d4e0ab725cf813fd47484fa9d3789f581cd4ff2b6f5dc70c3a4014d5ab2d3248b0221fe9af4fb6c8a81b
7
- data.tar.gz: 6847b441d5195c99eeb8bcfa790b11ae44d1e7b811c71331a6e9d68770dd35aa134873a7079ce8bf26428a805ff6c71eb3b4c52c00d7e9fdc0f919f31133e625
6
+ metadata.gz: da52e32aea945842bf8189c233b73005788fdafecb36a1229513533f3b75db1de124d31714ed820e09f2c8351fa72845cace43df705b50a0f4b0ea19e1a84da5
7
+ data.tar.gz: 2c382315f9b99381ac9d6854a98a94f5ce538b6006db24b73e73476cc9e0db8d56b379509ee83fa76f72432973538f22f51912d33d01af65d72a00b38fffdf10
data/.rubocop.yml CHANGED
@@ -10,9 +10,22 @@ Lint/UnusedMethodArgument:
10
10
  Style/EmptyLinesAroundClassBody:
11
11
  Enabled: false
12
12
 
13
+ Style/TrivialAccessors:
14
+ Enabled: false
15
+
16
+ Style/AlignParameters:
17
+ Enabled: false
18
+
19
+ Style/Documentation:
20
+ Enabled: false
21
+
13
22
  Metrics/MethodLength:
14
23
  Enabled: true
15
24
  Max: 15
16
25
 
17
26
  Metrics/AbcSize:
18
27
  Enabled: false
28
+
29
+ Metrics/LineLength:
30
+ Enabled: true
31
+ Max: 90
data/.travis.yml CHANGED
@@ -1,3 +1,9 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 2.0.0
4
+
5
+ addons:
6
+ code_climate:
7
+ repo_token: 6cc2a484a3960daa5e16ecdc42e7ccfbb22b32e75b09ecc6707c3330e826ba4b
8
+
9
+ before_install: gem install bundler --pre
data/Gemfile CHANGED
@@ -1,4 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in evoke.gemspec
4
3
  gemspec
4
+
5
+ gem 'codeclimate-test-reporter', group: :test, require: nil
data/README.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Evoke
2
2
 
3
+ [![GitHub version](https://badge.fury.io/gh/travishaynes%2Fevoke.svg)](http://badge.fury.io/gh/travishaynes%2Fevoke)
4
+ [![Build Status](https://travis-ci.org/travishaynes/evoke.svg)](https://travis-ci.org/travishaynes/evoke)
5
+ [![Code Climate](https://codeclimate.com/github/travishaynes/evoke/badges/gpa.svg)](https://codeclimate.com/github/travishaynes/evoke)
6
+ [![Test Coverage](https://codeclimate.com/github/travishaynes/evoke/badges/coverage.svg)](https://codeclimate.com/github/travishaynes/evoke)
7
+ [![Inline docs](http://inch-ci.org/github/travishaynes/evoke.svg)](http://inch-ci.org/github/travishaynes/evoke)
8
+
3
9
  A lightweight, zero-dependency task tool for Ruby.
4
10
 
5
11
  ## Installation
@@ -13,36 +19,45 @@ A lightweight, zero-dependency task tool for Ruby.
13
19
  Evoke tasks are Ruby classes that look like this:
14
20
 
15
21
  ```ruby
22
+ # Prints a friendly message to the console.
23
+ #
24
+ # This comment actually does something. The first line is used as a short
25
+ # description when `evoke help` or `evoke` is called without any arguments.
26
+ # The rest of the comment is printed, along with the first line, when
27
+ # `evoke help hello_world` is called to pull up help about this specific task.
16
28
  class HelloWorld < Evoke::Task
17
- # This description appears when your run `evoke` without any arguments.
18
- desc "Prints a friendly message"
19
29
 
20
- # This method is called by Evoke when the task is executed.
30
+ # The initializer of an Evoke::Task cannot have any required parameters.
31
+ def initialize
32
+ end
33
+
34
+ # Called when this method is invoked on the command-line. This task would be
35
+ # invoked using `evoke hello_world`.
21
36
  def invoke
22
37
  puts "Hello world!"
23
38
  end
24
39
  end
25
40
  ```
26
41
 
27
- **Important:** Initializers for Evoke::Tasks cannot have any required arguments.
28
-
29
- This task would be invoked from the command-line with `evoke hello_world`.
30
-
31
42
  #### Namespacing
32
43
 
33
44
  Tasks are namespaced using modules. Their command names are underscored from
34
45
  their Ruby class names. For example, a task named `Example::HelloWorld` would be
35
46
  invoked on the command line with `evoke example/hello_world`.
36
47
 
37
- #### Command-line-arguments
48
+ #### Command-Line Arguments
38
49
 
39
50
  Here's an example of a task that uses command-line arguments and is namespaced.
40
51
 
41
52
  ```ruby
42
53
  module Math
43
54
  class Add < Evoke::Task
55
+ # This can be used as an alternative to providing the short description in
56
+ # the class comment.
44
57
  desc "Adds two integers and prints the result in the console"
45
58
 
59
+ # All parameters come through as strings since they are read from the
60
+ # arguments supplied on the command-line.
46
61
  def invoke(a, b)
47
62
  puts a.to_i + b.to_i
48
63
  end
@@ -50,19 +65,50 @@ module Math
50
65
  end
51
66
  ```
52
67
 
53
- **Note:** All arguments come through as strings since they are read from the
54
- command-line.
55
-
56
68
  This task would be invoked from the command-line with `evoke math/add 5 10`,
57
69
  where a=5 and b=10 in this example.
58
70
 
59
- Switches are not currently supported. Use environment variables to use named
60
- arguments. Here's the same example as above using environment variables:
71
+ #### Optional Arguments
72
+
73
+ Variable-assigned optional parameters are supported. Key based, `&block` and
74
+ `*` parameters are not and will raise an error.
75
+
76
+ ```ruby
77
+ # SUPPORTED
78
+ def invoke(req, opt='optional argument'); end
79
+
80
+ # NOT SUPPORTED - errors will be raised
81
+ def invoke(opt: 'optional argument'); end
82
+ def invoke(*args); end
83
+ def invoke(&block); end
84
+ ```
85
+
86
+
87
+ #### Named Arguments
88
+
89
+ Environment variables are used for named arguments. Make sure to document the
90
+ required environment variables in the class comment of the task, perhaps even
91
+ including some examples. Normal parameters are displayed in the tasks' help,
92
+ environment variables are not.
93
+
94
+ Here's an example of the `math/add` task from earlier using named arguments that
95
+ is well documented:
61
96
 
62
97
  ```ruby
63
98
  module Math
99
+ # Adds two integers and prints the result in the console.
100
+ #
101
+ # Two environment variables are required to use this task: A and B.
102
+ #
103
+ # == Example: Adding 5 and 10.
104
+ #
105
+ # evoke math/add A=5 B=10
106
+ #
107
+ # == Example: Adding 2 and 3.
108
+ #
109
+ # evoke math/add A=2 B=3
110
+ #
64
111
  class Add < Evoke::Task
65
- desc "Adds two integers and prints the result in the console"
66
112
 
67
113
  def initialize
68
114
  @a = ENV['A'].to_i
@@ -76,15 +122,15 @@ module Math
76
122
  end
77
123
  ```
78
124
 
79
- This task would be invoked from the command-line with `evoke math/add A=5 B=10`.
80
-
81
- #### Syntax Usage
125
+ #### Documenting Tasks
82
126
 
83
127
  Using `evoke help` will give the user a more detailed description on how to use
84
128
  the task. Providing this description is as easy as adding a comment to the
85
129
  task's class. For example:
86
130
 
87
131
  ```ruby
132
+ # Prints the sum of two integers.
133
+ #
88
134
  # This is a completely useless task that allows you to add two numbers together
89
135
  # in the console using Evoke, a command-line task tool for Ruby.
90
136
  #
@@ -94,17 +140,22 @@ task's class. For example:
94
140
  #
95
141
  # This comment is displayed for this task when you run `evoke help add`.
96
142
  class Add < Evoke::Task
97
- desc "Prints the sum of two integers."
98
-
99
143
  def invoke(a, b)
100
144
  puts a.to_i + b.to_i
101
145
  end
102
146
  end
103
147
  ```
104
148
 
105
- Alternately, you can use the #syntax class method:
149
+ Alternately, you can use the `#syntax` and `#desc` class methods, which will
150
+ take precedence over the class comment.
106
151
 
107
152
  ```ruby
153
+ # This class comment will not be used to display help for this task because both
154
+ # the short and long descriptions are provided using #desc and #syntax.
155
+ #
156
+ # If only the #syntax method was used, the first line of this comment would
157
+ # still be used for the short description, and vice-versa. Both methods need to
158
+ # be used to completely disregard this comment.
108
159
  class Add < Evoke::Task
109
160
  desc "Prints the sum of two integers."
110
161
  syntax "Provide two integers as arguments to this task."
data/Rakefile CHANGED
@@ -2,7 +2,7 @@ require 'bundler/gem_tasks'
2
2
  require 'rake/testtask'
3
3
 
4
4
  Rake::TestTask.new do |t|
5
- t.libs << "test"
5
+ t.libs << 'test'
6
6
  t.test_files = FileList['test/**/*_test.rb']
7
7
  end
8
8
 
data/lib/evoke.rb CHANGED
@@ -10,7 +10,7 @@ module Evoke
10
10
  #
11
11
  # @return [Array] The task classes.
12
12
  def tasks
13
- ObjectSpace.each_object(Class).select {|klass| klass < Evoke::Task }
13
+ ObjectSpace.each_object(Class).select { |klass| klass < Evoke::Task }
14
14
  end
15
15
 
16
16
  # Finds a task with the supplied name.
@@ -22,7 +22,7 @@ module Evoke
22
22
  # Evoke.find_task('example/hello_world') # => Example::HelloWorld
23
23
  #
24
24
  def find_task(name)
25
- tasks.find {|task| task.to_s == name.camelize }
25
+ tasks.find { |task| task.to_s == name.camelize }
26
26
  end
27
27
 
28
28
  # Loads all the Evoke tasks in the supplied path.
@@ -45,7 +45,7 @@ module Evoke
45
45
  path = File.expand_path(path)
46
46
  end
47
47
 
48
- Dir[File.join(path, "**", "*_task.rb")].each {|f| load f }
48
+ Dir[File.join(path, '**', '*_task.rb')].each { |f| load f }
49
49
  end
50
50
 
51
51
  # Adds a code block that will be called before the task is invoked.
@@ -84,7 +84,7 @@ module Evoke
84
84
  # @param [Evoke::Task] task The task instance that is being invoked.
85
85
  # @param [Array] args The arguments that are being passed to the task.
86
86
  def call_before_hooks(task, *args)
87
- Array(@before_hooks).each {|hook| hook.call(task, *args) }
87
+ Array(@before_hooks).each { |hook| hook.call(task, *args) }
88
88
  end
89
89
  end
90
90
  end
data/lib/evoke/cli.rb CHANGED
@@ -13,9 +13,9 @@ module Evoke
13
13
  def start
14
14
  load_tasks
15
15
 
16
+ return no_tasks if tasks.empty?
16
17
  return usage if @command.nil?
17
-
18
- return syntax if @command == "help"
18
+ return syntax if @command == 'help'
19
19
 
20
20
  task = Evoke.find_task(@command) unless @command.nil?
21
21
 
@@ -24,6 +24,8 @@ module Evoke
24
24
  Evoke.invoke(task, *@arguments)
25
25
  end
26
26
 
27
+ private
28
+
27
29
  # Prints the syntax usage of the task requested by help.
28
30
  def syntax
29
31
  return usage if @arguments.empty?
@@ -35,24 +37,26 @@ module Evoke
35
37
  return unknown_command if task.nil?
36
38
 
37
39
  task.print_syntax
40
+
41
+ exit(2)
38
42
  end
39
43
 
40
44
  # Prints the usage for all the discovered tasks.
41
45
  def usage
42
- name_col_size = task_names.group_by(&:size).keys.max.to_i + 2
43
- tasks.each {|task| task.print_usage(name_col_size) }
46
+ grouped_tasks = task_names.group_by(&:size)
47
+ name_sizes = grouped_tasks.keys
48
+ biggest_name = name_sizes.max || 0
49
+ tasks.each { |task| task.print_usage(biggest_name + 2) }
44
50
 
45
51
  exit(2)
46
52
  end
47
53
 
48
- private
49
-
50
54
  # Gets the path for the local evoke.rb file. This doesn't check if the file
51
55
  # actually exists, it only returns the location where it might be.
52
56
  #
53
57
  # @return [String] The path for the evoke file.
54
58
  def evoke_file
55
- @evoke_file = File.join(Dir.pwd, "evoke.rb")
59
+ @evoke_file = File.join(Dir.pwd, 'evoke.rb')
56
60
  end
57
61
 
58
62
  # Loads the Evoke tasks. This will first search for a file named `evoke.rb`
@@ -63,21 +67,18 @@ module Evoke
63
67
  return load(evoke_file) if File.file?(evoke_file)
64
68
 
65
69
  # Load the tasks from the current working directory.
66
- Evoke.load_tasks("lib/tasks")
67
-
68
- # No reason to continue if there are no tasks to work with.
69
- return no_tasks if tasks.empty?
70
+ Evoke.load_tasks('lib/tasks')
70
71
  end
71
72
 
72
73
  # Tells the user there are no tasks to invoke and exits with status 1.
73
74
  def no_tasks
74
- STDERR.puts "No tasks found in the current working directory."
75
+ $stderr.puts 'No tasks found in the current working directory.'
75
76
  exit(1)
76
77
  end
77
78
 
78
79
  # Tells the user that the supplied task could not be found.
79
80
  def unknown_command
80
- STDERR.puts "No task named #{@command.inspect}"
81
+ $stderr.puts "No task named #{@command.inspect}"
81
82
  exit(1)
82
83
  end
83
84
 
@@ -93,7 +94,7 @@ module Evoke
93
94
  #
94
95
  # @return [Array] The name of all the tasks.
95
96
  def task_names
96
- @task_names ||= tasks.map {|task| task.name.underscore }
97
+ @task_names ||= tasks.map { |task| task.name.underscore }
97
98
  end
98
99
  end
99
100
  end
data/lib/evoke/comment.rb CHANGED
@@ -7,33 +7,54 @@ module Evoke
7
7
  # # comment that will be read.
8
8
  # class HelloWorld
9
9
  # extend Evoke::Comment
10
+ #
11
+ # def a_method
12
+ # # this won't work without at least one non-inherited method
13
+ # end
10
14
  # end
11
15
  #
12
16
  # HelloWorld.class_comment # => the multi-line comment before the class
13
17
  #
14
18
  module Comment
15
19
  # Extracts the comment prefixing a class.
16
- #
20
+ # @note At least one non-inherited method needs to be present in the class.
17
21
  # @return [String] The class' comment.
18
22
  def class_comment
19
- start_line, lines = start_index_and_code_lines
23
+ @class_comment ||= defined_methods.empty? ? '' : extract_class_comment
24
+ end
20
25
 
21
- comment = []
26
+ private
22
27
 
23
- (start_line - 1).downto(0).each do |i|
24
- line = lines[i].strip
28
+ # Reads the class's file and extracts the comment of the class that extends
29
+ # this module.
30
+ #
31
+ # @return [String] The multi-line string before the class.
32
+ def extract_class_comment
33
+ bottom_line, lines = start_index_and_code_lines
25
34
 
26
- if line.start_with?('#')
27
- comment << line[1..line.length].strip
28
- elsif comment != ''
29
- break
30
- end
35
+ comment = []
36
+
37
+ (bottom_line - 1).downto(0).each do |i|
38
+ line = parse_comment_line(lines[i])
39
+ break if line == false
40
+ comment << line
31
41
  end
32
42
 
33
- comment.reverse.join("\n")
43
+ comment.reverse.join("\n").strip
34
44
  end
35
45
 
36
- private
46
+ # Parses a line of code and extracts the comment if present.
47
+ #
48
+ # @param [String] line The line of code to parse.
49
+ # @return [NilClass] if the line is empty.
50
+ # @return [Boolean] false if the line is not a comment.
51
+ # @return [String] The extracted comment, without the prefixed # tag.
52
+ # @private
53
+ def parse_comment_line(line)
54
+ line = line.strip
55
+ return if line.empty?
56
+ line.start_with?('#') ? line[1..line.length].strip : false
57
+ end
37
58
 
38
59
  # Gets the lines in the class file and the line number that the class is
39
60
  # actually defined.
@@ -68,10 +89,12 @@ module Evoke
68
89
  # @return [Array] The source locations of every method in the class.
69
90
  # @private
70
91
  def defined_methods
71
- methods = methods(false).map { |m| method(m) }
72
- methods += instance_methods(false).map { |m| instance_method(m) }
73
- methods.map!(&:source_location)
74
- methods.compact
92
+ @defined_methods ||= begin
93
+ methods = methods(false).map { |m| method(m) }
94
+ methods += instance_methods(false).map { |m| instance_method(m) }
95
+ methods.map!(&:source_location)
96
+ methods.compact
97
+ end
75
98
  end
76
99
  end
77
100
  end
@@ -3,9 +3,10 @@ module Evoke
3
3
  # different purposes.
4
4
  module Inflections
5
5
  # Load the inflections.
6
- Dir[File.expand_path("../inflections/*.rb", __FILE__)].each {|f| require f }
6
+ inflections_path = File.expand_path('../inflections/*.rb', __FILE__)
7
+ Dir[inflections_path].each { |f| require f }
7
8
 
8
9
  # Add the inflections to the String class.
9
- constants.each {|i| String.send(:include, const_get(i)) }
10
+ constants.each { |i| String.send(:include, const_get(i)) }
10
11
  end
11
12
  end
@@ -1,35 +1,39 @@
1
- # String inflections for converting to CamelCase.
2
- #
3
- # Camelizing a string takes all the compound words separated by an underscore
4
- # and combines them together, capitalizing the first letter of each word. It
5
- # also converts '/' to '::'. For example "hello_world" is camelized to
6
- # "HelloWorld", and "hello/world" is camelized to "Hello::World".
7
- module Evoke::Inflections::Camelize
8
- # Converts a string to CamelCase. It also converts '/' to '::'.
9
- #
10
- # @example Camelize the string "example/hello_world".
11
- #
12
- # "example/hello_world".camelize # => "Example::HelloWorld"
13
- #
14
- # @return [String] The CamelCase string.
15
- def camelize
16
- dup.tap {|s|
17
- s.capitalize!
18
- s.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" }
19
- s.gsub!("/", "::")
20
- }
21
- end
1
+ module Evoke
2
+ module Inflections
3
+ # String inflections for converting to CamelCase.
4
+ #
5
+ # Camelizing a string takes all the compound words separated by an underscore
6
+ # and combines them together, capitalizing the first letter of each word. It
7
+ # also converts '/' to '::'. For example "hello_world" is camelized to
8
+ # "HelloWorld", and "hello/world" is camelized to "Hello::World".
9
+ module Camelize
10
+ # Converts a string to CamelCase. It also converts '/' to '::'.
11
+ #
12
+ # @example Camelize the string "example/hello_world".
13
+ #
14
+ # "example/hello_world".camelize # => "Example::HelloWorld"
15
+ #
16
+ # @return [String] The CamelCase string.
17
+ def camelize
18
+ dup.tap do |s|
19
+ s.capitalize!
20
+ s.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" }
21
+ s.gsub!('/', '::')
22
+ end
23
+ end
22
24
 
23
- # Replaces the existing String instance with a CamelCase string.
24
- #
25
- # @example Camelizing the string "example/hello_world".
26
- #
27
- # string = "example/hello_world"
28
- # string.camelize!
29
- # string # => "Example::HelloWorld"
30
- #
31
- # @return [String] This string modified to CamelCase.
32
- def camelize!
33
- replace(camelize)
25
+ # Replaces the existing String instance with a CamelCase string.
26
+ #
27
+ # @example Camelizing the string "example/hello_world".
28
+ #
29
+ # string = "example/hello_world"
30
+ # string.camelize!
31
+ # string # => "Example::HelloWorld"
32
+ #
33
+ # @return [String] This string modified to CamelCase.
34
+ def camelize!
35
+ replace(camelize)
36
+ end
37
+ end
34
38
  end
35
39
  end
@@ -1,38 +1,42 @@
1
- # String inflections for converting to underscored form.
2
- #
3
- # Underscoring a string injects an underscore between CamelCase words, replaces
4
- # all '::' with '/' and converts the string to lowercase. For example, the
5
- # string "HelloWorld" is underscored to "hello_world", and the string
6
- # "Hello::World" is underscored to "hello/world".
7
- module Evoke::Inflections::Underscore
8
- # Creates an underscored, lowercase form of the string and changes '::' to '/'
9
- # to convert namespaces to paths.
10
- #
11
- # @example Underscoring "Example::HelloWorld".
12
- #
13
- # "Example::HelloWorld" # => "example/hello_world"
14
- #
15
- # @return [String] The underscored string.
16
- def underscore
17
- dup.tap {|s|
18
- s.gsub!(/::/, '/')
19
- s.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
20
- s.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
21
- s.tr!("-", "_")
22
- s.downcase!
23
- }
24
- end
1
+ module Evoke
2
+ module Inflections
3
+ # String inflections for converting to underscored form.
4
+ #
5
+ # Underscoring a string injects an underscore between CamelCase words, replaces
6
+ # all '::' with '/' and converts the string to lowercase. For example, the
7
+ # string "HelloWorld" is underscored to "hello_world", and the string
8
+ # "Hello::World" is underscored to "hello/world".
9
+ module Underscore
10
+ # Creates an underscored, lowercase form of the string and changes '::' to '/'
11
+ # to convert namespaces to paths.
12
+ #
13
+ # @example Underscoring "Example::HelloWorld".
14
+ #
15
+ # "Example::HelloWorld" # => "example/hello_world"
16
+ #
17
+ # @return [String] The underscored string.
18
+ def underscore
19
+ dup.tap do |s|
20
+ s.gsub!(/::/, '/')
21
+ s.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
22
+ s.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
23
+ s.tr!('-', '_')
24
+ s.downcase!
25
+ end
26
+ end
25
27
 
26
- # Replaces the existing String instance with its underscored form.
27
- #
28
- # @example Underscoring the string "Example::HelloWorld".
29
- #
30
- # string = "Example::HelloWorld"
31
- # string.underscore!
32
- # string # => "example/hello_world"
33
- #
34
- # @return [String] This underscored form of the original string.
35
- def underscore!
36
- replace(underscore)
28
+ # Replaces the existing String instance with its underscored form.
29
+ #
30
+ # @example Underscoring the string "Example::HelloWorld".
31
+ #
32
+ # string = "Example::HelloWorld"
33
+ # string.underscore!
34
+ # string # => "example/hello_world"
35
+ #
36
+ # @return [String] This underscored form of the original string.
37
+ def underscore!
38
+ replace(underscore)
39
+ end
40
+ end
37
41
  end
38
42
  end
@@ -1,6 +1,18 @@
1
1
  module Evoke
2
2
  # Extendable module for providing access to method parameters during runtime.
3
3
  module Parameters
4
+ # Finds the minimum and maximum amount of parameters the supplied method
5
+ # supports.
6
+ #
7
+ # @param [UnboundMethod] method The method to check.
8
+ # @return [Array] The first item is the minimum size, second is the maximum.
9
+ def parameter_size(method)
10
+ req_size = required_parameters(method).size
11
+ opt_size = optional_parameters(method).size
12
+
13
+ [req_size, req_size + opt_size]
14
+ end
15
+
4
16
  # Gets all the required parameters for a method.
5
17
  #
6
18
  # @param [UnboundMethod] method The method to scan.
data/lib/evoke/task.rb CHANGED
@@ -9,8 +9,11 @@ module Evoke
9
9
  # @param [Integer] name_col_size The size of the name column.
10
10
  # @private
11
11
  def print_usage(name_col_size)
12
+ description = "#{@desc || class_comment}".split("\n")[0]
13
+ description ||= 'No description available.'
14
+
12
15
  $stdout.print name.underscore.ljust(name_col_size)
13
- $stdout.puts "# #{@desc || 'No description.'}"
16
+ $stdout.puts "# #{description}"
14
17
  end
15
18
 
16
19
  # Prints the syntax usage for this task to the console.
@@ -31,7 +34,7 @@ module Evoke
31
34
  # @param [String] value The description. Keep it short!
32
35
  # @return [String] The supplied description.
33
36
  def desc(value)
34
- value += "." unless value.end_with?(?.)
37
+ value += '.' unless value.end_with?('.')
35
38
  @desc = value
36
39
  end
37
40
 
@@ -61,13 +64,17 @@ module Evoke
61
64
  # @return nil if the validation passes.
62
65
  # @private
63
66
  def validate_arguments(arguments)
64
- e_size = instance_method(:invoke).arity
65
- a_size = Array(arguments).size
67
+ invoke_method = instance_method(:invoke)
68
+ min, max = parameter_size(invoke_method)
69
+
70
+ size = Array(arguments).size
71
+ return if size >= min && size <= max
72
+
73
+ e_size = min == max ? min : "#{min}..#{max}"
66
74
 
67
- return if e_size == a_size
75
+ $stderr.print 'Wrong number of arguments. '
76
+ $stderr.print "Received #{size} instead of #{e_size}.\n"
68
77
 
69
- $stderr.print "Wrong number of arguments. "
70
- $stderr.print "Received #{a_size} instead of #{e_size}.\n"
71
78
  exit(1)
72
79
  end
73
80
  end
data/lib/evoke/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Evoke
2
- VERSION = "0.1.2"
2
+ VERSION = '0.1.3'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: evoke
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Travis Haynes
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-03-05 00:00:00.000000000 Z
11
+ date: 2015-03-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler