command-set 0.10.0 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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