command-set 0.10.0 → 0.10.1

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.
@@ -155,8 +155,8 @@ module Command
155
155
  def initialize(name="")
156
156
  @name = name
157
157
  @command_list = { nil => RootCommand.setup(self, nil) {} }
158
+ @mode_commands = {}
158
159
  @included_sets = []
159
- @subject_template = nil
160
160
  @documentation = ""
161
161
  @prompt = nil
162
162
  @arguments = []
@@ -220,12 +220,18 @@ module Command
220
220
  @command_list.each_pair do |term, command|
221
221
  command.each_command(path + [term], visitor)
222
222
  end
223
+ return unless path.empty?
224
+ @mode_commands.each_pair do |term, command|
225
+ command.each_command([term], visitor)
226
+ end
223
227
  end
224
228
 
225
229
  def root_visit(terms, visitor)
226
230
  next_hop = if(terms.empty?)
227
231
  visitor.set_out_of_terms(self)
228
232
  @command_list[nil]
233
+ elsif(visitor.command_path.empty?)
234
+ @mode_commands[terms.first] || @command_list[terms.first]
229
235
  else
230
236
  @command_list[terms.first]
231
237
  end
@@ -307,10 +313,35 @@ module Command
307
313
 
308
314
  alias short_docs documentation
309
315
 
316
+ def build_command(home, name_or_class, name_or_nil, block)
317
+ if Class === name_or_class && Command > name_or_class
318
+ if block.nil?
319
+ command = name_or_class.dup
320
+ name = command.name
321
+ else
322
+ name = name_or_nil.to_s
323
+ command = name_or_class.setup(self, name, &block)
324
+ end
325
+ else
326
+ if String === name_or_class or Symbol === name_or_class
327
+ name = name_or_class.to_s
328
+ else
329
+ raise RuntimeError, "#{name_or_class} is neither a Command class nor a name!"
330
+ end
331
+ command = Command.setup(name, &block)
332
+ end
333
+
334
+ home[name] = command
335
+ end
336
+
310
337
  def command_list
311
338
  return @command_list.dup
312
339
  end
313
340
 
341
+ def mode_commands
342
+ return @mode_commands.dup
343
+ end
344
+
314
345
  def command_names
315
346
  return @command_list.keys.compact
316
347
  end
@@ -33,51 +33,6 @@ module Command
33
33
  end
34
34
  end
35
35
 
36
- =begin
37
- #An abstraction of the lifecycle of a command. Allows invocations to be
38
- #postponed temporarily, or for the command to be instantiated and still
39
- #passed around. Client code should almost never need to see this class,
40
- #so the methods aren't individually documented.
41
- class CommandSetup
42
- def initialize(cmd = [], args = {})
43
- @task_id = nil
44
- @args_hash = args
45
- @terms = []
46
- @command = cmd
47
- @execution_context = nil
48
- end
49
-
50
- attr_accessor :task_id, :command, :args_hash, :terms
51
-
52
- def class_resolution(command_set, path, subject)
53
- return command_set.process_terms(path, subject)
54
- end
55
-
56
- def resolve_command_class(command_set, subject)
57
- if @execution_context.nil? && Class === @command && Command > @command
58
- @execution_context = TermProcessor.new(subject)
59
- else
60
- command_path = @command
61
- @execution_context = class_resolution(command_set,
62
- command_path,
63
- subject)
64
- @command = @execution_context.command_class
65
- @args_hash = @execution_context.arg_hash.merge(@args_hash)
66
- @terms = command_path
67
- end
68
-
69
- return @command
70
- end
71
-
72
- def command_instance(command_set, subject)
73
- command_class = resolve_command_class(command_set, subject)
74
- command = command_class.new(@execution_context, task_id)
75
- command.consume_hash(@args_hash)
76
- return command
77
- end
78
- end
79
- =end
80
-
81
36
  class AnchoredCommandSetup < CommandSetup
82
37
  def initialize(command_set, cmd = [], args = {})
83
38
  super(cmd, args)
@@ -21,6 +21,7 @@ Action:: utility functions within the command action block
21
21
  #the new commands.
22
22
  def include_commands(set, *commands)
23
23
  new_commands = set.command_list
24
+ new_mode_commands = set.mode_commands
24
25
  options = Hash === commands.first ? commands.shift : {}
25
26
 
26
27
  commands.map!{|c| c.to_s}
@@ -28,9 +29,12 @@ Action:: utility functions within the command action block
28
29
  new_commands.delete_if do |name,command|
