Class: RVC::Completion

Inherits:
Object
  • Object
show all
Defined in:
lib/rvc/completion.rb

Instance Method Summary collapse

Constructor Details

#initialize(shell) ⇒ Completion

Returns a new instance of Completion.



40
41
42
43
# File 'lib/rvc/completion.rb', line 40

def initialize shell
  @shell = shell
  @cache = TTLCache.new 10
end

Instance Method Details

#child_candidates(word) ⇒ Object

TODO convert to globbing



160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/rvc/completion.rb', line 160

def child_candidates word
  arcs, absolute, trailing_slash = Path.parse word
  last = trailing_slash ? '' : (arcs.pop || '')
  arcs.map! { |x| x.gsub '\\', '' }
  base = absolute ? @shell.fs.root : @shell.fs.cur
  cur = @shell.fs.traverse(base, arcs).first or return []
  arcs.unshift '' if absolute
  children = @cache[cur, :children] rescue []
  children.
    select { |k,v| k.gsub(' ', '\\ ') =~ /^#{Regexp.escape(last)}/ }.
    map { |k,v| (arcs+[k])*'/' }.
    map { |x| x.gsub ' ', '\\ ' }.
    map { |x| [x, '/'] }
end

#cmd_candidates(word) ⇒ Object



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/rvc/completion.rb', line 129

def cmd_candidates word
  cmdpath = word.split '.'
  cmdpath << '' if cmdpath.empty? or word[-1..-1] == '.'
  prefix_regex = /^#{Regexp.escape(cmdpath[-1])}/

  ns = @shell.cmds.lookup(cmdpath[0...-1].map(&:to_sym), RVC::Namespace)
  return [] unless ns

  cmdpath_prefix = cmdpath[0...-1].join('.')
  cmdpath_prefix << '.' unless cmdpath_prefix.empty?

  ret = []

  ns.commands.each do |cmd_name,cmd|
    ret << ["#{cmdpath_prefix}#{cmd_name}", ' '] if cmd_name.to_s =~ prefix_regex
  end

  ns.namespaces.each do |ns_name,ns|
    ret << ["#{cmdpath_prefix}#{ns_name}.", ''] if ns_name.to_s =~ prefix_regex
  end

  # Aliases
  if ns == @shell.cmds then
    ret.concat @shell.cmds.aliases.keys.map(&:to_s).grep(prefix_regex).map { |x| [x, ' '] }
  end

  ret.sort_by! { |a,b| a }
  ret
end

#complete(word, line, point) ⇒ Object



83
84
85
86
87
88
89
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
115
116
117
118
119
120
121
122
123
# File 'lib/rvc/completion.rb', line 83

def complete word, line, point
  candidates = []

  if line and point
    # Full completion capabilities
    line = line[0...point]
    first_whitespace_index = line.index(' ')

    if !first_whitespace_index
      # Command
      candidates.concat cmd_candidates(word)
    else
      # Arguments
      begin
        cmdpath, args = Shell.parse_input line
      rescue ArgumentError
        # Unmatched double quote
        cmdpath, args = Shell.parse_input(line+'"')
      end

      if cmd = @shell.cmds.lookup(cmdpath)
        args << word if word == ''
        candidates.concat cmd.complete(word, args)
      else
        candidates.concat fs_candidates(word)
      end
    end
  else
    # Limited completion
    candidates.concat cmd_candidates(word)
    candidates.concat fs_candidates(word)
  end

  if candidates.size == 1
    append_char = candidates[0][1]
  else
    append_char = '?' # should never be displayed
  end

  return append_char, candidates.map(&:first)
end

#completor(word) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/rvc/completion.rb', line 61

def completor word
  return unless word
  begin
    line = Readline.line_buffer if Readline.respond_to? :line_buffer
    point = Readline.point if Readline.respond_to? :point
    append_char, candidates = complete word, line, point
    Readline.completion_append_character = append_char
    candidates
  rescue RVC::Util::UserError
    puts
    puts $!.message
    Readline.refresh_line
  rescue
    puts
    puts "#{$!.class}: #{$!.message}"
    $!.backtrace.each do |x|
      puts x
    end
    Readline.refresh_line
  end
end

#fs_candidates(word) ⇒ Object



125
126
127
# File 'lib/rvc/completion.rb', line 125

def fs_candidates word
  child_candidates(word) + mark_candidates(word)
end

#inspectObject

Halt infinite loop when printing exceptions



46
47
48
# File 'lib/rvc/completion.rb', line 46

def inspect
  ""
end

#installObject



50
51
52
53
54
55
56
57
58
59
# File 'lib/rvc/completion.rb', line 50

def install
  if Readline.respond_to? :char_is_quoted=
    Readline.completer_word_break_characters = " \t\n\"'"
    Readline.completer_quote_characters = "\"\\"
    is_quoted = lambda { |str,i| i > 0 && str[i-1] == '\\' && !is_quoted[str,i-1] }
    Readline.char_is_quoted = is_quoted
  end

  Readline.completion_proc = lambda { |word| completor(word) }
end

#mark_candidates(word) ⇒ Object



175
176
177
178
179
180
# File 'lib/rvc/completion.rb', line 175

def mark_candidates word
  return [] unless word.empty? || word[0..0] == '~'
  prefix_regex = /^#{Regexp.escape(word[1..-1] || '')}/
  @shell.fs.marks.keys.grep(prefix_regex).sort.
                       map { |x| ["~#{x}", '/'] }
end