dracula 0.2.0 → 0.2.1

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: 9ef4fdc18122746e01e3149d3fdbc21d262649f0
4
- data.tar.gz: 0a2953b9331e1488dbb11955f1fc9a9ace65a767
3
+ metadata.gz: b6c602659c7e89af0bb4cbc3f0ec4a8a1a55c4b4
4
+ data.tar.gz: e34ed6c3b948eb8e26b258fad6dbd42ea93ec878
5
5
  SHA512:
6
- metadata.gz: 560efe1eb189a1b04726345375797e277893f401a40dff95983ab6f29f31da8fb4710746018a42c3e4d10fd3006ee7751e5473bd4d2b2f1099d8b7d63bf7acb8
7
- data.tar.gz: 84316707c0cee5f937493abc316a67f052b51140cb46430eb6631fed9a1394b3da24a3f3ccc07b799f0cb1731eaddf9b1053dcc948a24ed03101cee0e4cb102c
6
+ metadata.gz: a8a72ba7fc5a3dff0ddba48eb98bc572555582986ac0e17746b067eb87d013cbaab58c6ccb047d5b7911c20703b2a9efbdacaeb8fc8b480d276d074e90302cb0
7
+ data.tar.gz: 44c776e24136257cc0d299a852e6264ea7e77db1114bc9ab578768800253834ff08435b38aefbf0e18a1262150f630f392c6728250f74f1cdd4b7c2d6dc08454
data/README.md CHANGED
@@ -1,27 +1,234 @@
1
- # Dracula
1
+ # Dracula — CLI Framework
2
2
 
