Class: Command::Command
Defined Under Namespace
Classes: DontResume
Class Attribute Summary collapse
Instance Attribute Summary collapse
#advice_block, #argument_list, #context
Class Method Summary
collapse
Instance Method Summary
collapse
action, document, doesnt_undo, format_advice, parent_argument, parent_arguments, subject_methods, undo
#alternating_argument, #argument, argument_typemap, #create, #create_decorator, document, #named_optionals, register_argument, register_decorator, #special_argument, #subject
consume_terms, embed_argument, executeable?, optional_argument
Methods included from Common
add_requirements, completion_list, find_command, process_terms
#action_thread, #chain, #chain_first, #defer, #dont_undo, #fan_out, #pause, #root, #subject, #task, #undo, #up
#begin_list, #end_list, #item, #list, #sub_collector
Constructor Details
#initialize(execution_context, resume = nil) ⇒ Command
Returns a new instance of Command.
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
|
# File 'lib/command-set/command.rb', line 256
def initialize(execution_context, resume=nil)
raise CommandException, "#{@name}: unrecognized command" unless self.class.defined?
@path = execution_context.command_path
@nesting = execution_context.set_nesting
@argument_list = self.class.argument_list.dup
@subject_requirements = self.class.subject_requirements.dup
resolve_parent_arguments
subject = execution_context.subject
context = execution_context.subject_context
@subject_image = subject.get_image(subject_requirements || [], context)
@arg_hash = {}
@should_undo = true
@validation_problem = CommandException.new("No arguments provided!")
@last_completed_task = DontResume
@resume_from = resume
@main_collector = nil
end
|
Class Attribute Details
.defined ⇒ Object
Returns the value of attribute defined.
120
121
122
|
# File 'lib/command-set/command.rb', line 120
def defined
@defined
end
|
.doc_text ⇒ Object
Returns the value of attribute doc_text.
120
121
122
|
# File 'lib/command-set/command.rb', line 120
def doc_text
@doc_text
end
|
.name ⇒ Object
Returns the value of attribute name.
120
121
122
|
# File 'lib/command-set/command.rb', line 120
def name
@name
end
|
Instance Attribute Details
#arg_hash ⇒ Object
Returns the value of attribute arg_hash.
320
321
322
|
# File 'lib/command-set/command.rb', line 320
def arg_hash
@arg_hash
end
|
#nesting ⇒ Object
Returns the value of attribute nesting.
320
321
322
|
# File 'lib/command-set/command.rb', line 320
def nesting
@nesting
end
|
#path ⇒ Object
Returns the value of attribute path.
320
321
322
|
# File 'lib/command-set/command.rb', line 320
def path
@path
end
|
Class Method Details
.create_argument_methods ⇒ Object
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
|
# File 'lib/command-set/command.rb', line 225
def create_argument_methods
names = argument_list.inject([]) do |list, arg|
list + [*arg.names]
end
names.each do |name|
define_method(name) do
@arg_hash[name]
end
private(name)
define_method(name.to_s + "=") do |value|
@arg_hash[name] = value
end
private(name.to_s + "=")
end
end
|
.defined? ⇒ Boolean
192
193
194
|
# File 'lib/command-set/command.rb', line 192
def defined?
return @defined
end
|
.documentation(width, prefix = []) ⇒ Object
202
203
204
205
206
207
208
209
|
# File 'lib/command-set/command.rb', line 202
def documentation(width, prefix=[])
if @doc_text.nil?
return short_docs(width, prefix)
else
return short_docs(width) +
["\n"] + @doc_text.wrap(width)
end
end
|
.each_command(path, visitor) ⇒ Object
163
164
165
|
# File 'lib/command-set/command.rb', line 163
def each_command(path, visitor)
visitor.arrive_at(path, self)
end
|
.inherited(subclass) ⇒ Object
122
123
124
125
126
127
128
129
130
131
132
133
134
|
# File 'lib/command-set/command.rb', line 122
def inherited(subclass)
[ [:name, proc {name.dup}],
[:argument_list, proc {argument_list.dup }],
[:parent_arguments, proc {parent_arguments.dup }],
[:doc_text, proc {doc_text.nil? ? nil : doc_text.dup}],
[:subject_requirements, proc {subject_requirements.dup}],
[:defined, proc {false}],
[:advice_block, proc {advice_block.dup}],
[:context, proc {[]}]
].each do |var, prok|
subclass.instance_variable_set("@#{var.to_s}", prok.call)
end
end
|
.initialize_copy(original) ⇒ Object
136
137
138
139
140
141
142
|
# File 'lib/command-set/command.rb', line 136
def initialize_copy(original)
super
@argument_list = original.argument_list.dup
@parent_arguments = original.parent_arguments.dup
@subject_requirements = original.subject_requirements.dup
@context = []
end
|
.inspect ⇒ Object
196
197
198
199
200
|
# File 'lib/command-set/command.rb', line 196
def inspect
arguments = argument_list.map{|arg| arg.name}
return "#<Class:#{"%0#x" % self.object_id} - Command:#{name()}(#{arguments.join(", ")})>"
end
|
.parent_argument_list ⇒ Object
167
168
169
|
# File 'lib/command-set/command.rb', line 167
def parent_argument_list
@parent_arguments
end
|
.push_context(part) ⇒ Object
243
244
245
246
|
# File 'lib/command-set/command.rb', line 243
def push_context(part)
return unless Symbol === part
@context.unshift(part)
end
|
.setup(new_name = nil, &block) ⇒ Object
Establishes a subclass of Command. This is important because commands are actually classes in CommandSet; their instances are specific executions of the command, which allows for undo’s, and history management. The block will get run in the context of the new class, allowing you to quickly define the class completely.
For examples, see Command::StandardCommands
151
152
153
154
155
156
157
158
159
160
161
|
# File 'lib/command-set/command.rb', line 151
def setup(new_name=nil, &block)
command_class = Class.new(self)
new_name = new_name.to_s
command_class.instance_variable_set("@name", new_name)
command_class.instance_eval &block
command_class.defined
return command_class
end
|
.short_docs(width, prefix = []) ⇒ Object
211
212
213
214
215
216
217
218
219
220
221
222
223
|
# File 'lib/command-set/command.rb', line 211
def short_docs(width, prefix=[])
docs = prefix + [name]
docs += argument_list.map do |arg|
if arg.required?
"<#{arg.name}>"
else
"[#{arg.name}]"
end
end
return docs.join(" ").wrap(width)
end
|
.single_consume(argument, arg_hash, subject, terms) ⇒ Object
183
184
185
|
# File 'lib/command-set/command.rb', line 183
def single_consume(argument, arg_hash, subject, terms)
arg_hash.merge! argument.consume(subject, terms)
end
|
.visit(terms, visitor) ⇒ Object
Also known as:
root_visit
171
172
173
174
175
176
177
178
179
|
# File 'lib/command-set/command.rb', line 171
def visit(terms, visitor)
visitor.arrive_at(terms, self)
if(terms.empty?)
return visitor.command_out_of_terms(self)
else
return visitor.(terms, self)
end
end
|
Instance Method Details
371
372
373
|
# File 'lib/command-set/command.rb', line 371
def advise_formatter(formatter)
formatter.receive_advice(&self.class.advice_block)
end
|
#all_arguments ⇒ Object
332
333
334
|
# File 'lib/command-set/command.rb', line 332
def all_arguments
@argument_list
end
|
#consume_hash(args_hash) ⇒ Object
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
|
# File 'lib/command-set/command.rb', line 388
def consume_hash(args_hash)
allowed_arguments = all_arguments.inject([]) do |allowed, argument|
allowed += [*argument.name]
end
wrong_values = {}
required_names = []
args_hash.keys.each do |name|
args_hash[name.to_s] = args_hash[name]
end
all_arguments.each do |argument|
begin
@arg_hash.merge! argument.consume_hash(@subject_image, args_hash)
rescue ArgumentInvalidException => aie
wrong_values.merge! aie.pairs
rescue OutOfArgumentsException
required_names += ([*argument.name].find_all {|name| not @arg_hash.has_key?(name)})
end
end
wrong_names = @arg_hash.keys - allowed_arguments
unless wrong_values.empty?
aie = ArgumentInvalidException.new(wrong_values)
@validation_problem = aie
raise aie
end
unless wrong_names.empty?
aue = ArgumentUnrecognizedException.new("Unrecognized arguments: #{wrong_names.join(", ")}")
@validation_problem = aue
raise aue
end
unless required_names.empty?
ooae = OutOfArgumentsException.new("Missing arguments: #{required_names.join(", ")}")
@validation_problem = ooae
raise ooae
end
@validation_problem = nil
end
|
#go(collector) ⇒ Object
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
|
# File 'lib/command-set/command.rb', line 349
def go(collector)
return if @resume_from == DontResume
unless self.respond_to? :execute
raise CommandException, "#{self.path}: command declared but no action defined"
end
@main_collector = collector
begin
validate_arguments
verify_image
execute
join_undo
rescue Interrupt
puts "Command cancelled"
rescue ResumeFrom => rf
rf.setup.task_id = @last_completed_task
rf.setup.command_class = self.class
rf.setup.arg_hash = arg_hash.dup
raise rf
end
end
|
#inspect ⇒ Object
340
341
342
343
|
# File 'lib/command-set/command.rb', line 340
def inspect
name = self.class.name
return "#<Command:#{name}>:#{"%#x" % self.object_id} #{@arg_hash.inspect}"
end
|
#join_undo ⇒ Object
437
438
439
440
441
442
|
# File 'lib/command-set/command.rb', line 437
def join_undo
if(undoable? && @should_undo && subject.undo_stack != nil)
subject.undo_stack.add(self)
end
return nil
end
|
#name ⇒ Object
322
323
324
|
# File 'lib/command-set/command.rb', line 322
def name
self.class.name
end
|
#parent ⇒ Object
345
346
347
|
# File 'lib/command-set/command.rb', line 345
def parent
@nesting.last
end
|
#required_arguments ⇒ Object
326
327
328
329
330
|
# File 'lib/command-set/command.rb', line 326
def required_arguments
@argument_list.find_all do |arg|
arg.required?
end
end
|
#resolve_parent_arguments ⇒ Object
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
|
# File 'lib/command-set/command.rb', line 277
def resolve_parent_arguments
missing = []
names = []
self.class.parent_argument_list.uniq.each do |name|
found = nil
@nesting.reverse.each do |set_nesting|
found = set_nesting.argument_list.find do |argument|
argument.names.include? name
end
unless found.nil?
@subject_requirements += found.subject_requirements
@argument_list << found
break
end
end
if found.nil?
missing << name
else
names += [*found.names]
end
end
unless missing.empty?
raise CommandError,
"No parent has an argument named \"#{missing.join(", ")}\""
end
names.each do |name|
(class << self; self; end).instance_eval do
define_method(name) do
@arg_hash[name]
end
private(name)
define_method(name.to_s + "=") do |value|
@arg_hash[name] = value
end
private(name.to_s + "=")
end
end
end
|
#subject_requirements ⇒ Object
336
337
338
|
# File 'lib/command-set/command.rb', line 336
def subject_requirements
@subject_requirements
end
|
#undoable? ⇒ Boolean
433
434
435
|
# File 'lib/command-set/command.rb', line 433
def undoable?
return false
end
|
#validate_arguments ⇒ Object
444
445
446
447
448
449
|
# File 'lib/command-set/command.rb', line 444
def validate_arguments
raise @validation_problem if Exception === @validation_problem
required_arguments.each do |argument|
argument.check_present(@arg_hash.keys)
end
end
|
#verify_image ⇒ Object
375
376
377
378
379
380
381
382
383
384
385
386
|
# File 'lib/command-set/command.rb', line 375
def verify_image
return if subject_requirements.nil?
subject_requirements.each do |requirement|
begin
if Subject::UndefinedField === @subject_image.send(requirement)
raise CommandException, "\"#{name}\" requires \"#{requirement.to_s}\" to be set"
end
rescue NameError => ne
raise CommandException, "\"#{name}\" requires subject to include \"#{requirement.to_s}\""
end
end
end
|