module Complete
Module containing tab-completion logic and methods.
Public Class Methods
Return an Array
of completion options for the given input line and client state.
# File lib/droxi/complete.rb, line 8 def self.complete(line, state) tokens = Text.tokenize(line, include_empty: true) type = completion_type(tokens) completion_options(type, tokens.last, state).map do |option| option.gsub(' ', '\ ').sub(/\\ $/, ' ') .split.drop(tokens.last.count(' ')).join(' ') .sub(%r{[^\\/]$}, '\0 ') end end
Private Class Methods
# File lib/droxi/complete.rb, line 111 def self.basename(string) string.end_with?('/') ? '' : File.basename(string) end
Return a version of a path with .. and . resolved to appropriate directories.
# File lib/droxi/complete.rb, line 131 def self.collapse(path) new_path = path.dup nil while new_path.sub!(%r{[^/]+/\.\./}, '/') nil while new_path.sub!('./', '') new_path end
Return an Array
of potential command name tab-completions for a String
.
# File lib/droxi/complete.rb, line 48 def self.command(string, names) names.select { |n| n.start_with?(string) }.map { |n| n + ' ' } end
Return an Array
of potential tab-completion options for a given completion type, word, and client state.
# File lib/droxi/complete.rb, line 22 def self.completion_options(type, word, state) case type when 'COMMAND' then command(word, Commands::NAMES) when 'LOCAL_FILE' then local(word) when 'LOCAL_DIR' then local_dir(word) when 'REMOTE_FILE' then remote(word, state) when 'REMOTE_DIR' then remote_dir(word, state) else [] end end
Return a String
representing the type of tab-completion that should be performed, given the current line buffer state.
# File lib/droxi/complete.rb, line 35 def self.completion_type(tokens) index = tokens.drop_while { |token| token[/^-\w+$/] }.size if index <= 1 'COMMAND' elsif tokens[0].start_with?('!') || tokens[0].downcase == 'exec' 'LOCAL_FILE' elsif Commands::NAMES.include?(tokens.first) cmd = Commands.const_get(tokens.first.upcase.to_sym) cmd.type_of_arg(index - 2) end end
# File lib/droxi/complete.rb, line 119 def self.final_match(string, candidate, is_dir) string + candidate.partition(basename(string))[2] + (is_dir ? '/' : ' ') end
Return an Array
of potential local tab-completions for a String
.
# File lib/droxi/complete.rb, line 61 def self.local(string) dir = local_search_path(string) basename = basename(string) begin matches = Dir.entries(dir).select { |entry| match?(basename, entry) } matches.map do |entry| final_match(string, entry, File.directory?(dir + '/' + entry)) end rescue Errno::ENOENT [] end end
Return an Array
of potential local tab-completions for a String
, including only directories.
# File lib/droxi/complete.rb, line 77 def self.local_dir(string) local(string).select { |match| match.end_with?('/') } end
Return the directory in which to search for potential local tab-completions for a String
.
# File lib/droxi/complete.rb, line 54 def self.local_search_path(string) File.expand_path(strip_filename(string)) rescue ArgumentError string end
# File lib/droxi/complete.rb, line 115 def self.match?(prefix, candidate) candidate.start_with?(prefix) && !candidate[/^\.\.?$/] end
Return an Array
of potential remote tab-completions for a String
.
# File lib/droxi/complete.rb, line 94 def self.remote(string, state) dir = remote_search_path(string, state) basename = basename(string) entries = state.contents(dir).map { |entry| File.basename(entry) } matches = entries.select { |entry| match?(basename, entry) } matches.map do |entry| final_match(string, entry, state.directory?(dir + '/' + entry)) end end
Return an Array
of potential remote tab-completions for a String
, including only directories.
# File lib/droxi/complete.rb, line 107 def self.remote_dir(string, state) remote(string, state).select { |result| result.end_with?('/') } end
Return the directory in which to search for potential remote tab-completions for a String
.
# File lib/droxi/complete.rb, line 83 def self.remote_search_path(string, state) path = case when string.empty? then state.pwd + '/' when string.start_with?('/') then string else state.pwd + '/' + string end strip_filename(collapse(path)) end
Return the name of the directory indicated by a path.
# File lib/droxi/complete.rb, line 124 def self.strip_filename(path) return path if path == '/' path.end_with?('/') ? path.sub(%r{/$}, '') : File.dirname(path) end