29
30
  not commands.include? name
30
31
  end
32
+ new_mode_commands.delete_if do |name, command|
33
+ not commands.include? name
34
+ end
31
35
  end
32
36
 
33
- unless new_commands.empty?
37
+ unless new_commands.empty? and new_mode_commands.empty?
34
38
  @included_sets << [set, options]
35
39
  end
36
40
 
@@ -44,13 +48,17 @@ Action:: utility functions within the command action block
44
48
  next unless CommandSet === command
45
49
  @command_list[name].include_commands(command)
46
50
  else
47
- @command_list[name] = command.clone
51
+ @command_list[name] = command
48
52
  end
49
53
  unless(options[:context].nil?)
50
54
  @command_list[name] = ContextBoundary.new(@command_list[name],
51
55
  options[:context])
52
56
  end
53
57
  end
58
+
59
+ new_mode_commands.each_pair do |name, command|
60
+ @mode_commands[name] = command
61
+ end
54
62
  end
55
63
 
56
64
  #If you've got a file dedicated to a set of commands, (and you really
@@ -96,32 +104,28 @@ Action:: utility functions within the command action block
96
104
  # be a subclass of the class you passed in, which is great for a
97
105
  # series of related commands.
98
106
  def command(name_or_command_class, name_or_nil=nil, &block)
99
- @subject_template = nil
100
-
101
- if Class === name_or_command_class && Command > name_or_command_class
102
- if block.nil?
103
- command = name_or_command_class.dup
104
- name = command.name
105
- else
106
- name = name_or_nil.to_s
107
- command = name_or_command_class.setup(self, name, &block)
108
- end
109
- elsif name_or_command_class.nil?
107
+ if name_or_command_class.nil?
110
108
  command = @command_list[nil]
111
109
  command.instance_eval(&block)
112
110
  return
113
111
  else
114
- if String === name_or_command_class or Symbol === name_or_command_class
115
- name = name_or_command_class.to_s
116
- else
117
- raise RuntimeError, "#{name_or_command_class} is neither a Command class nor a name!"
118
- end
119
- command = Command.setup(name, &block)
112
+ build_command(@command_list, name_or_command_class,
113
+ name_or_nil, block)
114
+ end
115
+ end
116
+
117
+ def command_alias(name, command)
118
+ if Array === command
119
+ command = find_command(command)
120
120
  end
121
121
 
122
122
  @command_list[name] = command
123
123
  end
124
124
 
125
+ def mode_command(name_or_class, name_or_nil=nil, &block)
126
+ build_command(@mode_commands, name_or_class, name_or_nil, block)
127
+ end
128
+
125
129
  #Defines a nested CommandSet. Commands within the nested set will be
126
130
  #referenced by preceding them with the name of the set.
127
131
  #DSL::CommandSetDefinition will be available within the block to be
@@ -606,6 +610,14 @@ Action:: utility functions within the command action block
606
610
  subject.chain_of_command.unshift(setup)
607
611
  end
608
612
 
613
+ def up(levels = 1)
614
+ return @nesting[-(levels+1)]
615
+ end
616
+
617
+ def root
618
+ return @nesting[0]
619
+ end
620
+
609
621
  #:section: Miscellany
610
622
 
611
623
  #Not normally called from within an #action block, this provides the
@@ -14,7 +14,7 @@ module Command
14
14
  # #get_formatter, and #prompt_user
15
15
  class BaseInterpreter
16
16
  attr_accessor :out_io, :logger
17
- attr_reader :subject, :command_set
17
+ attr_reader :subject, :command_set, :sub_modes
18
18
 
19
19
  def initialize
20
20
  @command_set=nil
@@ -51,7 +51,6 @@ module Command
51
51
  @subject = subject
52
52
  end
53
53
 
54
-
55
54
  def command_set=(set)
56
55
  @command_set = set
57
56
  @subject = prep_subject(get_subject)
@@ -79,13 +78,13 @@ module Command
79
78
  raise RuntimeError, "Sub-modes must be CommandSets!"
80
79
  end
81
80
 
82
- @sub_modes.push([mode, mode.most_recent_args, nesting])
81
+ sub_modes.push([mode, mode.most_recent_args, nesting])
83
82
  return nil
84
83
  end
85
84
 
86
85
  # The compliment to #push_mode. Removes the most recent command set.
87
86
  def pop_mode
88
- @sub_modes.pop
87
+ sub_modes.pop
89
88
  return nil
90
89
  end
91
90
 
