is-command 0.9.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.
- data/.yardopts +9 -0
- data/lib/is/command.rb +351 -0
- metadata +48 -0
data/.yardopts
ADDED
data/lib/is/command.rb
ADDED
@@ -0,0 +1,351 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
module Is
|
6
|
+
|
7
|
+
class Command
|
8
|
+
|
9
|
+
VERSION = '0.9.3'
|
10
|
+
|
11
|
+
module Mixin
|
12
|
+
|
13
|
+
@@messages = {
|
14
|
+
:commands => 'Commands',
|
15
|
+
:actions => 'Actions',
|
16
|
+
:aliases => 'Aliases',
|
17
|
+
:commons => 'Common options',
|
18
|
+
:options => 'Options'
|
19
|
+
}
|
20
|
+
|
21
|
+
class << self
|
22
|
+
|
23
|
+
# @param [Hash] values
|
24
|
+
# @return [Hash]
|
25
|
+
def messages values = {}
|
26
|
+
@@messages.merge! values
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [Symbol, nil]
|
32
|
+
attr_reader :name
|
33
|
+
|
34
|
+
# @return [Array<String>, nil]
|
35
|
+
attr_reader :description
|
36
|
+
|
37
|
+
# @param [Symbol, String] name
|
38
|
+
# @param [Array<String>] description
|
39
|
+
# @yield [*args]
|
40
|
+
# @return [Command]
|
41
|
+
def command name, *description, &block
|
42
|
+
@actions ||= {}
|
43
|
+
@actions[name.intern] = Command.new self, name, *description, &block
|
44
|
+
end
|
45
|
+
|
46
|
+
# @param [Symbol, String, nil] name
|
47
|
+
# @param [Array<String>] description
|
48
|
+
# @yield [*args]
|
49
|
+
# @return [Hash, Proc]
|
50
|
+
def action name = nil, *description, &block
|
51
|
+
@actions ||= {}
|
52
|
+
if name
|
53
|
+
@actions[name.intern] = {
|
54
|
+
:name => name.intern,
|
55
|
+
:description => description,
|
56
|
+
:block => block
|
57
|
+
}
|
58
|
+
else
|
59
|
+
@block = block
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# @param [Symbol, String] name
|
64
|
+
# @return [Command, Hash, Array, String, Symbol, nil]
|
65
|
+
def [] name
|
66
|
+
@actions[name.intern]
|
67
|
+
end
|
68
|
+
|
69
|
+
# @param [Hash, Array<Symbol>, nil] args
|
70
|
+
# @yield [name, action]
|
71
|
+
# @return [void]
|
72
|
+
def each *args, &block
|
73
|
+
if args.size == 0
|
74
|
+
c = a = s = true
|
75
|
+
elsif Hash === args[0]
|
76
|
+
h = args[0]
|
77
|
+
c = h[:command]
|
78
|
+
a = h[:action]
|
79
|
+
s = h[:synonym] || h[:alias]
|
80
|
+
else
|
81
|
+
c = args.include? :command
|
82
|
+
a = args.include? :action
|
83
|
+
s = args.include?(:synonym) || args.include?(:alias)
|
84
|
+
end
|
85
|
+
@actions.select do |k, v|
|
86
|
+
(c && Command === v) || (a && Hash === v) ||
|
87
|
+
(s && (Array === v || String === v || Symbol === v))
|
88
|
+
end.each &block
|
89
|
+
end
|
90
|
+
|
91
|
+
# @yield [*args]
|
92
|
+
# @return [Proc]
|
93
|
+
def default &block
|
94
|
+
action &block
|
95
|
+
end
|
96
|
+
|
97
|
+
# @param [Symbol, String] name
|
98
|
+
# @param [Array<String>, String, Symbol] source
|
99
|
+
# @return [Array<String>, String, Symbol]
|
100
|
+
def synonym name, source
|
101
|
+
@actions ||= {}
|
102
|
+
@actions[name.intern] = source
|
103
|
+
end
|
104
|
+
|
105
|
+
# @return [Array<Hash>]
|
106
|
+
def commons
|
107
|
+
@commons ||= []
|
108
|
+
if @up.respond_to? :commons
|
109
|
+
@up.commons + @commons
|
110
|
+
else
|
111
|
+
@commons
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# @param [Array<String, Class>] defs
|
116
|
+
# @yield [value]
|
117
|
+
# @return [Hash]
|
118
|
+
def key *defs, &block
|
119
|
+
@keys ||= []
|
120
|
+
@commons ||= []
|
121
|
+
if Hash === defs[-1]
|
122
|
+
opts = defs.pop
|
123
|
+
else
|
124
|
+
opts = {}
|
125
|
+
end
|
126
|
+
k = { :defs => defs, :block => block }
|
127
|
+
if opts[:common]
|
128
|
+
@commons << k
|
129
|
+
else
|
130
|
+
@keys << k
|
131
|
+
end
|
132
|
+
k
|
133
|
+
end
|
134
|
+
|
135
|
+
# @param [Array<String>] args
|
136
|
+
# @return [Array<String>]
|
137
|
+
def parse *args
|
138
|
+
@options ||= {}
|
139
|
+
@keys ||= []
|
140
|
+
@commons ||= []
|
141
|
+
context = self
|
142
|
+
opts = OptionParser.new do |o|
|
143
|
+
(commons + @keys).each do |k|
|
144
|
+
defs = k[:defs]
|
145
|
+
block = proc do |value|
|
146
|
+
context.instance_exec value, &k[:block]
|
147
|
+
end
|
148
|
+
o.on *defs, &block
|
149
|
+
end
|
150
|
+
end
|
151
|
+
opts.order args
|
152
|
+
end
|
153
|
+
|
154
|
+
# @param [Array<String>] args
|
155
|
+
# @return [Object, nil]
|
156
|
+
def process *args
|
157
|
+
@actions ||= {}
|
158
|
+
if Hash === args[-1]
|
159
|
+
@options = args.pop
|
160
|
+
else
|
161
|
+
@options = {}
|
162
|
+
end
|
163
|
+
args = parse *args
|
164
|
+
if args[0]
|
165
|
+
a = @actions[args[0].intern]
|
166
|
+
case a
|
167
|
+
when Command
|
168
|
+
args.shift
|
169
|
+
return a.process *args, @options
|
170
|
+
when Hash
|
171
|
+
args.shift
|
172
|
+
args = parse *args
|
173
|
+
return instance_exec *args, &a[:block]
|
174
|
+
when Array
|
175
|
+
args.shift
|
176
|
+
return process *a, *args, @options
|
177
|
+
when String, Symbol
|
178
|
+
args.shift
|
179
|
+
return process a.to_s, *args, @options
|
180
|
+
end
|
181
|
+
end
|
182
|
+
if @block
|
183
|
+
return instance_exec *args, &@block
|
184
|
+
else
|
185
|
+
raise 'Invalid command line.'
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
# @return [String, nil]
|
190
|
+
def fullname
|
191
|
+
if @up && @up.respond_to?(:fullname)
|
192
|
+
@up.fullname + ' ' + @name.to_s
|
193
|
+
else
|
194
|
+
@name.to_s
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
# @param [Hash] opts
|
199
|
+
# @option opts [Boolean, String, :auto] :highlight
|
200
|
+
# @option opts [Boolean, String, :auto] :color
|
201
|
+
# @option opts [String] :marker
|
202
|
+
# @return [String]
|
203
|
+
def help opts = {}
|
204
|
+
h = opts[:highlight] || opts[:color]
|
205
|
+
hl = opts[:marker] || "\e[1m"
|
206
|
+
hr = ''
|
207
|
+
case h
|
208
|
+
when true, :true, :TRUE, :yes, :YES
|
209
|
+
hr = "\e[0m;"
|
210
|
+
when false, :false, :FALSE, :no, :NO
|
211
|
+
hl = ''
|
212
|
+
when nil, :auto, :AUTO
|
213
|
+
if $stdout.stat.chardev?
|
214
|
+
hr = "\e[0m"
|
215
|
+
else
|
216
|
+
hl = ''
|
217
|
+
end
|
218
|
+
else
|
219
|
+
hl = h
|
220
|
+
hr = "\e[0m"
|
221
|
+
end
|
222
|
+
cc = {}
|
223
|
+
aa = {}
|
224
|
+
ss = {}
|
225
|
+
@actions.each do |k, v|
|
226
|
+
case v
|
227
|
+
when Command
|
228
|
+
cc[k] = v
|
229
|
+
when Hash
|
230
|
+
aa[k] = v
|
231
|
+
else
|
232
|
+
ss[k] = v
|
233
|
+
end
|
234
|
+
end
|
235
|
+
mm = opts[:nocommons] ? @commons : commons or []
|
236
|
+
kk = @keys || []
|
237
|
+
result = ''
|
238
|
+
result << "#{hl}#{fullname}#{hr}\n"
|
239
|
+
result << "\t#{@description.join("\n\t")}\n"
|
240
|
+
result << "\n"
|
241
|
+
if ! cc.empty?
|
242
|
+
result << "#{hl}#{@@messages[:commands]}:#{hr}\n"
|
243
|
+
cc.each do |k, v|
|
244
|
+
result << "\t#{k}\n"
|
245
|
+
end
|
246
|
+
result << "\n"
|
247
|
+
end
|
248
|
+
if ! aa.empty?
|
249
|
+
result << "#{hl}#{@@messages[:actions]}:#{hr}\n"
|
250
|
+
aa.each do |k, v|
|
251
|
+
result << "\t#{k}\n"
|
252
|
+
end
|
253
|
+
result << "\n"
|
254
|
+
end
|
255
|
+
if ! ss.empty?
|
256
|
+
result << "#{hl}#{@@messages[:aliases]}:#{hr}\n"
|
257
|
+
aa.each do |k, v|
|
258
|
+
if Array === v
|
259
|
+
value = v.join ' '
|
260
|
+
else
|
261
|
+
value = v.to_s
|
262
|
+
end
|
263
|
+
result << "\t#{k} = #{value}\n"
|
264
|
+
end
|
265
|
+
result << "\n"
|
266
|
+
end
|
267
|
+
if ! mm.empty?
|
268
|
+
result << "#{hl}#{@@messages[:commons]}:#{hr}\n"
|
269
|
+
o = OptionParser.new
|
270
|
+
mm.each do |k|
|
271
|
+
o.on *k[:defs]
|
272
|
+
end
|
273
|
+
result << "#{o.summarize.join('')}\n"
|
274
|
+
#result << "\n"
|
275
|
+
end
|
276
|
+
if ! kk.empty?
|
277
|
+
result << "#{hl}#{@@messages[:options]}:#{hr}\n"
|
278
|
+
o = OptionParser.new
|
279
|
+
kk.each do |k|
|
280
|
+
o.on *k[:defs]
|
281
|
+
end
|
282
|
+
result << "#{o.summarize.join('')}\n"
|
283
|
+
#result << "\n"
|
284
|
+
end
|
285
|
+
aa.each do |k, v|
|
286
|
+
result << "#{hl}#{fullname} #{k}#{hr}\n"
|
287
|
+
result << "\t#{v[:description].join("\n\t")}\n"
|
288
|
+
result << "\n"
|
289
|
+
end
|
290
|
+
cc.each do |k, v|
|
291
|
+
result << v.help(:nocommons => true)
|
292
|
+
end
|
293
|
+
# result << "\n"
|
294
|
+
GC.start
|
295
|
+
result
|
296
|
+
end
|
297
|
+
|
298
|
+
# @return [Proc]
|
299
|
+
def to_proc
|
300
|
+
method(:process).to_proc
|
301
|
+
end
|
302
|
+
|
303
|
+
private :command, :action, :default, :synonym, :key, :parse
|
304
|
+
protected :commons
|
305
|
+
|
306
|
+
end
|
307
|
+
|
308
|
+
class Application
|
309
|
+
|
310
|
+
include Mixin
|
311
|
+
|
312
|
+
def initialize name = nil, *description, &block
|
313
|
+
if name
|
314
|
+
@name = name.intern
|
315
|
+
end
|
316
|
+
@description = description
|
317
|
+
instance_eval &block
|
318
|
+
end
|
319
|
+
|
320
|
+
# @return [Object, nil]
|
321
|
+
def run
|
322
|
+
process *ARGV
|
323
|
+
end
|
324
|
+
|
325
|
+
end
|
326
|
+
|
327
|
+
class << self
|
328
|
+
|
329
|
+
# @param [Symbol, String, nil] name
|
330
|
+
# @param [Array<String>] description
|
331
|
+
# @yield
|
332
|
+
# @return [Object, nil]
|
333
|
+
def runapp name = nil, *description, &block
|
334
|
+
app = Command::Application.new name, *description, &block
|
335
|
+
app.run
|
336
|
+
end
|
337
|
+
|
338
|
+
end
|
339
|
+
|
340
|
+
include Mixin
|
341
|
+
|
342
|
+
def initialize up, name, *description, &block
|
343
|
+
@up = up
|
344
|
+
@name = name.intern if name
|
345
|
+
@description = description
|
346
|
+
instance_eval &block
|
347
|
+
end
|
348
|
+
|
349
|
+
end
|
350
|
+
|
351
|
+
end
|
metadata
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: is-command
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.3
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ivan Shikhalev
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-04-27 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Multicommand apps helper.
|
15
|
+
email: shikhalev@gmail.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- lib/is/command.rb
|
21
|
+
- .yardopts
|
22
|
+
homepage: https://github.com/shikhalev/gems/
|
23
|
+
licenses:
|
24
|
+
- GNU LGPL
|
25
|
+
post_install_message:
|
26
|
+
rdoc_options: []
|
27
|
+
require_paths:
|
28
|
+
- lib
|
29
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ! '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 1.9.2
|
35
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
36
|
+
none: false
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
requirements: []
|
42
|
+
rubyforge_project:
|
43
|
+
rubygems_version: 1.8.25
|
44
|
+
signing_key:
|
45
|
+
specification_version: 3
|
46
|
+
summary: Multicommand apps helper
|
47
|
+
test_files: []
|
48
|
+
has_rdoc:
|