evoke 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
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