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 +4 -4
- data/.rubocop.yml +13 -0
- data/.travis.yml +6 -0
- data/Gemfile +2 -1
- data/README.md +71 -20
- data/Rakefile +1 -1
- data/lib/evoke.rb +4 -4
- data/lib/evoke/cli.rb +15 -14
- data/lib/evoke/comment.rb +39 -16
- data/lib/evoke/inflections.rb +3 -2
- data/lib/evoke/inflections/camelize.rb +36 -32
- data/lib/evoke/inflections/underscore.rb +39 -35
- data/lib/evoke/parameters.rb +12 -0
- data/lib/evoke/task.rb +14 -7
- data/lib/evoke/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 469f902eb78d1d43894adf316bd4ec3e428a1d3e
|
4
|
+
data.tar.gz: 257b7371196e71be263e7fda29a6e319cfc4177c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# Evoke
|
2
2
|
|
3
|
+
[](http://badge.fury.io/gh/travishaynes%2Fevoke)
|
4
|
+
[](https://travis-ci.org/travishaynes/evoke)
|
5
|
+
[](https://codeclimate.com/github/travishaynes/evoke)
|
6
|
+
[](https://codeclimate.com/github/travishaynes/evoke)
|
7
|
+
[](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
|
-
#
|
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-
|
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
|
-
|
60
|
-
|
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
|
-
|
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
|
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
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,
|
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
|
-
|
43
|
-
|
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,
|
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(
|
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
|
-
|
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
|
-
|
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
|
-
|
23
|
+
@class_comment ||= defined_methods.empty? ? '' : extract_class_comment
|
24
|
+
end
|
20
25
|
|
21
|
-
|
26
|
+
private
|
22
27
|
|
23
|
-
|
24
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
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
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
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
|
data/lib/evoke/inflections.rb
CHANGED
@@ -3,9 +3,10 @@ module Evoke
|
|
3
3
|
# different purposes.
|
4
4
|
module Inflections
|
5
5
|
# Load the inflections.
|
6
|
-
|
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
|
-
|
2
|
-
|
3
|
-
#
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
2
|
-
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# string
|
6
|
-
#
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
data/lib/evoke/parameters.rb
CHANGED
@@ -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 "# #{
|
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 +=
|
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
|
-
|
65
|
-
|
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
|
-
|
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
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.
|
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-
|
11
|
+
date: 2015-03-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|