class SimpleScripting::TabCompletion::CommandlineProcessor
Constants
- BASE_CURSOR_MARKER
Arbitrary; can be anything (except an empty string).
- LONG_OPTIONS_PREFIX
- OPTIONS_TERMINATOR
Public Class Methods
process_commandline(source_commandline, cursor_position, switches_definition)
click to toggle source
# File lib/simple_scripting/tab_completion/commandline_processor.rb, line 19 def self.process_commandline(source_commandline, cursor_position, switches_definition) # An input string with infinite "<tabN>" substrings will cause an infinite cycle (hehe). 0.upto(Float::INFINITY) do |i| cursor_marker = BASE_CURSOR_MARKER.sub(">", "#{i}>") if !source_commandline.include?(cursor_marker) commandline_with_marker = source_commandline[0...cursor_position] + cursor_marker + source_commandline[cursor_position..-1].to_s # Remove the executable. processed_argv = Shellwords.split(commandline_with_marker)[1..-1] return new(processed_argv, cursor_marker, switches_definition) end end end
Public Instance Methods
completing_an_option?()
click to toggle source
We're abstracted from the commandline, with this exception. This is because while an option is being completed, the decoder would not recognize the key.
# File lib/simple_scripting/tab_completion/commandline_processor.rb, line 38 def completing_an_option? processed_argv[marked_word_position].start_with?(LONG_OPTIONS_PREFIX) && marked_word_position < options_terminator_position end
completing_word_prefix()
click to toggle source
# File lib/simple_scripting/tab_completion/commandline_processor.rb, line 46 def completing_word_prefix word = processed_argv[marked_word_position] # Regex alternative: [/\A(.*?)#{cursor_marker}/m, 1] word[0, word.index(cursor_marker)] end
parsed_pairs()
click to toggle source
Returns key, value prefix (before marker), value suffix (after marker), other_pairs
# File lib/simple_scripting/tab_completion/commandline_processor.rb, line 55 def parsed_pairs parsed_pairs = parse_argv || raise("Parsing error") key, value = parsed_pairs.detect do |_, value| !boolean?(value) && value.include?(cursor_marker) end # Impossible case, unless there is a programmatic error. # key || raise("Guru meditation! (#{self.class}##{__method__}:#{__LINE__})") value_prefix, value_suffix = value.split(cursor_marker) parsed_pairs.delete(key) [key, value_prefix || "", value_suffix || "", parsed_pairs] end
parsing_error?()
click to toggle source
# File lib/simple_scripting/tab_completion/commandline_processor.rb, line 42 def parsing_error? parse_argv.nil? end
Private Instance Methods
boolean?(value)
click to toggle source
For the lulz.
# File lib/simple_scripting/tab_completion/commandline_processor.rb, line 110 def boolean?(value) !!value == value end
marked_word_position()
click to toggle source
# File lib/simple_scripting/tab_completion/commandline_processor.rb, line 75 def marked_word_position processed_argv.index { |word| word.include?(cursor_marker) } end
options_terminator_position()
click to toggle source
Returns Float::INFINITY when there is no options terminator.
# File lib/simple_scripting/tab_completion/commandline_processor.rb, line 81 def options_terminator_position processed_argv.index(OPTIONS_TERMINATOR) || Float::INFINITY end
parse_argv()
click to toggle source
Helpers
# File lib/simple_scripting/tab_completion/commandline_processor.rb, line 89 def parse_argv # We need to convert all the arguments to optional, otherwise it's not possible to # autocomplete arguments when not all the mandatory ones are not typed yet, eg: # # `my_command <tab>` with definition ['mand1', 'mand2'] # adapted_switches_definition = switches_definition.dup adapted_switches_definition.each_with_index do |definition, i| adapted_switches_definition[i] = "[#{definition}]" if definition.is_a?(String) && !definition.start_with?('[') end SimpleScripting::Argv.decode(*adapted_switches_definition, arguments: processed_argv.dup, auto_help: false) rescue Argv::InvalidCommand, Argv::ArgumentError, OptionParser::InvalidOption # OptionParser::InvalidOption: see case "-O<tab>" in test suite. # return nil end