3
3
  [![Build Status](https://semaphoreci.com/api/v1/renderedtext/dracula/branches/master/badge.svg)](https://semaphoreci.com/renderedtext/dracula)
4
+ [![Gem Version](https://badge.fury.io/rb/dracula.svg)](https://badge.fury.io/rb/dracula)
4
5
 
5
- ## Usage
6
+ Dracula is a framework for creating command line application.
6
7
 
7
- First, define your commands:
8
+ The structure of the framework is heavily inspired by Thor, and can be even used
9
+ as a drop in replacement for the Thor framework.
10
+
11
+ Opposed to Thor, Dracula generates a Heroku like interface. For example, a task
12
+ management app would have the following interface:
13
+
14
+ ``` txt
15
+ app tasks:list
16
+ app tasks:info
17
+ app calendar:show
18
+ app calendar:events:list
19
+ app calendar:events:add
20
+ ```
21
+
22
+ For help, you can always invoke:
23
+
24
+ ``` txt
25
+ app help <command-name>
26
+ ```
27
+
28
+ ## Hello world example
8
29
 
9
30
  ``` ruby
10
- class Login < Dracula::Command
11
- flag :username, :short => "u", :required => true
12
- flag :password, :short => "p", :required => true
13
- flag :verbose, :short => "v", :type => :boolean
14
-
15
- def run
16
- if flags[:vebose]
17
- puts "Running verbosely"
18
- end
31
+ class CLI < Dracula
19
32
 
20
- puts "Logginng in with #{flags[:username]}:#{flags[:password]}"
33
+ desc "hello", "displays hello messages"
34
+ def hello(message)
35
+ puts "Hi #{message}!"
21
36
  end
37
+
22
38
  end
39
+
40
+ CLI.start(ARGV)
41
+ ```
42
+
43
+ ```
44
+ $ cli hello dracula
45
+
46
+ Hi dracula!
23
47
  ```
24
48
 
49
+ Every method in your class represents a command.
50
+
51
+ ## Command line options
52
+
53
+ A command can have one or more command line options.
54
+
25
55
  ``` ruby
26
- Login.run("--username Vlad --password Transylvania")
56
+ class CLI < Dracula
57
+
58
+ option :name
59
+ desc "hello", "displays hello messages"
60
+ def hello
61
+ puts "Hi #{options[:name]}!"
62
+ end
63
+
64
+ end
65
+
66
+ CLI.start(ARGV)
67
+ ```
68
+
69
+ ```
70
+ $ cli hello --name "Peter"
71
+
72
+ Hi Peter!
73
+ ```
74
+
75
+ The options are defined above the method.
76
+
77
+ #### Default values
78
+
79
+ Options can have default values:
80
+
81
+ ``` ruby
82
+ class CLI < Dracula
83
+
84
+ option :name, :default => "there"
85
+ desc "hello", "displays hello messages"
86
+ def hello
87
+ puts "Hi #{options[:name]}!"
88
+ end
89
+
90
+ end
91
+
92
+ CLI.start(ARGV)
93
+ ```
94
+
95
+ ```
96
+ $ cli hello
97
+
98
+ Hi there!
99
+
100
+ $ cli hello --name Peter
101
+
102
+ Hi Peter!
103
+ ```
104
+
105
+ #### Required options
106
+
107
+ By default, every parameter is optional. You can pass set required to true to
108
+ make the option compulsory.
109
+
110
+ ``` ruby
111
+ class CLI < Dracula
112
+
113
+ option :name, :default => "there", :required => true
114
+ desc "hello", "displays hello messages"
115
+ def hello
116
+ puts "Hi #{options[:name]}!"
117
+ end
118
+
119
+ end
120
+
121
+ CLI.start(ARGV)
27
122
  ```
123
+
124
+ ```
125
+ $ cli hello
126
+
127
+ Missing option: --name NAME
128
+
129
+ $ cli hello --name Peter
130
+
131
+ Hi Peter!
132
+ ```
133
+
134
+ #### Boolean options
135
+
136
+ By default, the options expect a value to be passed. However, if you set the
137
+ type of the option to boolean, only the flag need to be passed:
138
+
139
+ ``` ruby
140
+ class CLI < Dracula
141
+
142
+ option :json, :type => :boolean
143
+ option :name, :required => true
144
+ desc "hello", "displays hello messages"
145
+ def hello
146
+ if options[:json]
147
+ puts '{ "message": "Hi #{options[:name]}!" }'
148
+ else
149
+ puts "Hi #{options[:name]}!"
150
+ end
151
+ end
152
+
153
+ end
154
+
155
+ CLI.start(ARGV)
156
+ ```
157
+
158
+ ```
159
+ $ cli hello --name Peter
160
+
161
+ Hi Peter!
162
+
163
+ $ cli hello --name Peter --json
164
+
165
+ { "message": "Hi Peter!" }
166
+ ```
167
+
168
+ ## Namespaces
169
+
170
+ A CLI application can have subcommands and subnamespaces. For example:
171
+
172
+ ``` ruby
173
+ class Greetings < Dracula
174
+
175
+ desc "hello", "displays a hello message"
176
+ def hello
177
+ puts "Hi!"
178
+ end
179
+
180
+ desc "bye", "displays a bye message"
181
+ def bye
182
+ puts "Bye!"
183
+ end
184
+
185
+ end
186
+
187
+ class CLI < Dracula
188
+
189
+ desc "suck_blood", "suck blood from innocent victims"
190
+ def suck_blood
191
+ puts "BLOOD!"
192
+ end
193
+
194
+ subcommand "greetings", "shows various greetings", Greetings
195
+ end
196
+
197
+ CLI.start(ARGV)
198
+ ```
199
+
200
+ ```
201
+ $ cli suck_blood
202
+ BLOOD!
203
+
204
+ $ cli greetings:hello
205
+ Hi!
206
+
207
+ $ cli greetings:bye
208
+ Bye!
209
+ ```
210
+
211
+ ## Development
212
+
213
+ After checking out the repo, run `bin/setup` to install dependencies. Then,
214
+ run `rake spec` to run the tests. You can also run `bin/console` for an
215
+ interactive prompt that will allow you to experiment.
216
+
217
+ To install this gem onto your local machine, run `bundle exec rake install`.
218
+ To release a new version, update the version number in `version.rb`, and then
219
+ run `bundle exec rake release`, which will create a git tag for the version,
220
+ push git commits and tags, and push the `.gem` file
221
+ to [rubygems.org](https://rubygems.org).
222
+
223
+ ## Contributing
224
+
225
+ Bug reports and pull requests are welcome on GitHub at
226
+ <https://github.com/renderedtext/dracula>. This project is intended
227
+ to be a safe, welcoming space for collaboration, and contributors are expected
228
+ to adhere to the [Contributor Covenant](http://contributor-covenant.org) code
229
+ of conduct.
230
+
231
+ ## License
232
+
233
+ The gem is available as open source under the terms of
234
+ the [MIT License](http://opensource.org/licenses/MIT).
@@ -22,9 +22,20 @@ class Dracula
22
22
  desc.name
23
23
  end
24
24
 
25
+ def arguments
26
+ @klass.instance_method(@method_name).parameters.select { |p| p[0] == :req }.map { |p| p[1].to_s.upcase }
27
+ end
28
+
29
+ def banner
30
+ namespace = @klass.namespace.name ? "#{@klass.namespace.name}:" : ""
31
+ args = arguments.count > 0 ? " #{arguments.join(" ")}" : ""
32
+
33
+ "#{namespace}#{desc.name}#{args}"
34
+ end
35
+
25
36
  def help
26
37
  msg = [
27
- "Usage: #{Dracula.program_name} #{@klass.namespace.name ? "#{@klass.namespace.name}:" : "" }#{desc.name}",
38
+ "Usage: #{Dracula.program_name} #{banner}",
28
39
  "",
29
40
  "#{desc.description}",
30
41
  ""
@@ -46,19 +57,34 @@ class Dracula
46
57
  end
47
58
 
48
59
  def run(params)
49
- args = params.take_while { |p| p[0] != "-" }
50
- flags = parse_flags(params.drop_while { |p| p[0] != "-" })
60
+ args = params.take_while { |p| p[0] != "-" }
51
61
 
52
- missing_flags = missing_required_flags(flags)
62
+ if args.count != arguments.count
63
+ puts "Missing arguments"
64
+ puts ""
65
+ help
66
+ exit(1)
67
+ end
68
+
69
+ parsed_flags = parse_flags(params.drop_while { |p| p[0] != "-" })
53
70
 
54
- if missing_flags.empty?
55
- @klass.new(flags).public_send(method_name, *args)
56
- else
57
- puts "Required Parameter: --#{missing_flags.first.name}"
71
+ missing_flags = missing_required_flags(parsed_flags)
72
+
73
+ unless missing_flags.empty?
74
+ puts "Required Parameter: #{missing_flags.first.banner}"
58
75
  puts ""
59
76
  help
60
77
  exit(1)
61
78
  end
79
+
80
+ @klass.new(parsed_flags).public_send(method_name, *args)
81
+ rescue OptionParser::MissingArgument => ex
82
+ flag = flags.find { |f| "--#{f.name}" == ex.args.first }
83
+
84
+ puts "Parameter has no value: #{flag.banner}"
85
+ puts ""
86
+ help
87
+ exit(1)
62
88
  end
63
89
 
64
90
  private
data/lib/dracula/flag.rb CHANGED
@@ -32,10 +32,28 @@ class Dracula
32
32
  alias_method :short_name, :alias_name
33
33
 
34
34
  def banner
35
- if alias_name.nil?
35
+ if short_name_banner
36
+ "#{short_name_banner}, #{long_name_banner}"
37
+ else
38
+ long_name_banner
39
+ end
40
+ end
41
+
42
+ def short_name_banner
43
+ return nil if short_name.nil?
44
+
45
+ if boolean?
46
+ "-#{short_name}"
47
+ else
48
+ "-#{short_name} #{name.upcase}"
49
+ end
50
+ end
51
+
52
+ def long_name_banner
53
+ if boolean?
36
54
  "--#{name}"
37
55
  else
38
- "-#{alias_name}, --#{name}"
56
+ "--#{name} #{name.upcase}"
39
57
  end
40
58
  end
41
59
 
@@ -1,3 +1,3 @@
1
1
  class Dracula
2
- VERSION = "0.2.0".freeze
2
+ VERSION = "0.2.1".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dracula
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Igor Šarčević
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-08-21 00:00:00.000000000 Z
11
+ date: 2017-08-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler