command_lion 1.0.0

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.
@@ -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