Module: Command::DSL::Action

Includes:
Formatting
Included in:
Command
Defined in:
lib/command-set/dsl.rb

Overview

The methods available within the DSL::CommandDefinition#action method

The trickiest thing to realize about writing Commands is that a CommandSet is an object that contains several Command subclasses; Commad::setup creates a subclass, and so CommandSet#command does too. It’s when a command is invoked that it’s actually instantiated.

Also note that you can access the arguments of a command as read-only attributes, and you can write to and read from instance variables, which will be local to the invocation of the command. This is especially useful for undo and redo.

Instance Method Summary collapse

Methods included from Formatting

#begin_list, #end_list, #item, #list

Instance Method Details

#action_thread(&block) ⇒ Object

These methods are nodoc’d because at present, they don’t work. They’d be awesome for big jobs - splitting them into subthreads and such. But they need to be debugged, and IIRC there’s a deadlock condition



528
529
530
531
532
533
534
535
# File 'lib/command-set/dsl.rb', line 528

def action_thread(&block) #:nodoc:
  return Thread.new do
    collector = sub_collector
    $stdout.set_thread_collector(collector)
    block.call
    $stdout.remove_thread_collector(collector)
  end
end

#chain(klass_or_path, args) ⇒ Object

It frequently makes sense to offer shortcut chains to the user, or even commands that can only be run as part of another command. Calling chain with either a command class or a command path allows will cause that command to be invoked before returning control to the user.



484
485
486
487
488
489
# File 'lib/command-set/dsl.rb', line 484

def chain(klass_or_path, args)
  setup = CommandSetup.new
  setup.command = klass_or_path
  setup.args_hash = args || {}
  subject.chain_of_command.push(setup)
end

#chain_first(klass_or_path, args) ⇒ Object

Like #chain, but interjects the command being chained to the start of the queue, immediately after this command completes.



493
494
495
496
497
498
# File 'lib/command-set/dsl.rb', line 493

def chain_first(klass_or_path, args)
  setup = CommandSetup.new
  setup.command = klass_or_path
  setup.args_hash = args
  subject.chain_of_command.unshift(setup)
end

#defer(deck = nil) ⇒ Object

Stop here and return control to the user. If several commands are chained (c.f. #chain) and the pause is subsequently resumed (StandardCommands::Resume) the rest of the chain (not this command) will be dropped.

Raises:



458
459
460
# File 'lib/command-set/dsl.rb', line 458

def defer(deck = nil) 
  raise ResumeFromOnlyThis, deck
end

#dont_undoObject

Some commands sometimes cause side effects. When evaluating arguments, if you discover that undoing doesn’t make sense, and will be confusing to the user, call dont_undo, and the interpreter will ignore the call for purposes of undoing



434
435
436
437
# File 'lib/command-set/dsl.rb', line 434

def dont_undo
  @should_undo = false
  return nil
end

#farm_out(array, thread_count, &block) ⇒ Object

:nodoc:



538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
# File 'lib/command-set/dsl.rb', line 538

def farm_out(array, thread_count, &block) #:nodoc:
  first_batch = (array[0...thread_count]||[]).map do |item|
    action_thread { block.call(item) }
  end

  rest = (array[thread_count..-1] || [])

  waiter = ThreadsWait.new(*first_batch)

  rest.each do |item|
    waiter.next_wait
    waiter.join_nowait(action_thread{block.call(item)})
  end

  waiter.join
end

#interruptableObject

This method is deprecated but remains as a nicety. As it stands, any command can be interrupted at the command line with Ctrl-C, and return to the prompt.



520
521
522
# File 'lib/command-set/dsl.rb', line 520

def interruptable
  yield
end

#pause(deck = nil) ⇒ Object

Stop here. Return control to the user. If several commands are chained (c.f. #chain) and the pause is subsequently resumed (StandardCommands::Resume) the whole chain will be resumed.

Raises:



450
451
452
# File 'lib/command-set/dsl.rb', line 450

def pause(deck = nil)
  raise ResumeFrom, deck
end

#sub_collectorObject

This returns a new Results::Collector, which can allow for some very sophisticated command output. Specifically, it can allow a command to loop over a large amount of data once, depositing output in multiple lists at once, for instance a status list (with hashmarks) and results(with useful data) list.



513
514
515
# File 'lib/command-set/dsl.rb', line 513

def sub_collector
  @main_collector.dup
end

#subjectObject

This is how you’ll access the Command::Subject object that’s the interface of every command to the program state.



441
442
443
# File 'lib/command-set/dsl.rb', line 441

def subject
  @subject
end

#task(id) ⇒ Object

Allows for a command to be broken into pieces so that a resume can pick up within a command. The block will be executed normally, but if the command is resumed with a task id, all task blocks until that id will be skipped.



466
467
468
469
470
471
472
473
474
475
# File 'lib/command-set/dsl.rb', line 466

def task(id) #:yield:
  if not @resume_from.nil?
    if @resume_from == id
      @resume_from = nil
    end
    return
  end
  yield if block_given?
  @last_completed_task = id
end

#undo(box) ⇒ Object

Not normally called from within an #action block, this provides the default behavior for an undo (raise an exception)

Raises:



504
505
506
# File 'lib/command-set/dsl.rb', line 504

def undo(box)
  raise CommandException, "#{@name} cannot be undone"
end