@@ -94,8 +93,8 @@ module Command
94
93
  #If your interpreter needs extra fields in the subject, alter
95
94
  #subject_requirements to return an array of those fields.
96
95
  def subject_requirements
97
- return [:undo_stack, :interpreter_behavior,
98
- :chain_of_command, :pause_decks]
96
+ return [:undo_stack, :interpreter, :interpreter_behavior,
97
+ :chain_of_command, :pause_decks, :mode_stack]
99
98
  end
100
99
 
101
100
  def get_subject
@@ -109,9 +108,11 @@ module Command
109
108
  @command_set.add_defaults(subject)
110
109
  subject.required_fields(subject_requirements())
111
110
  subject.undo_stack = @undo_stack
111
+ subject.interpreter = self
112
112
  subject.interpreter_behavior = @behavior
113
113
  subject.chain_of_command = @commands_pending
114
114
  subject.pause_decks = @pause_decks
115
+ subject.mode_stack = @sub_modes
115
116
  return subject
116
117
  end
117
118
 
@@ -2,6 +2,7 @@ require 'readline'
2
2
  require 'command-set'
3
3
  require 'dl/import'
4
4
  require 'command-set/interpreter/base'
5
+ require 'command-set/formatter/strategy'
5
6
 
6
7
  #This really locks text-interpreter down to Linux, maybe Unix-like
7
8
  #platforms, I'm thinking. A more flexible way of doing this would rock,
@@ -394,7 +394,3 @@ module Command
394
394
  end
395
395
  end
396
396
 
397
- #TODO migrate these requires to only where they're needed
398
- require 'command-set/formatter/base'
399
- require 'command-set/formatter/strategy'
400
- require 'command-set/formatter/xml'
@@ -84,7 +84,7 @@ module StdCmd
84
84
  @@set = nil
85
85
  def self.define_commands
86
86
  return @@set ||= Command::CommandSet.define_commands do
87
- command Command::StandardCommand::Quit
87
+ mode_command Command::StandardCommand::Quit
88
88
  end
89
89
  end
90
90
 
@@ -94,7 +94,7 @@ module StdCmd
94
94
  @@set = nil
95
95
  def self.define_commands
96
96
  return @@set ||= Command::CommandSet.define_commands do
97
- command("undo") do
97
+ mode_command("undo") do
98
98
  doesnt_undo
99
99
  action do
100
100
  command=subject.undo_stack.get_undo
@@ -108,7 +108,7 @@ module StdCmd
108
108
  EOH
109
109
  end
110
110
 
111
- command("redo") do
111
+ mode_command("redo") do
112
112
  doesnt_undo
113
113
  action do
114
114
  command=subject.undo_stack.get_redo
@@ -137,7 +137,7 @@ module StdCmd
137
137
  end
138
138
  end
139
139
 
140
- command(:exit) do
140
+ mode_command(:exit) do
141
141
  subject_methods :interpreter
142
142
  doesnt_undo
143
143
 
@@ -66,7 +66,7 @@ module Command
66
66
  end
67
67
 
68
68
  def term_without_hop(terms, node)
69
- raise CommandException, "No such command #{terms.first}"
69
+ raise CommandException, "#{@command_path.join(" ")}: No such command #{terms.first}"
70
70
  end
71
71
  end
72
72
 
@@ -81,7 +81,6 @@ module Command
81
81
  @set_nesting = []
82
82
  end
83
83
 
84
-
85
84
  attr_accessor :arg_hash, :terms, :subject,
86
85
  :task_id, :command_class, :set_nesting
87
86
 
@@ -100,7 +99,7 @@ module Command
100
99
 
101
100
  def term_without_hop(terms, node)
102
101
  if CommandSet === node
103
- raise CommandException, "No such command: #{terms.first}"
102
+ raise CommandException, "#{@command_path.join(" ")}: No such command: #{terms.first}"
104
103
  end
105
104
  end
106
105
 
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: command-set
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.10.0
7
- date: 2008-02-06 00:00:00 -08:00
6
+ version: 0.10.1
7
+ date: 2008-02-12 00:00:00 -08:00
8
8
  summary: Framework for interactive programs focused around a DSL for commands
9
9
  require_paths:
10
10
  - lib
@@ -61,7 +61,7 @@ rdoc_options:
61
61
  - --main
62
62
  - Command
63
63
  - --title
64
- - command-set-0.10.0 RDoc
64
+ - command-set-0.10.1 RDoc
65
65
  extra_rdoc_files:
66
66
  - doc/README
67
67
  - doc/GUIDED_TOUR