zabcon 0.0.6 → 0.0.327

Sign up to get free protection for your applications and to get access to all the features.
data/libs/command_tree.rb CHANGED
@@ -16,133 +16,441 @@
16
16
  #along with this program; if not, write to the Free Software
17
17
  #Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
18
 
19
+ #--
19
20
  ##########################################
20
21
  # Subversion information
21
- # $Id: command_tree.rb 272 2011-01-06 21:04:22Z nelsonab $
22
- # $Revision: 272 $
22
+ # $Id: command_tree.rb 325 2011-09-26 08:57:00Z nelsonab $
23
+ # $Revision: 325 $
23
24
  ##########################################
25
+ #++
24
26
 
25
- require 'libs/zdebug'
27
+ require 'singleton'
28
+ require 'libs/lexer'
29
+ require 'zbxapi/zdebug'
26
30
  require 'libs/zabcon_exceptions'
31
+ require 'libs/zabcon_globals'
32
+ require 'libs/argument_processor'
27
33
 
28
- class Parser
34
+ class ZabconExecuteBase
35
+ include ZDebug
36
+
37
+ attr_reader :results
38
+
39
+ def execute
40
+ raise "Unitialized base method"
41
+ end
42
+
43
+ end
44
+
45
+ class ZabconExecuteCommand < ZabconExecuteBase
46
+
47
+ class NilCommand < Exception
48
+ end
49
+
50
+ #TODO Calling/showing help needs to be streamlined and cleaned up better
51
+ class Help < Exception
52
+ attr_reader :obj
53
+ def initialize(obj)
54
+ @obj=obj
55
+ end
56
+
57
+ def show_help
58
+ @obj.help.call
59
+ end
60
+ end
61
+
62
+ attr_reader :show_params, :options, :help
63
+
64
+ #Configure the command item
65
+ #Also perform the necessary argument processing at this step.
66
+ def initialize(cmd_obj)
67
+ raise "cmd_obj must be fo type CommandList::Cmd" if cmd_obj.class!=CommandList::Cmd
68
+
69
+ @results=nil
70
+ @proc=cmd_obj.command_obj.method(:execute)
71
+ @command_obj=cmd_obj.command_obj
72
+ begin
73
+ arg_result=@command_obj.call_arg_processor(cmd_obj.parameters)
74
+ rescue ParameterError => e
75
+ e.help_func=cmd_obj.command_obj.help_method
76
+ raise e
77
+ end
78
+ @cmd_params=arg_result.cmd_params
79
+ @show_params=arg_result.show_params
80
+ @printing=cmd_obj.command_obj.print?
81
+ @command_name=cmd_obj.command_obj.command_name
82
+ # @help=cmd_obj.help
83
+ # @options=options
84
+
85
+ end
86
+
87
+ def print?
88
+ @printing==true
89
+ end
90
+
91
+ def execute
92
+
93
+ @results=@command_obj.execute(@cmd_params)
94
+
95
+ end
96
+ end
97
+
98
+ class ZabconExecuteVariable < ZabconExecuteBase
99
+ def initialize(var)
100
+ @var=var
101
+ end
102
+
103
+ def assign(val)
104
+ @results=val
105
+ GlobalVars.instance[@var]=val
106
+ end
107
+
108
+ end
109
+
110
+ class ZabconExecuteContainer
29
111
 
30
112
  include ZDebug
31
113
 
