Class: VopShellBackend

Inherits:
Backend show all
Defined in:
lib/vop/shell/vop_shell_backend.rb

Instance Method Summary collapse

Constructor Details

#initialize(op, options = {}) ⇒ VopShellBackend

Returns a new instance of VopShellBackend.



6
7
8
9
10
11
12
# File 'lib/vop/shell/vop_shell_backend.rb', line 6

def initialize(op, options = {})
  @op = op
  @options = options
  @local_context = {}

  reset_to_command_mode
end

Instance Method Details

#complete(word) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/vop/shell/vop_shell_backend.rb', line 60

def complete(word)
  $logger.debug "completing #{word}"

  command_list = @op.commands.keys

  list = []

  parts = nil

  if @command_selected
    #$logger.debug("asking for lookup values for command '#{@command_selected.name}' and param '#{@current_param[:name]}'")
    list = @command_selected.lookup(@current_param[:name], @collected_values)
  else
    begin
      (parts, command, param_values) = parse_command_string(word)

      if command
        $logger.debug "command selected (#{command.name}), fetching param lookups"

        # all lookup values for a default_param (if exists)
        if command.default_param
          list += command.lookup(command.default_param[:name], @collected_values)
          $logger.debug "added lookups for default param, list now #{list.length} elements"
        end

        # names of all params that have not been specified yet or are :multi
        command.params.each do |param|
          if not param_values.keys.include? param[:name] || param[:multi]
            list << param[:name]
          end
        end

      else
        $logger.debug "no command selected yet, returning command list"
        list = command_list
      end
    rescue => e
      $logger.debug "can't parse >>#{word}<< : #{e.message}"
      $logger.debug e.backtrace
    end
  end

  the_filter = parts ? parts.last : word
  if the_filter
    $logger.debug "filtering completion list against : #{the_filter}"
    list.delete_if do |x|
      x[0...the_filter.size] != the_filter
    end
  end

  prefix = ''
  if parts
    prefix = parts.length > 1 ? parts[0..-2].join(" ").strip : ''
  end
  if $logger.debug?
    more_text = list.length > 1 ? " (and #{list.length-1} more)" : ''
    $logger.debug "completion from >#{word}< to #{prefix} + #{list.first}#{more_text}"
  end
  list.map do |x|
    [prefix, x].join(' ').strip
  end
end

#contextObject



14
15
16
# File 'lib/vop/shell/vop_shell_backend.rb', line 14

def context
  @local_context
end

#execute_commandObject



228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/vop/shell/vop_shell_backend.rb', line 228

def execute_command
  command = @command_selected
  $logger.debug "vop_shell_backend executing command '#{command.short_name}'"

  begin
    extras = {
      'shell' => self
    }
    (response, context) = @op.execute_command(command.short_name, @collected_values, extras)

    if command.short_name == 'exit'
      $logger.info "exiting on user request"
      Kernel.exit(0)
    end

    if context
      if context['prompt']
        set_prompt context['prompt']
      end

      @local_context.merge! context
    end

    format_output(command, response)
  ensure
    reset_to_command_mode
  end
end

#execute_command_if_possibleObject



217
218
219
220
221
222
223
224
225
226
# File 'lib/vop/shell/vop_shell_backend.rb', line 217

def execute_command_if_possible
  mandatory = @command_selected.mandatory_params
  @missing_params = mandatory.select { |p| ! @collected_values.include? p[:name] }

  if @missing_params.size > 0
    @current_param = @missing_params.first
  else
    execute_command
  end
end

#parse_command_string(command_line, presets = {}) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/vop/shell/vop_shell_backend.rb', line 123

