class Conjur::CLI::Complete
Class for generating ‘conjur` bash completions
Attributes
arg_words[R]
command_words[R]
commands[R]
current_word_index[R]
flag_words[R]
line[R]
switch_words[R]
words[R]
Public Class Methods
new(line, point=nil)
click to toggle source
# File lib/conjur/complete.rb, line 31 def initialize line, point=nil @line = line @words = tokenize_cmd @line point ||= @line.length @current_word_index=(tokenize_cmd @line.slice(0,point)).length-1 # fix arrays for empty "current word" # ie "conjur group list " if @line.match(/[ =]$/) @words << '' @current_word_index += 1 end @commands, @switch_words, @flag_words, @arg_words = parse_command @words, @current_word_index @command_words = @commands .drop(1) .map(&:name) .map(&:to_s) .unshift('conjur') end
Public Instance Methods
classify_word(word, command)
click to toggle source
# File lib/conjur/complete.rb, line 116 def classify_word word, command if word.start_with? '-' sym = flag_to_sym word if switches(command).member? sym :switch else :flag end else if subcommands(command).has_key? word.to_sym :subcommand else :argument end end end
complete(kind)
click to toggle source
# File lib/conjur/complete.rb, line 133 def complete kind kind = kind.to_s.downcase.gsub(/[^a-z]/, '') case kind when 'resource' complete_resource when 'role' complete_role when 'file' complete_file current_word when 'hostname' complete_hostname else complete_resource kind if [ 'group', 'user', 'variable', 'host', 'layer', ].member? kind end or [] end
complete_args(cmd, prev, num_args)
click to toggle source
# File lib/conjur/complete.rb, line 176 def complete_args cmd, prev, num_args kind=nil if prev.start_with? '-' flag_name=flag_to_sym prev flag = cmd.flags[flag_name] desc = flag.argument_name if defined? flag.argument_name kind = desc.to_s.downcase else desc = cmd.arguments_description if defined? cmd.arguments_description kind = desc.to_s.downcase.split[num_args-1] end complete kind end
complete_file(word)
click to toggle source
# File lib/conjur/complete.rb, line 209 def complete_file word # use Bash's file completion for compatibility `bash -c "compgen -f #{word}"`.shellsplit end
complete_flags(cmd)
click to toggle source
generate completions for the switches and flags of a Conjur::CLI::Command
@param cmd [Conjur::CLI::Command] command for which to search for flags
and switches
@return [Array] completion words
# File lib/conjur/complete.rb, line 160 def complete_flags cmd cmd.flags.values.map do |flag| candidates = [flag.name] candidates += flag.aliases if flag.aliases candidates.map do |c| "-#{'-' if c.length > 1}#{c}#{'=' if c.length > 1}" end end + cmd.switches.values.map do |switch| candidates = [switch.name] candidates += switch.aliases if switch.aliases candidates.map do |c| "-#{'-' if c.length > 1}#{c}" end end end
complete_hostname()
click to toggle source
# File lib/conjur/complete.rb, line 214 def complete_hostname `bash -c "compgen -A hostname"`.shellsplit end
complete_resource(resource_kind=nil)
click to toggle source
# File lib/conjur/complete.rb, line 190 def complete_resource resource_kind=nil Conjur::Command.api.resources({kind: resource_kind}) .map do |r| res = Resource.new r.attributes['id'] if resource_kind res.name else res.to_s end end end
complete_role()
click to toggle source
# File lib/conjur/complete.rb, line 202 def complete_role Conjur::Command.api.current_role(Conjur.configuration.account).memberships .map { |r| Resource.new(r.id) } .reject { |r| r.kind.start_with? '@' } .map(&:to_s) end
completions()
click to toggle source
# File lib/conjur/complete.rb, line 218 def completions prev = current_word(-1) if current_word.start_with? '-' complete_flags @commands.last else (subcommands @commands.last).keys.map(&:to_s) + (complete_args @commands.last, prev, @arg_words.length) end.flatten .select do |candidate| candidate.start_with? current_word.sub('\:',':') end .map do |candidate| # if the current word is colon separated, strip its complete tokens # eg. for --as-role=user:ryanprior, we're actually only completing 'ryanprior' # because bash treats 'user' as a separate word non_escaped_colon_regex = /(?<!\\):/ num_tokens = current_word.split(non_escaped_colon_regex).length if num_tokens > 1 candidate = candidate .split(non_escaped_colon_regex) .drop(num_tokens-1) .join(':') end "#{candidate}#{' ' if not candidate.end_with? '='}" end end
current_word(offset=0)
click to toggle source
# File lib/conjur/complete.rb, line 53 def current_word offset=0 @words[@current_word_index + offset] end
flag_to_sym(flag)
click to toggle source
# File lib/conjur/complete.rb, line 86 def flag_to_sym flag flag.match(/--?([^=]+)=?/)[1].to_sym end
parse_command(words, current_word_index)
click to toggle source
# File lib/conjur/complete.rb, line 90 def parse_command words, current_word_index command = Conjur::CLI commands = [command] switches = [] flags = [] arguments = [] index = 1 until index >= current_word_index do word = words[index] case classify_word word, command when :switch switches.push word when :flag flags.push [word, words[index+1]] index += 1 when :subcommand command = command.commands[word.to_sym] commands.push command when :argument arguments.push word end index += 1 end return commands, switches, flags, arguments end
subcommands(cmd)
click to toggle source
Generate array of subcommands for which documentation is not hidden
@param cmd [Conjur::CLI::Command] the command to search @return [Array] the subcommands
# File lib/conjur/complete.rb, line 61 def subcommands cmd cmd.commands.select do |_, c| c.nodoc.nil? end end
switches(cmd)
click to toggle source
Generate array of symbols representing switches for cmd
and their aliases
@param cmd [Conjur::CLI::Command] the command to search @return [Array] the symbols representing switches and their aliases
# File lib/conjur/complete.rb, line 72 def switches cmd cmd.switches.map { |_,switch| [switch.name] + (switch.aliases or []) }.flatten end
tokenize_cmd(line)
click to toggle source
Split line according on spaces and after ‘=’
@param line [String] to split @return [Array] the substrings
# File lib/conjur/complete.rb, line 82 def tokenize_cmd line line.split(/ |(?<==)/) end