32
- attr_reader :commands
114
+ attr_reader :show_params, :results, :options
115
+
116
+ def initialize(usr_str)
117
+ @initial_string=usr_str
118
+ @commands=[]
119
+ @printing=true
120
+ commandlist=CommandList.instance
121
+
122
+ tokens=Tokenizer.new(usr_str)
123
+
124
+ #split_str=usr_str.split2(:split_char=>'=|\s', :include_split=>true)
125
+ #
126
+ #unravel=false #remove any extra space before the first =
127
+ #split_str2=split_str.map {|item|
128
+ # if unravel
129
+ # item
130
+ # elsif item=="="
131
+ # unravel=true
132
+ # item
133
+ # elsif item.empty?
134
+ # nil
135
+ # elsif item.scan(/\s/).empty?
136
+ # item
137
+ # else
138
+ # nil
139
+ # end
140
+ #}.delete_if {|i| i.nil?}
141
+ #
142
+ #if !split_str2[1].nil? && split_str2[1]=='='
143
+ # split_str=split_str2 #use the trimmed version
144
+ # var_name=split_str[0].strip
145
+ # raise ParseError.new("Variable names cannot contain spaces or invalid characters \"#{var_name}\"",:retry=>true) if !var_name.scan(/[^\w]/).empty?
146
+ #
147
+ # debug(5,:var=>var_name,:msg=>"Creating Variable assignment")
148
+ # add(ZabconExecuteVariable.new(var_name))
149
+ #
150
+ # usr_str=split_str[2..split_str.length-1].join.strip
151
+ # debug(5,:var=>usr_str,:msg=>"Continuging to parse with")
152
+ #end
153
+ #
154
+ #debug(6,:var=>split_str,:msg=>"Split Str")
155
+ #debug(6,:var=>split_str2,:msg=>"Split Str2")
156
+ #debug(6,:var=>usr_str,:msg=>"User Str")
157
+ pos=tokens.walk(0)
158
+ if (positions=tokens.assignment?(pos,:return_pos=>true))
159
+ var_name = tokens[positions[0]].value
160
+ debug(5,:var=>var_name,:msg=>"Creating Variable assignment")
161
+ add(ZabconExecuteVariable.new(var_name))
162
+ tokens=tokens.drop(positions[2]+1)
163
+ end
164
+
165
+ cmd_str=tokens.map{|i| i.value}.join
166
+ debug(5,:msg=>"Command String",:var=>cmd_str)
167
+ cmd=commandlist.find_and_parse(cmd_str)
168
+ add(ZabconExecuteCommand.new(cmd))
33
169
 
34
- def initialize(default_argument_processor)
35
- @commands=NewCommandTree.new
36
- @default_argument_processor=default_argument_processor
37
170
  end
38
171
 
39
- def strip_comments(str)
40
- str.lstrip!
41
- str.chomp!
42
- if str =~ /^ ## .*/ then
43
- str = ""
44
- elsif str =~ /(.+) ## .*/ then
45
- str = Regexp.last_match(1)
46
- else
47
- str
172
+ def print?
173
+ @printing==true #Ensure we get a boolean ;-)
174
+ end
175
+
176
+ def add(obj)
177
+ raise "Expected ZabconExecuteCommand Class" if
178
+ obj.class!=ZabconExecuteCommand &&
179
+ obj.class!=ZabconExecuteVariable
180
+ @commands<<obj
181
+ if obj.class==ZabconExecuteCommand
182
+ @printing=@printing & obj.print?
183
+ @show_params=obj.show_params
184
+ @options=obj.options
185
+ end
186
+
187
+ end
188
+
189
+ def execute
190
+ stack=[]
191
+ ptr=0
192
+ while ptr<@commands.length
193
+ case @commands[ptr].class.to_s
194
+ when "ZabconExecuteCommand"
195
+ @commands[ptr].execute
196
+ @results=@commands[ptr].results
197
+ when "ZabconExecuteVariable"
198
+ stack<<ptr
199
+ end
200
+ ptr+=1
201
+ end
202
+
203
+ while !stack.empty?
204
+ ptr=stack.pop
205
+ @commands[ptr].assign(@results)
48
206
  end
49
207
  end
50
208
 
51
- def search(str)
52
- debug(7,str,"Searching")
209
+ end
210
+
211
+
212
+ #Command is the main class used to define commands in Zabcon which are then
213
+ #inserted into the global singleton class CommandList
214
+ class Command
215
+ attr_reader :str, :aliases, :argument_processor, :flags
216
+ attr_reader :required_args, :valid_args
217
+ attr_reader :help_tag, :path
53
218
 
