Class: Conjur::CLI::Complete
- Inherits:
-
Object
- Object
- Conjur::CLI::Complete
- Defined in:
- lib/conjur/complete.rb
Overview
Class for generating ‘conjur` bash completions
Defined Under Namespace
Classes: Resource
Instance Attribute Summary collapse
-
#arg_words ⇒ Object
readonly
Returns the value of attribute arg_words.
-
#command_words ⇒ Object
readonly
Returns the value of attribute command_words.
-
#commands ⇒ Object
readonly
Returns the value of attribute commands.
-
#current_word_index ⇒ Object
readonly
Returns the value of attribute current_word_index.
-
#flag_words ⇒ Object
readonly
Returns the value of attribute flag_words.
-
#line ⇒ Object
readonly
Returns the value of attribute line.
-
#switch_words ⇒ Object
readonly
Returns the value of attribute switch_words.
-
#words ⇒ Object
readonly
Returns the value of attribute words.
Instance Method Summary collapse
- #classify_word(word, command) ⇒ Object
- #complete(kind) ⇒ Object
- #complete_args(cmd, prev, num_args) ⇒ Object
- #complete_file(word) ⇒ Object
-
#complete_flags(cmd) ⇒ Array
generate completions for the switches and flags of a Conjur::CLI::Command.
- #complete_hostname ⇒ Object
- #complete_resource(resource_kind = nil) ⇒ Object
- #complete_role ⇒ Object
- #completions ⇒ Object
- #current_word(offset = 0) ⇒ Object
- #flag_to_sym(flag) ⇒ Object
-
#initialize(line, point = nil) ⇒ Complete
constructor
A new instance of Complete.
- #parse_command(words, current_word_index) ⇒ Object
-
#subcommands(cmd) ⇒ Array
Generate array of subcommands for which documentation is not hidden.
-
#switches(cmd) ⇒ Array
Generate array of symbols representing switches for
cmd
and their aliases. -
#tokenize_cmd(line) ⇒ Array
Split line according on spaces and after ‘=’.
Constructor Details
#initialize(line, point = nil) ⇒ Complete
Returns a new instance of Complete.
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# 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 |
Instance Attribute Details
#arg_words ⇒ Object (readonly)
Returns the value of attribute arg_words.
29 30 31 |
# File 'lib/conjur/complete.rb', line 29 def arg_words @arg_words end |
#command_words ⇒ Object (readonly)
Returns the value of attribute command_words.
29 30 31 |
# File 'lib/conjur/complete.rb', line 29 def command_words @command_words end |
#commands ⇒ Object (readonly)
Returns the value of attribute commands.
29 30 31 |
# File 'lib/conjur/complete.rb', line 29 def commands @commands end |
#current_word_index ⇒ Object (readonly)
Returns the value of attribute current_word_index.
29 30 31 |
# File 'lib/conjur/complete.rb', line 29 def current_word_index @current_word_index end |
#flag_words ⇒ Object (readonly)
Returns the value of attribute flag_words.
29 30 31 |
# File 'lib/conjur/complete.rb', line 29 def flag_words @flag_words end |
#line ⇒ Object (readonly)
Returns the value of attribute line.
29 30 31 |
# File 'lib/conjur/complete.rb', line 29 def line @line end |
#switch_words ⇒ Object (readonly)
Returns the value of attribute switch_words.
29 30 31 |
# File 'lib/conjur/complete.rb', line 29 def switch_words @switch_words end |
#words ⇒ Object (readonly)
Returns the value of attribute words.
29 30 31 |
# File 'lib/conjur/complete.rb', line 29 def words @words end |
Instance Method Details
#classify_word(word, command) ⇒ Object
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# 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) ⇒ Object
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# 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) ⇒ Object
176 177 178 179 180 181 182 183 184 185 186 187 188 |
# 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) ⇒ Object
209 210 211 212 |
# 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) ⇒ Array
generate completions for the switches and flags of a Conjur::CLI::Command
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# 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 ⇒ Object
214 215 216 |
# File 'lib/conjur/complete.rb', line 214 def complete_hostname `bash -c "compgen -A hostname"`.shellsplit end |
#complete_resource(resource_kind = nil) ⇒ Object
190 191 192 193 194 195 196 197 198 199 200 |
# 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 ⇒ Object
202 203 204 205 206 207 |
# File 'lib/conjur/complete.rb', line 202 def complete_role Conjur::Command.api.current_role.all .map { |r| Resource.new(r.roleid) } .reject { |r| r.kind.start_with? '@' } .map(&:to_s) end |
#completions ⇒ Object
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
# 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) ⇒ Object
53 54 55 |
# File 'lib/conjur/complete.rb', line 53 def current_word offset=0 @words[@current_word_index + offset] end |
#flag_to_sym(flag) ⇒ Object
86 87 88 |
# File 'lib/conjur/complete.rb', line 86 def flag_to_sym flag flag.match(/--?([^=]+)=?/)[1].to_sym end |
#parse_command(words, current_word_index) ⇒ Object
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 |
# 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) ⇒ Array
Generate array of subcommands for which documentation is not hidden
61 62 63 64 65 |
# File 'lib/conjur/complete.rb', line 61 def subcommands cmd cmd.commands.select do |_, c| c.nodoc.nil? end end |
#switches(cmd) ⇒ Array
Generate array of symbols representing switches for cmd
and their aliases
72 73 74 75 76 |
# File 'lib/conjur/complete.rb', line 72 def switches cmd cmd.switches.map { |_,switch| [switch.name] + (switch.aliases or []) }.flatten end |
#tokenize_cmd(line) ⇒ Array
Split line according on spaces and after ‘=’
82 83 84 |
# File 'lib/conjur/complete.rb', line 82 def tokenize_cmd line line.split(/ |(?<==)/) end |