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, #sub_collector

Instance Method Details

#chain(*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.



570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
# File 'lib/command-set/dsl.rb', line 570

def chain(*args)
  anchor = CommandSet === args.first ? args.shift : self.parent
  setup = AnchoredCommandSetup.new(anchor)
  setup.arg_hash = Hash === args.last ? args.pop : {}

  if args.length == 1
    args = args[0]
    case args
    when Array
      setup.terms = args
    when String
      setup.terms = [args]
    when Symbol
      setup.terms = [args.to_s]
    when Class
      setup.command_class = args
    else
      raise CommandException, "Can't chain #{args.inspect}"
    end
  else
    if args.find{|arg| not (String === arg or Symbol === arg)}
      raise CommandException, "Can't chain #{args.inspect}"
    else
      setup.terms = args.map{|arg| arg.to_s}
    end
  end

  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.



602
603
604
605
606
607
# File 'lib/command-set/dsl.rb', line 602

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:



544
545
546
# File 'lib/command-set/dsl.rb', line 544

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



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

def dont_undo
  @should_undo = false
  return nil
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.



620
621
622
# File 'lib/command-set/dsl.rb', line 620

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:



536
537
538
# File 'lib/command-set/dsl.rb', line 536

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

#subjectObject

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



527
528
529
# File 'lib/command-set/dsl.rb', line 527

def subject
  @subject_image
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.



552
553
554
555
556
557
558
559
560
561
# File 'lib/command-set/dsl.rb', line 552

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:



613
614
615
# File 'lib/command-set/dsl.rb', line 613

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