54
- str=strip_comments(str)
219
+ include ArgumentProcessor
220
+
221
+ #Class containing processed arguments to be passed to the command
222
+ class Arguments
223
+ class ParameterError < Exception
224
+ end
55
225
 
226
+ attr_accessor :cmd_params
227
+ attr_reader :show_params
56
228
 
57
- # cmd_node=@commands.search(nodes) # a side effect of the function is that it also manipulates nodes
58
- cmd_node=@commands.get_command(str)
59
- debug(7,cmd_node,"search result")
60
- return cmd_node[:command],cmd_node[:parameters]
229
+ def initialize(args, flags)
230
+ if args.class==String
231
+ @cmd_params=args
232
+ @show_params=nil
233
+ else
234
+ raise "Unknown Argument Object type: #{args.class}" if args.class!=Array && args.class!=Hash
235
+
236
+ @cmd_params=args
237
+ @show_params = {}
238
+ if args.class!=Array && (args["show"] || flags[:default_cols])
239
+ show=args["show"] || flags[:default_cols]
240
+ @show_params={:show=>show}
241
+ @cmd_params.delete("show") if args["show"]
242
+ @cmd_params.merge!({"extendoutput"=>true})
243
+ end
244
+ end
245
+ end
61
246
 
247
+ def show_params=(value)
248
+ raise ParameterError.new("Show argument must be of type Array") if !vaue.is_a?(Array)
249
+ @show_params=value
250
+ end
62
251
  end
63
252
 
253
+ class LoginRequired < Exception
254
+ end
64
255
 
65
- # Returns nil if the command is incomplete or unknown
66
- # If the command is known the associated argument processor is also called and it's results are returned as part
67
- # of the return hash
68
- # the return hash consists of:
69
- # :proc - the name of the procedure which will execute the associated command
70
- # :api_params - parameters to pass to the API call
71
- # :show_params - parameters to pass to the print routines
72
- # :helpproc - help procedure associated with the command
73
- # The argument processor function is passed a string of the arguments after the command, along with the
74
- # array of valid arguments and the help function associated with the command.
75
- # If the argument processor has an error it should call the help function and return nil. In which case this function
76
- # will return nil
77
- def parse(str,user_vars=nil)
78
- debug(7,str,"Parsing")
79
- # options=
80
- debug(7,user_vars,"User Variables")
256
+ class ParameterError < Exception
257
+ end
81
258
 
82
- result=@commands.get_command(str)
259
+ class ArgumentError < Exception
260
+ end
83
261
 
84
- cmd=result[:command]
262
+ class LoopError < Exception
263
+ end
85
264
 
86
- if cmd.nil? or cmd[:commandproc].nil? then
87
- raise ParseError.new("Parse error, incomplete/unknown command: #{str}",:retry=>true)
265
+ def initialize(path)
266
+ raise "Path must be an array" if path.class!=Array
267
+ @path=path
268
+ @cmd_method=nil
269
+ @valid_args=[]
270
+ @aliases=[]
271
+ @flags={}
272
+ @result_type=nil
273
+
274
+ #TODO Can the argument processor stuff be cleaned up?
275
+ @argument_processor=method(:default_processor)
276
+ @help_tag=nil
277
+ @depreciated=nil
278
+ end
279
+
280
+ def command_name
281
+ @path.join(" ")
282
+ end
283
+
284
+ def print?
285
+ if @flags.nil?
286
+ false
88
287
  else
89
- # The call here to the argument process requires one argument as it's a lambda block which is setup when the
90
- # command node is created
91
- debug(6,result[:parameters],"calling argument processor")
92
- args=cmd[:argument_processor].call(result[:parameters],user_vars)
93
- debug(6,args,"received from argument processor")
94
- retval = args.nil? ? nil : {:proc=>cmd[:commandproc], :helpproc=>cmd[:helpproc], :options=>cmd[:options]}.merge(args)
95
- return retval
288
+ @flags[:print_output]==true
96
289
  end
