class HammerCLI::Bash::Completion

Public Class Methods

load_description(path) click to toggle source
# File lib/hammer_cli/bash/completion.rb, line 22
def self.load_description(path)
  JSON.load(File.open(path))
rescue Errno::ENOENT
  {}
end
new(dict) click to toggle source
# File lib/hammer_cli/bash/completion.rb, line 6
def initialize(dict)
  @dict = dict
end

Public Instance Methods

complete(line) click to toggle source
# File lib/hammer_cli/bash/completion.rb, line 10
def complete(line)
  @complete_line = line.end_with?(' ')
  full_path = line.split(' ')
  complete_path = @complete_line ? full_path : full_path[0..-2]
  dict, path = traverse_tree(@dict, complete_path)

  return [] unless path.empty? # lost during traversing

  partial = @complete_line ? '' : full_path.last
  finish_word(dict, partial)
end

Private Instance Methods

complete_value(value_description, partial, is_param) click to toggle source
# File lib/hammer_cli/bash/completion.rb, line 39
def complete_value(value_description, partial, is_param)
  case value_description['type']
  when 'value'
    if !partial.empty?
      []
    elsif is_param
      ['--->', 'Add parameter']
    else
      ['--->', 'Add option <value>']
    end
  when 'directory'
    directories(partial)
  when 'file'
    files(partial, value_description)
  when 'enum'
    enum(partial, value_description['values'])
  when 'multienum'
    multienum(partial, value_description['values'])
  when 'schema'
    schema(value_description['schema'])
  when 'list'
    ['--->', 'Add comma-separated list of values']
  when 'key_value_list'
    ['--->', 'Add comma-separated list of key=value']
  end
end
directories(partial = '') click to toggle source
# File lib/hammer_cli/bash/completion.rb, line 114
def directories(partial = '')
  dirs = []
  dirs += Dir.glob("#{partial}*").select { |f| File.directory?(f) }
  dirs = dirs.map { |d| d + '/' } if dirs.length == 1
  dirs
end
enum(partial = '', values = []) click to toggle source
# File lib/hammer_cli/bash/completion.rb, line 130
def enum(partial = '', values = [])
  values.select { |v| v.start_with?(partial) }.map { |v| v + ' ' }
end
files(partial = '', opts = {}) click to toggle source
# File lib/hammer_cli/bash/completion.rb, line 121
def files(partial = '', opts = {})
  filter = opts.fetch('filter', '.*')
  file_names = []
  file_names += Dir.glob("#{partial}*").select do |f|
    File.directory?(f) || f =~ /#{filter}/
  end
  file_names.map { |f| File.directory?(f) ? f + '/' : f + ' ' }
end
finish_option_or_subcommand(dict, incomplete) click to toggle source
# File lib/hammer_cli/bash/completion.rb, line 35
def finish_option_or_subcommand(dict, incomplete)
  dict.keys.select { |k| k.is_a?(String) && k =~ /^#{incomplete}/ }.map { |k| k + ' ' }
end
finish_option_value(dict, incomplete) click to toggle source
# File lib/hammer_cli/bash/completion.rb, line 74
def finish_option_value(dict, incomplete)
  complete_value(dict, incomplete, false) if dict.key?('type')
end
finish_param(dict, incomplete) click to toggle source
# File lib/hammer_cli/bash/completion.rb, line 66
def finish_param(dict, incomplete)
  if dict['params'] && !dict['params'].empty?
    complete_value(dict['params'].first, incomplete, true)
  else
    []
  end
end
finish_word(dict, incomplete) click to toggle source
# File lib/hammer_cli/bash/completion.rb, line 30
def finish_word(dict, incomplete)
  finish_option_value(dict, incomplete) ||
    (finish_option_or_subcommand(dict, incomplete) + finish_param(dict, incomplete))
end
multienum(partial = '', values = []) click to toggle source
# File lib/hammer_cli/bash/completion.rb, line 134
def multienum(partial = '', values = [])
  return values if partial.empty?

  parts = partial.split(',')
  resolved = []
  to_complete = parts.each_with_object([]) do |part, res|
    next resolved << part if values.include?(part)

    res << part
  end

  hints = to_complete.map do |p|
    values.select { |v| v.start_with?(p) }
  end.flatten(1).uniq
  return values - parts if hints.empty?
  return [(resolved + hints).join(',')] if hints.size == 1

  hints
end
parse_option(dict, path) click to toggle source
# File lib/hammer_cli/bash/completion.rb, line 104
def parse_option(dict, path)
  if dict[path.first]['type'] == 'flag' # flag
    traverse_tree(dict, path[1..-1])
  elsif path.length >= 2 # option with value
    traverse_tree(dict, path[2..-1])
  else # option with value missing
    [dict[path.first], path[1..-1]]
  end
end
parse_params(dict, path) click to toggle source
# File lib/hammer_cli/bash/completion.rb, line 96
def parse_params(dict, path)
  traverse_tree({ 'params' => dict['params'][1..-1] }, path[1..-1])
end
parse_subcommand(dict, path) click to toggle source
# File lib/hammer_cli/bash/completion.rb, line 100
def parse_subcommand(dict, path)
  traverse_tree(dict[path.first], path[1..-1])
end
schema(template = '') click to toggle source
# File lib/hammer_cli/bash/completion.rb, line 154
def schema(template = '')
  ['--->', "Add value by following schema: #{template}"]
end
traverse_tree(dict, path) click to toggle source
# File lib/hammer_cli/bash/completion.rb, line 78
def traverse_tree(dict, path)
  return [dict, []] if path.nil? || path.empty?
  result = if dict.key?(path.first)
             if path.first.start_with?('-')
               parse_option(dict, path)
             else
               parse_subcommand(dict, path)
             end
           elsif dict['params']
             # traverse params one by one
             parse_params(dict, path)
           else
             # not found
             [{}, path]
           end
  result
end