command_lion 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,21 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'command_lion'
3
+ require 'pry'
4
+
5
+ CommandLion::App.run do
6
+
7
+ name "File Readr"
8
+
9
+ command :read do
10
+ description "Read the lines from a given file back to the screen."
11
+ flag "--read"
12
+ type :string
13
+
14
+ action do
15
+ IO.foreach(argument) do |line|
16
+ print line
17
+ end
18
+ end
19
+ end
20
+
21
+ end
@@ -0,0 +1,21 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'command_lion'
3
+ require 'pry'
4
+
5
+ CommandLion::App.run do
6
+
7
+ name "Readr"
8
+
9
+ command :read do
10
+ description "Stream arguments read from STDIN back to the screen."
11
+ flag "--read"
12
+ type :stdin_stream
13
+
14
+ action do
15
+ arguments do |argument|
16
+ puts argument
17
+ end
18
+ end
19
+ end
20
+
21
+ end
@@ -0,0 +1,35 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'command_lion'
3
+ require 'pry'
4
+
5
+ CommandLion::App.run do
6
+
7
+ name "Rainbow Hello"
8
+ version "1.0.0"
9
+ description "A typical, contrived example application."
10
+
11
+ command :hello do
12
+ description "A simple command to say hello!"
13
+
14
+ type :string
15
+ flag "hello"
16
+
17
+ default "world"
18
+
19
+ action do
20
+ puts "Hello #{argument}!"
21
+ end
22
+
23
+ option :rainbow do
24
+ description "STDOUT is much prettier with rainbows!"
25
+
26
+ flag "--rainbow"
27
+
28
+ action do
29
+ require 'lolize/auto'
30
+ end
31
+ end
32
+ end
33
+
34
+ end
35
+
@@ -0,0 +1,27 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'command_lion'
3
+ require 'pry'
4
+
5
+ CommandLion::App.run do
6
+ command :example do
7
+ flag "-e"
8
+ type :string
9
+ default "something"
10
+ description "An example command."
11
+ action do
12
+ options[:example].argument.times do
13
+ puts argument
14
+ end
15
+ end
16
+
17
+ option :example do
18
+ flag "--count"
19
+ type :integer
20
+ default 1
21
+ description "How many times to print to the screen."
22
+ action do
23
+ abort "Argument must be an integer greater than or equal to 1" unless argument >= 1
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,19 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'command_lion'
3
+ require 'pry'
4
+
5
+ class Example < CommandLion::Base
6
+ simple_attr :example
7
+ end
8
+
9
+ test = Example.build do
10
+ example "lol"
11
+ end
12
+
13
+ test.example
14
+ # => "lol"
15
+
16
+ test.example?
17
+ # => true
18
+
19
+ puts test
@@ -0,0 +1,20 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'command_lion'
3
+ require 'pry'
4
+
5
+ class Example < CommandLion::Base
6
+ simple_attrs :example1, :example2
7
+ end
8
+
9
+ test = Example.build do
10
+ example1 "lol"
11
+ example2 "lol"
12
+ end
13
+
14
+ test.example1?
15
+ # => true
16
+
17
+ test.example2?
18
+ # => true
19
+
20
+ puts test
@@ -0,0 +1,3 @@
1
+ wiggle
2
+ swiggle
3
+ giggle
@@ -0,0 +1,346 @@
1
+ module CommandLion
2
+
3
+
4
+ # == DSL Keywords:
5
+ # name::
6
+ # The name of your application. This is how your application would be referenced in conversation.
7
+ # It's also going to be used as the defualt banner for the application which will appear at the
8
+ # top of the help menu.
9
+ #
10
+ # == Example
11
+ # app = CommandLion::App.build do
12
+ # name "Example"
13
+ # end
14
+ #
15
+ # app.name?
16
+ # # => true
17
+ #
18
+ # app.name = "Changed Name"
19
+ # # => "Changed Name"
20
+ #
21
+ # app.name
22
+ # # => Changed Name
23
+ # usage::
24
+ # Your usage string can be used to help show the basic information for how to use your application.
25
+ # You can make this as simple or as complex as you like. One will be generated for you by default
26
+ # when your application runs, but won't be pre-built for you inside the build block for now.
27
+ #
28
+ # == Example
29
+ # app = CommandLion::App.build do
30
+ # usage "example [commands] [options...]"
31
+ # end
32
+ #
33
+ # app.usage?
34
+ # # => true
35
+ #
36
+ # app.usage = <<USAGE
37
+ # /|
38
+ # ~~~/ |~
39
+ # tsharky [command] [switches] [--] [arguments]
40
+ # USAGE
41
+ # # => " /|\n" + "~~~/ |~\n" + "tsharky [command] [switches] [--] [arguments]\n"
42
+ #
43
+ # app.usage
44
+ # # => " /|\n" + "~~~/ |~\n" + "tsharky [command] [switches] [--] [arguments]\n"
45
+ #
46
+ # puts app.usage
47
+ # # /|
48
+ # # ~~~/ |~
49
+ # # tsharky [command] [switches] [--] [arguments]
50
+ # description::
51
+ # To provide further context for your application's existence, it's fairly nice to have a description.
52
+ # Like, the usage statement, this can be as complex or as simple as you would like. It isn't required either.
53
+ #
54
+ # == Example
55
+ # app = CommandLion::App.build do
56
+ # description "Example"
57
+ # end
58
+ #
59
+ # app.description?
60
+ # # => true
61
+ #
62
+ # app.description = "Changed"
63
+ # # => "Changed"
64
+ #
65
+ # app.description
66
+ # # => Changed
67
+ class App < Base
68
+
69
+ def self.default_help(app)
70
+ flagz = app.commands.map do |_, cmd|
71
+ if cmd.flags?
72
+ if cmd.flags.long?
73
+ cmd.flags.short + cmd.flags.long
74
+ else
75
+ cmd.flags.short
76
+ end
77
+ elsif cmd.index?
78
+ cmd.index.to_s if cmd.index?
79
+ else
80
+ raise "No flags or index was given!"
81
+ end
82
+ end
83
+ max_flag = flagz.map(&:length).max + 2
84
+ max_desc = app.commands.values.map(&:description).select{|d| d unless d.nil? }.map(&:length).max
85
+ puts app.name
86
+ if app.version?
87
+ puts
88
+ puts "VERSION"
89
+ puts app.version
90
+ end
91
+ if app.description?
92
+ puts
93
+ puts "DESCRIPTION"
94
+ puts app.description
95
+ puts
96
+ end
97
+ if app.usage?
98
+ puts
99
+ puts "USAGE"
100
+ puts usage
101
+ puts
102
+ end
103
+ puts "COMMANDS"
104
+ app.commands.values.select { |cmd| cmd unless cmd.is_a? CommandLion::Option }.each do |command|
105
+ if command.flags?
106
+ short = command.flags.long? ? command.flags.short + ", " : command.flags.short
107
+ short_long = "#{short}#{command.flags.long}".ljust(max_flag)
108
+ else
109
+ short_long = "#{command.index.to_s}".ljust(max_flag)
110
+ end
111
+ puts "#{short_long} #{command.description}"
112
+ if command.options?
113
+ #binding.pry
114
+ command.options.each do |_, option|
115
+ short = option.flags.long? ? option.flags.short + ", " : option.flags.short
116
+ short_long = " " + "#{short}#{option.flags.long}".ljust(max_flag - 2)
117
+ puts "#{short_long} #{option.description}"
118
+ end
119
+ end
120
+ puts
121
+ end
122
+ end
123
+
124
+ def self.run(&block)
125
+ app = new
126
+ app.instance_eval(&block)
127
+ if ARGV.empty?
128
+ if app.help?
129
+ puts app.help
130
+ else
131
+ default_help(app)
132
+ end
133
+ else
134
+ app.parse
135
+ threadz = false
136
+ app.commands.each do |_, cmd|
137
+ next unless cmd.given?
138
+ if cmd.threaded?
139
+ threadz = [] unless threadz
140
+ threadz << Thread.new do
141
+ cmd.before.call if cmd.before?
142
+ cmd.action.call if cmd.action?
143
+ cmd.after.call if cmd.after?
144
+ end
145
+ else
146
+ cmd.before.call if cmd.before?
147
+ cmd.action.call if cmd.action?
148
+ cmd.after.call if cmd.after?
149
+ end
150
+ end
151
+ threadz.map(&:join) if threadz
152
+ end
153
+ end
154
+
155
+ # A tiny bit of rainbow magic is included. You can simple include
156
+ # this option within your application and, if you have the `lolize` gem
157
+ # installed, then rainbows will automagically be hooked to STDOUT to make your
158
+ # application much prettier.
159
+ #
160
+ # It'd be funny if this was turned on by default and you had to opt-out of the
161
+ # rainbows. Good thing I didn't do that, right?
162
+ def rainbows
163
+ require 'lolize/auto'
164
+ rescue
165
+ raise "The 'lolize' gem is not installed. Install it for rainbow magic!"
166
+ end
167
+
168
+ # Simple attributes for the application. Mostly just metadata to help
169
+ # provide some context to the application.
170
+ #
171
+ # * `name` is the name people would refernce your application to in conversation.
172
+ # * `usage` is a simple, optional custom string to provide further context for the app.
173
+ # * `description` allows you to describe what your application does and why it exists.
174
+ # * `version` allows you to do simple version control for your app.
175
+ simple_attrs :name, :usage, :description, :version, :help
176
+
177
+ # An application usually has multiple commands.
178
+ #
179
+ # app = CommandLion::App.build
180
+ # # meta information
181
+ #
182
+ # command :example1 do
183
+ # # more code
184
+ # end
185
+ #
186
+ # command :example2 do
187
+ # # more code
188
+ # end
189
+ # end
190
+ #
191
+ # app.commands.map(&:name)
192
+ # # => [:example1, :example2]
193
+ def command(index, &block)
194
+ if index.is_a? Command
195
+ cmd = index
196
+ else
197
+ cmd = Command.new
198
+ cmd.index= index
199
+ cmd.instance_eval(&block)
200
+ end
201
+ @commands = {} unless @commands
202
+ @flags = [] unless @flags
203
+ if cmd.flags?
204
+ @flags << cmd.flags.short if cmd.flags.short?
205
+ @flags << cmd.flags.long if cmd.flags.long?
206
+ elsif cmd.index # just use index
207
+ @flags << cmd.index.to_s
208
+ else
209
+ raise "No index or flags were given to use this command."
210
+ end
211
+ if cmd.options?
212
+ cmd.options.each do |_, option|
213
+ @flags << option.flags.short if cmd.flags.short?
214
+ @flags << option.flags.long if cmd.flags.long?
215
+ @commands << option
216
+ end
217
+ end
218
+ @commands[cmd.index] = cmd
219
+ cmd
220
+ end
221
+
222
+ # Plugin a command.
223
+ def plugin(command)
224
+ command(command)
225
+ end
226
+
227
+ # Direct access to the various flags an application has.
228
+ def flags
229
+ @flags
230
+ end
231
+
232
+ # Direct access to the various commands an application has.
233
+ def commands
234
+ @commands
235
+ end
236
+
237
+ # Parse arguments off of ARGV.
238
+ def parse
239
+ @commands.each do |_, cmd|
240
+ if cmd.flags?
241
+ next unless argv_index = ARGV.index(cmd.flags.short) or ARGV.index(cmd.flags.long)
242
+ else
243
+ next unless argv_index = ARGV.index(cmd.index.to_s)
244
+ end
245
+ cmd.given = true unless argv_index.nil?
246
+ if cmd.type.nil?
247
+ yield cmd if block_given?
248
+ else
249
+ if parsed = parse_cmd(cmd, flags)
250
+ cmd.arguments = parsed || cmd.default
251
+ yield cmd if block_given?
252
+ elsif cmd.default
253
+ cmd.arguments = cmd.default
254
+ yield cmd if block_given?
255
+ end
256
+ end
257
+ end
258
+ end
259
+
260
+ # Parse a given command with its
261
+ def parse_cmd(cmd, flags)
262
+ args = Raw.arguments_to(cmd.flags.short, flags)
263
+ if args.empty?
264
+ args = Raw.arguments_to(cmd.flags.long, flags)
265
+ end
266
+ return nil if args.nil?
267
+ case cmd.type
268
+ when :stdin
269
+ args = STDIN.gets.strip
270
+ when :stdin_stream
271
+ args = STDIN
272
+ when :stdin_string
273
+ args = STDIN.gets.strip
274
+ when :stdin_strings
275
+ args = STDIN.gets.strip
276
+ when :stdin_integer
277
+ args = STDIN.gets.strip.to_i
278
+ when :stdin_integers
279
+ args = []
280
+ while arg = STDIN.gets
281
+ next if arg.nil?
282
+ arg = arg.strip
283
+ parse = arg.to_i
284
+ if parse.to_s == arg
285
+ args << parse
286
+ end
287
+ end
288
+ args
289
+ when :stdin_bool
290
+ args = STDIN.gets.strip.downcase == "true"
291
+ when :single, :string
292
+ args.first
293
+ when :strings, :multi
294
+ if cmd.delimiter?
295
+ if args.count > 1
296
+ args = args.first.split(cmd.delimiter)
297
+ #args = args.first.join.split(cmd.delimiter).flatten.select { |arg| arg unless arg.empty? }
298
+ #args = args.select { |arg| arg if arg.include?(cmd.delimiter) }
299
+ #args = args.map { |arg| arg.split(cmd.delimiter) }.flatten
300
+ else
301
+ args = args.map { |arg| arg.split(cmd.delimiter) }.flatten
302
+ end
303
+ end
304
+ args
305
+ when :integer
306
+ args.first.to_i
307
+ when :integers
308
+ if cmd.delimiter?
309
+ if args.count > 1
310
+ args = args.join
311
+ args = args.select { |arg| arg if arg.include?(cmd.delimiter) }
312
+ args = args.map { |arg| arg.split(cmd.delimiter) }.flatten
313
+ else
314
+ args = args.map { |arg| arg.split(cmd.delimiter) }.flatten
315
+ end
316
+ end
317
+ args.map(&:to_i)
318
+ when :bool, :bools
319
+ if cmd.delimiter?
320
+ if args.count > 1
321
+ args = args.join
322
+ args = args.select { |arg| arg if arg.include?(cmd.delimiter) }
323
+ args = args.map { |arg| arg.split(cmd.delimiter) }.flatten
324
+ else
325
+ args = args.map { |arg| arg.split(cmd.delimiter) }.flatten
326
+ end
327
+ end
328
+ args.map { |arg| arg == "true" }
329
+ end
330
+ rescue => e# this is dangerous
331
+ puts e
332
+ nil
333
+ end
334
+
335
+ def run!
336
+ parse do |cmd|
337
+ cmd.action.call
338
+ end
339
+ end
340
+
341
+ if __FILE__== $0
342
+ run!
343
+ end
344
+ end
345
+
346
+ end
@@ -0,0 +1,112 @@
1
+ module CommandLion
2
+
3
+ class Base
4
+
5
+ class << self
6
+ # Build up an object with a given block.
7
+ # @param [&block]
8
+ #
9
+ # == Basic Usage
10
+ # class Example < CommandLion::Base
11
+ # simple_attr :example
12
+ # end
13
+ #
14
+ # test = Example.build do
15
+ # example "lol"
16
+ # end
17
+ #
18
+ # test.example
19
+ # # => "lol"
20
+ #
21
+ # test.example?
22
+ # # => true
23
+ #
24
+ def build(&block)
25
+ obj = new
26
+ obj.instance_eval(&block)
27
+ obj
28
+ end
29
+
30
+ # Quickly spin up an in-memory key-value storage object for the framework.
31
+ #
32
+ # == Basic Usage
33
+ # class Example < CommandLion::Base
34
+ # key_value :example
35
+ # end
36
+ #
37
+ # test = Example.new
38
+ # test.example[:lol] = "lol"
39
+ #
40
+ # test.example[:lol]
41
+ # # => "lol"
42
+ #
43
+ def key_value(attribute)
44
+ define_method :"#{attribute}" do
45
+ instance_variable_set(:"@#{attribute}", Hash.new) unless instance_variable_get(:"@#{attribute}")
46
+ instance_variable_get(:"@#{attribute}")
47
+ end
48
+ end
49
+
50
+ # This method is important for creating the basic attributes for the framework.
51
+ # @param attribute [Symbol]
52
+ #
53
+ # == Basic Usage
54
+ # class Example < CommandLion::Base
55
+ # simple_attr :example
56
+ # end
57
+ #
58
+ # test = Example.new
59
+ #
60
+ # test.example
61
+ # # => nil
62
+ #
63
+ # test.example?
64
+ # # => false
65
+ #
66
+ # test.example = "lol"
67
+ # # => "lol"
68
+ #
69
+ # test.example
70
+ # # => "lol"
71
+ #
72
+ # test.example?
73
+ # # => true
74
+ #
75
+ def simple_attr(attribute)
76
+ define_method :"#{attribute}" do |value = nil|
77
+ return instance_variable_get(:"@#{attribute}") if value.nil?
78
+ instance_variable_set(:"@#{attribute}", value)
79
+ end
80
+ define_method :"#{attribute}=" do |value|
81
+ instance_variable_set(:"@#{attribute}", value)
82
+ end
83
+ define_method :"#{attribute}?" do
84
+ return true if instance_variable_get(:"@#{attribute}")
85
+ false
86
+ end
87
+ end
88
+
89
+ # This method is important for creating multiple basic attributes.
90
+ # @param attribute [Array<Symbol>]
91
+ #
92
+ # == Basic Usage
93
+ # class Example < CommandLion::Base
94
+ # simple_attrs :example, :example2
95
+ # end
96
+ #
97
+ # test = Example.new
98
+ #
99
+ # test.example = "lol"
100
+ # test.example2 = "lol2"
101
+ #
102
+ def simple_attrs(*attributes)
103
+ attributes.each do |attribute|
104
+ simple_attr(attribute)
105
+ end
106
+ end
107
+
108
+ end
109
+
110
+ end
111
+
112
+ end