97
290
  end
98
291
 
99
- def complete(str,loggedin=false)
100
- nodes = str.split
101
- cmd_node=@commands
102
- i=0
103
- while i<nodes.length
104
- tmp=cmd_node.search(nodes[i])
105
- break if tmp.nil?
106
- cmd_node=tmp
107
- i+=1
292
+ def set_method(&cmd_method)
293
+ @cmd_method=cmd_method
294
+ end
295
+
296
+ #Adds an alias name for the current command
297
+ def add_alias(name)
298
+ @aliases<<name.split2
299
+ end
300
+
301
+ #How many alias' are there?
302
+ def alias_total
303
+ @aliases.length
304
+ end
305
+
306
+ def generate_alias(index)
307
+ raise "Index out of bounds 0 >= i < N, i=#{index} N=#{alias_total}" if index<0 || index>=alias_total
308
+ new_alias=self.dup
309
+ new_alias.instance_variable_set("@path",@aliases[index])
310
+ new_alias.instance_variable_set("@aliases",[])
311
+ new_alias
312
+ end
313
+
314
+ #accepts an array of valid arguments
315
+ def set_valid_args(args)
316
+ @valid_args=args
317
+ end
318
+
319
+ def default_show(cols)
320
+ raise "Cols must be an array" if cols.class!=Array
321
+ @flags[:default_cols]=cols
322
+ end
323
+
324
+ def depreciated(str)
325
+ @depreciated=str
326
+ end
327
+
328
+ def arg_processor(&block)
329
+ @argument_processor=block
330
+ end
331
+
332
+ def set_arg_processor(method)
333
+ @argument_processor=method
334
+ end
335
+
336
+ def set_help_tag(sym)
337
+ @help_tag=sym
338
+ end
339
+
340
+ #--
341
+ #TODO Complete type casting section and add error checking
342
+ #++
343
+ #Valid flags:
344
+ # :login_required - command requires a valid login
345
+ # :print_output - the output of the command will be passed to the print processor
346
+ # :array_params - Only process the parameters as an array
347
+ def set_flag(flag)
348
+ case flag.class.to_s
349
+ when "Symbol"
350
+ flag={flag=>true}
108
351
  end
109
352
 
110
- if cmd_node.commandproc.nil? then
111
- # roll up the list of available commands.
112
- commands = cmd_node.children.collect {|node| node.command}
353
+ @flags.merge!(flag)
354
+ end
355
+
356
+ def call_arg_processor(parameters)
357
+ def set_show_args(args)
358
+ @arguments.show_params=args
359
+ end
113
360
 
114
- # don't include the current node if the command is empty
115
- if cmd_node.command!="" then commands += [cmd_node.command] end
116
- return commands
361
+ @arguments=Arguments.new("",@flags)
362
+ result=@argument_processor.call(parameters,@valid_args,@flags)
363
+ return result if result.is_a?(Arguments)
364
+ if !result.is_a?(String) && !result.is_a?(Hash) && !result.is_a?(Array)
365
+ raise ("Arugment processor for \"#{command_name}\" returned invalid parameters: class: #{result.class}, #{result}")
117
366
  else
118
- puts "complete"
119
- return nil
367
+ @arguments.cmd_params=result
368
+ arguments=@arguments
369
+ return arguments
120
370
  end
121
371
  end
122
372
 