def parse_command_string(command_line, presets = {})
  parts = command_line.split.map { |x| x.chomp.strip }
  (command_name, *params) = parts
  command = @op.commands[command_name]

  param_values = Hash.new { |h,k| h[k] = [] }
  presets.each do |k,v|
    param_values[k] = [v]
  end
  if params
    params.each do |param|
      if param =~ /(.+?)=(.+)/ then
        # --> named param
        key = $1
        value = $2
      else
        # --> unnamed param
        value = param
        if command
          default_param = command.default_param
          if default_param != nil then
            key = default_param[:name]
            $logger.debug "collecting value '#{value}' for default param '#{default_param[:name]}'"
          else
            $logger.debug "ignoring param '#{value}' because there's no default param"
          end
        else
          # can't process an unnamed param unless we've got a command
        end
      end

      if key
        param_values[key] << value
      end
    end
  end
  [parts, command, param_values]
end

#process_ctrl_cObject



36
37
38
39
40
41
42
43
# File 'lib/vop/shell/vop_shell_backend.rb', line 36

def process_ctrl_c
  puts "\n"
  if @command_selected
    reset_to_command_mode
  else
    Kernel.exit
  end
end

#process_input(command_line) ⇒ Object



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/vop/shell/vop_shell_backend.rb', line 162

def process_input(command_line)
  $logger.debug "+++ process_input #{command_line} +++"
  if @command_selected
    # we're in parameter processing mode - so check which parameter
    # we've got now and switch modes if necessary

    # we might have been waiting for multiple param values - check if the user finished
    # adding values by entering an empty string as value
    if @current_param && (@current_param[:multi] and command_line == "") then
      @missing_params.shift
      execute_command_if_possible
    else
      # TODO check +command_line+ against lookups/general validity?
      @collected_values[@current_param[:name]] << command_line
      if @current_param[:multi] then
        $logger.debug "param '#{@current_param[:name]}' expects multiple values...deferring mode switching"
      else
        @missing_params.shift
        execute_command_if_possible
      end
    end
  else
    (unused, @command_selected, values) = parse_command_string(command_line, @local_context)

    if @command_selected
      values.each do |key, value_list|
        begin
          value_list.each do |value|
            @current_param = @command_selected.param(key)
            if @current_param
              @collected_values[@current_param[:name]] << value
            else
              # TODO handle extra params?
            end
          end
        rescue Exception => ex
          # TODO broken (error: undefined method `accepts_extra_params' for Vop::Command machines.select_machine:Vop::Command)
          if @command_selected && false && @command_selected.accepts_extra_params
            puts "collecting value for extra param : #{key} => #{value}"
            @collected_values["extra_params"] = {} unless @collected_values.has_key?("extra_params")
            @collected_values["extra_params"][key] = Array.new if @collected_values["extra_params"][key] == nil
            @collected_values["extra_params"][key] << value
          else
            #puts "ignoring parameter value '#{value_list}' for param '#{key}' : " + ex.to_s
            raise ex
          end
        end
      end


      execute_command_if_possible
    end
  end
end

#promptObject



49
50
51
52
53
# File 'lib/vop/shell/vop_shell_backend.rb', line 49

def prompt
  @command_selected && @current_param ?
    "#{@command_selected.short_name}.#{@current_param[:name]} ? " :
    @prompt || '>> '
end

#reset_to_command_modeObject



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/vop/shell/vop_shell_backend.rb', line 18

def reset_to_command_mode
  # this shell has two modes that determine the available tab completion proposals
  # command_mode
  #    we're waiting for the user to pick a command that should be executed
  # parameter mode
  #    the command to execute has already been selected, but the user needs to specify additional parameters
  # we'll start in the mode where no command has been selected yet
  @command_selected = nil

  # if the user selected a command already, we'll have to collect parameters for this command until
  # we've got all mandatory parameters so that we can execute the command
  @collected_values = Hash.new { |h,k| h[k] = [] }

  @missing_params = []

  @current_param = nil
end

#set_prompt(p) ⇒ Object



45
46
47
# File 'lib/vop/shell/vop_shell_backend.rb', line 45

def set_prompt(p)
  @prompt = p
end

#show_bannerObject



55
56
57
58
# File 'lib/vop/shell/vop_shell_backend.rb', line 55

def show_banner
  s = @options[:banner]
  puts s if s
end