dracula 0.2.0 → 0.2.1

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: 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