123
- def insert(insert_path,commandproc,arguments=[],helpproc=nil,argument_processor=nil,*options)
124
- debug(10,{"insert_path"=>insert_path, "commandproc"=>commandproc, "arguments"=> arguments, "helpproc"=>helpproc, "argument_processor"=>argument_processor, "options"=>options})
125
- # insert_path_arr=[""]+insert_path.split # we must pre-load our array with a blank node at the front
126
- # p insert_path_arr
373
+ #Sets the symbold describing the result type. May be used by the print processor
374
+ # as a hint for printing the output.
375
+ def result_type(type)
376
+ @result_type=type
377
+ end
378
+
379
+ def execute(parameters)
380
+ def set_result_message(msg)
381
+ @response.message=msg
382
+ end
383
+
384
+ def set_result_type(type)
385
+ @response.type=type
386
+ end
387
+
388
+ # def output(params)
389
+ # @response.data<<params
390
+ # end
391
+
392
+ raise LoopError.new("Loop detected, Command.execute called more than 3 times") if caller.grep(caller[0]).length>3
393
+ @response=Response.new
394
+ @response.type=@result_type if !@result_type.nil?
395
+
396
+ puts @depreciated if !@depreciated.nil?
397
+ if !@flags.nil? && @flags[:login_required] && !server.connected?
398
+ raise LoginRequired.new("\"#{@command_name}\" requires an active login")
399
+ end
400
+
401
+ @response.data=@cmd_method.call(parameters)
402
+
403
+ retval=@response #ensure @result is empty for our next use
404
+ @response=nil
127
405
 
128
- # If the parameter "argument_processor" is nil use the default argument processor
129
- arg_processor = argument_processor.nil? ? @default_argument_processor : argument_processor
130
- @commands.insert(insert_path,commandproc,arguments,helpproc,arg_processor,options)
406
+ retval
131
407
  end
132
408
 
133
- end
409
+ private
134
410
 
135
- #{"add"=>{:node=>proc, "host"=>{:node=>proc,"group"=>{:node=>proc}}},"delete"=>...}
411
+ def parameter_error(msg)
412
+ raise ParameterError.new(msg)
413
+ end
136
414
 
137
- class NewCommandTree
415
+ def server
416
+ ZabbixServer.instance
417
+ end
418
+
419
+ def global_vars
420
+ GlobalVars.instance
421
+ end
422
+ end
423
+
424
+ class CommandList
138
425
  include ZDebug
426
+ include Singleton
427
+
428
+ class InvalidCommand < Exception
429
+ def initialize(str)
430
+ @str=str
431
+ end
432
+
433
+ def message
434
+ "Unknown or Invalid Command: #{@str}"
435
+ end
436
+ end
437
+
438
+ class Cmd
439
+ attr_reader :command_obj, :parameters
440
+
441
+ def initialize(command_obj,parameters)
442
+ @command_obj=command_obj
443
+ @parameters=parameters
444
+ end
445
+ end #End Cmd sub class
139
446
 
140
447
  def initialize
141
- @tree = {}
448
+ @cmd_tree={}
142
449
  end
143
450
 
144
- def insert(insert_path,commandproc,arguments,helpproc,argument_processor,options)
145
- tree_node=@tree
451
+ def insert(insert_path, cmd_obj)
452
+ raise "Insert_path must be an array" if insert_path.class!=Array
453
+ tree_node=@cmd_tree
146
454
  path_length=insert_path.length-1
147
455
  insert_path.each_index do |index|
148
456
  if tree_node[insert_path[index]].nil?
@@ -150,241 +458,133 @@ class NewCommandTree
150
458
  tree_node[insert_path[index]]={}
151
459
  tree_node=tree_node[insert_path[index]]
152
460
  else
153
- local_arg_processor=lambda do |params,user_vars|
154
- if argument_processor.nil?
155
- nil
156
- else
157
- argument_processor.call(helpproc,arguments,params,user_vars,options) # We pass the list of valid arguments to
158
- end
159
- end
160
- if options.nil?
161
- local_options=nil
162
- else
163
- local_options = Hash[*options.collect { |v|
164
- [v, true]
165
- }.flatten]
166
- end
167
- tree_node[insert_path[index]]={:node=>
168
- {:commandproc=>commandproc, :arguments=>arguments, :helpproc=>helpproc,
169
- :argument_processor=>local_arg_processor,:options=>local_options}}
461
+ tree_node[insert_path[index]]={:node=>cmd_obj}
170
462
  end
171
463
  else
172
464
  tree_node=tree_node[insert_path[index]]
173
465
  end
174
466
  end
467
+
468
+ (0..(cmd_obj.alias_total-1)).each {|i|
469
+ insert(cmd_obj.aliases[i],cmd_obj.generate_alias(i))} if cmd_obj.alias_total>0
175
470
  end
176
471
 
177
- #get_command(String)
178
- #returns a Hash with two items: :command and :parameters
179
- #:command is a hash denoting all of the components of a the command when it was inserted
180
- #:parameters is the remainder of the String passed in.
181
- #
182
- #example:
183
- # get_command("get host show=all")
184
- # {:command=>{hash created from insert}, :parameters=>"show=all"}
185
- #
186
- # get_command("get host test test2")
187
- # {:command=>{hash created from insert}, :parameters=>"test test2"
188
- def get_command(str)
189
- str_array=str.downcase.split #ensure all comparisons are done in lower case
190
- str_items=str_array.length
191
-
192
- cur_node=@tree
472
+ def get(path)
473
+ path=setup_path(path)
474
+
475
+ cur_node=@cmd_tree
193
476
  count=0
194
477
 
195
- str_array.collect do |item|
478
+ path.collect do |item|
196
479
  break if cur_node[item].nil?
197
480
  count+=1
198
481
 
199
482
  cur_node=cur_node[item]
200
483
  end
201
484
 
202
- cmd= cur_node.nil? ? nil : cur_node[:node]
203
-
204
- #remove preceding items found so we can return the remainder
205
- #as the parameters
206
- count.times do |i|
207
- str=str.gsub(/^#{str_array[i]}/,"")
208
- str=str.gsub(/^\s*/,"")
209
- end
210
-
211
- {:command=>cmd,:parameters=>str}
485
+ cmd=cur_node.nil? ? nil : cur_node[:node]
212
486
  end
213
487
 
214
- end
215
- def search(search_path)
216
- debug(10,search_path,"search_path")
217
- return retval if results.empty? # no more children to search, return retval which may be self or nil, see logic above
218
- debug(10)
488
+ def find_and_parse(str)
219
489
 
220
- return results[0].search(search_path)
221
- debug(10,"Not digging deeper")
490
+ tokens=Tokenizer.new(str)
491
+ token_items=tokens.length
222
492
 
223
- return self if search_path[0]==@command
493
+ cur_node=@cmd_tree
494
+ pos=tokens.walk(0)
224
495
 
225
- end
226
-
227
- def insert(insert_path,command,commandproc,arguments,helpproc,argument_processor,options)
228
- do_insert(insert_path,command,commandproc,arguments,helpproc,argument_processor,options,0)
229
- end
230
-
231
- # Insert path is the path to insert the item into the tree
232
- # Insert path is passed in as an array of names which associate with pre-existing nodes
233
- # The function will recursively insert the command and will remove the top of the input path stack at each level until it
234
- # finds the appropraite level. If the appropriate level is never found an exception is raised.
235
- def do_insert(insert_path,command,commandproc,arguments,helpproc,argument_processor,options,depth)
236
- debug(11,{"insert_path"=>insert_path, "command"=>command, "commandproc"=>commandproc, "arguments"=> arguments,
237
- "helpproc"=>helpproc, "verify_func"=>argument_processor, "depth"=>depth})
238
- debug(11,@command,"self.command")
239
- # debug(11,@children.map {|child| child.command},"children")
240
-
241
- if insert_path[0]==@command then
242
- debug(11,"Found node")
243
- if insert_path.length==1 then
244
- debug(11,command,"inserting")
245
- @children << CommandTree.new(command,commandproc,depth+1,arguments,helpproc,argument_processor,options)
246
- else
247
- debug(11,"Not found walking tree")
248
- insert_path.shift
249
- if !@children.empty? then
250
- @children.each { |node| node.do_insert(insert_path,command,commandproc,arguments,helpproc,argument_processor,options,depth+1)}
251
- else
252
- raise(Command_Tree_Exception,"Unable to find insert point in Command Tree")
253
- end
254
- end
255
- end
256
- end
257
-
258
- =begin
259
- class CommandTree
260
-
261
- include ZDebug
262
-
263
- attr_reader :command, :commandproc, :children, :arguments, :helpproc, :depth, :argument_processor, :options
264
-
265
- # Arguments hash takes the form of {"name"=>{:type=>Class, :optional=>true/false}}
266
- # If type is nil then the argument takes no options
267
- def initialize(command,commandproc,depth,arguments,helpproc,argument_processor,options)
268
- debug(10,{"command"=>command, "commandproc"=>commandproc, "arguments"=> arguments,"helpproc"=>helpproc,
269
- "verify_func"=>argument_processor, "depth"=>depth, "options"=>options})
270
- @command=command
271
- @commandproc=commandproc
272
- @children=[]
273
- @arguments=arguments
274
- @helpproc=helpproc
275
- @depth=depth
276
- # verify functions are special.
277
- # We pass them the list of valid arguments first and then the parameters which need to be verified
278
- # This will allow for either unique or generalized verification functions
279
- # The verify function can safely be called with objects with no verify function as nil checking is performed in the
280
- # lambda
281
- # If no verify function was setup we return true
282
- @argument_processor=lambda do |params,user_vars|
283
- if argument_processor.nil?
284
- nil
285
- else
286
- argument_processor.call(@helpproc,@arguments,params,user_vars,options) # We pass the list of valid arguments to
287
- end
288
- end
289
- if options.nil?
290
- @options=nil
291
- else
292
- @options = Hash[*options.collect { |v|
293
- [v, true]
294
- }.flatten]
496
+ while !tokens.end?(pos)
497
+ item=tokens[pos].value
498
+ break if cur_node[item].nil?
499
+ cur_node=cur_node[item]
500
+ pos=tokens.walk(pos+1)
295
501
  end
296
- debug(10,self.inspect,"Initialization complete")
297
- end
298
502
 
299
- def inspect
300
- r_str ="#<#{self.class.to_s}:0x#{self.object_id.to_s(16)} @command=#{@command.inspect}, @commandproc=#{@commandproc.inspect}, "
301
- r_str+="@helpproc=#{@helpproc.inspect}, @argument_processor=#{@argument_processor.inspect}, @arguments=#{@arguments.inspect}, "
302
- r_str+="@options=#{@options.inspect}, "
303
- r_str+="@depth=#{@depth}, @children="
304
- if @children.empty?
305
- r_str+= "[]"
306
- else
307
- children=@children.map {|child| child.command }
308
- r_str+= children.inspect
309
- end
310
- r_str+=">"
311
- r_str
312
- end
503
+ #tokens.each do |item|
504
+ # if item.empty? || !item.scan(/^\s*$/).empty?
505
+ # count+=1
506
+ # else
507
+ # break if cur_node[item].nil?
508
+ # count+=1
509
+ # cur_node=cur_node[item]
510
+ # end
511
+ #end
313
512
 
314
- # search will search check to see if the parameter command is found in the current node
315
- # or the immediate children nodes. It does not search the tree beyond one level.
316
- # The loggedin argument is used to differentiate searching for commands which require a valid
317
- # login or not. If loggedin is false it will return commands which do not require a valid login.
318
- debug(10,self,"self",300)
513
+ raise InvalidCommand.new(str) if cur_node.nil? || !cur_node[:node]
319
514
 
320
- return nil if search_path.nil?
321
- return nil if search_path.empty?
515
+ cmd=cur_node[:node]
516
+ #params=str_array[count..str_array.length].join.strip
322
517
 
323
- retval=nil
518
+ debug(6,:msg=>"Tokens", :var=>tokens)
519
+ debug(6,:msg=>"Pos", :var=>pos)
520
+ debug(6,:msg=>"Parsed", :var=>tokens.parse)
521
+ params = tokens.drop(pos+1).join
324
522
 
325
- retval=self if search_path[0]==@command
523
+ debug(6,:msg=>"Parameters", :var=>params)
326
524
 
525
+ Cmd.new(cmd,params)
526
+ end
327
527
 
328
- search_path.shift
329
- debug(10,search_path, "shifted search path")
528
+ def get_command_list(tree=nil)
529
+ def get_subtree(tree)
530
+ tmp=tree.dup
531
+ path=nil
532
+ if !tmp[:node].nil?
533
+ path=tree[:node].path.join(" ")
534
+ tmp.delete(:node)
535
+ end
536
+ tree=tmp
330
537
 
331
- return retval if search_path.length==0
538
+ if tree.empty?
539
+ return path if !path.nil?
540
+ return nil
541
+ end
542
+ results=tree.keys.sort.map {|key|
543
+ get_subtree(tree[key])
544
+ }
545
+ [path,results]
546
+ end
332
547
 
333
- # p search_path
334
- # p @children.map {|child| child.command}
335
- debug(10,@children.map{|child| child.command},"Current children")
548
+ get_subtree(@cmd_tree).flatten.compact.sort
549
+ end
336
550
 
337
- results=@children.map {|child| child.command==search_path[0] ? child : nil }
338
- results.compact!
339
- debug(10,results,"Children search results",200)
551
+ private
340
552
 
553
+ def setup_path(path)
554
+ if path.class==Array
555
+ path
556
+ elsif path.class==String
557
+ path.split2
558
+ else
559
+ raise "Path must be Array or string"
560
+ end
561
+ end
341
562
  end
342
- =end
343
-
344
-
345
- if __FILE__ == $0
346
-
347
- require 'pp'
348
- require 'argument_processor'
349
563
 
350
- arg_processor=ArgumentProcessor.new()
351
- commands=Parser.new(arg_processoor.method(:default))
352
- commands.set_debug_level(6)
353
-
354
-
355
- def test_parse(cmd)
356
- puts "\ntesting \"#{cmd}\""
357
- retval=commands.parse(cmd)
358
- puts "result:"
359
- return retval
564
+ #Base module for instantiating Zabcon commands.
565
+ module ZabconCommand
566
+ #Method used to add commands to the Zabcon command processor
567
+ #path is the command path such as "get host group"
568
+ #A block must also be passed, this block will be executed against the
569
+ # Command object to to define the command and then inserted into the
570
+ # global CommandList singleton.
571
+ def self.add_command (path, &block)
572
+ path=
573
+ if path.class==Array
574
+ path
575
+ elsif path.class==String
576
+ path.split2(:trim_empty=>true)
577
+ else
578
+ raise "Path must be Array or string"
579
+ end
580
+ cmd=Command.new(path)
581
+ cmd.instance_eval(&block)
582
+ raise "Help tag required for \"#{path.join(" ")}\", and must be of type symbol. Use the symbol :none for no help" if cmd.help_tag.class!=Symbol
583
+ CommandList.instance.insert(path,cmd)
360
584
  end
361
- commands.set_debug_level(0)
362
- commands.insert "", "help", lambda { puts "This is a generic help stub" }
363
- puts
364
- commands.insert "", "get", nil
365
- puts
366
- commands.insert "get", "host", :gethost, {"show"=>{:type=>nil,:optional=>true}}
367
- commands.set_debug_level(0)
368
- puts
369
- commands.insert "get", "user", :getuser
370
- puts
371
- commands.insert "get user", "group", :getusergroup
372
- puts
373
-
374
- pp commands
375
-
376
- commands.set_debug_level(0)
377
-
378
- test_parse("get user")
379
- test_parse("get user show=all arg1 arg2")
380
- test_parse("get user show=\"id, one, two, three\" arg1 arg2")
381
- test_parse("get user group show=all arg1")
382
- test_parse("set value")
383
- test_parse("help")[:proc].call
384
585
 
586
+ end
385
587
 
386
- p commands.complete("hel")
387
- p commands.complete("help")
388
- p commands.complete("get user all")
588
+ if __FILE__ == $0
389
589
 
390
590
  end