Class: IRB::Completion
- Inherits:
-
Object
- Object
- IRB::Completion
- Defined in:
- lib/irb/ext/completion.rb
Constant Summary collapse
- TYPE =
Convenience constants for sexp access of Ripper::SexpBuilder.
0
- VALUE =
1
- CALLEE =
3
- RESERVED_UPCASE_WORDS =
%w{ BEGIN END }
- RESERVED_DOWNCASE_WORDS =
%w{ alias and begin break case class def defined do else elsif end ensure false for if in module next nil not or redo rescue retry return self super then true undef unless until when while yield }
Instance Attribute Summary collapse
-
#source ⇒ Object
readonly
Returns the value of attribute source.
Instance Method Summary collapse
-
#call(source) ⇒ Object
Returns an array of possible completion results, with the current IRB::Context.
-
#constants ⇒ Object
TODO: test and or fix the fact that we need to get constants from the singleton class.
- #context ⇒ Object
- #evaluate(s) ⇒ Object
- #expand_path(source) ⇒ Object
- #format_methods(receiver, methods, filter) ⇒ Object
- #global_variables ⇒ Object
- #instance_methods ⇒ Object
- #instance_methods_of(klass) ⇒ Object
- #instance_variables ⇒ Object
- #local_variables ⇒ Object
- #match_methods_vars_or_consts_in_scope(symbol) ⇒ Object
- #methods_of_object(root) ⇒ Object
- #methods_of_object_in_variable(path) ⇒ Object
- #results ⇒ Object
- #unwind_callstack(root, stack = []) ⇒ Object
Instance Attribute Details
#source ⇒ Object (readonly)
Returns the value of attribute source.
39 40 41 |
# File 'lib/irb/ext/completion.rb', line 39 def source @source end |
Instance Method Details
#call(source) ⇒ Object
Returns an array of possible completion results, with the current IRB::Context.
This is meant to be used with Readline which takes a completion proc.
49 50 51 52 |
# File 'lib/irb/ext/completion.rb', line 49 def call(source) @source = source results end |
#constants ⇒ Object
TODO: test and or fix the fact that we need to get constants from the singleton class.
80 81 82 |
# File 'lib/irb/ext/completion.rb', line 80 def constants evaluate('Object.constants + self.class.constants + (class << self; constants; end)').map(&:to_s) end |
#context ⇒ Object
41 42 43 |
# File 'lib/irb/ext/completion.rb', line 41 def context IRB::Driver.current.context end |
#evaluate(s) ⇒ Object
54 55 56 |
# File 'lib/irb/ext/completion.rb', line 54 def evaluate(s) context.__evaluate__(s) end |
#expand_path(source) ⇒ Object
131 132 133 134 135 136 137 138 139 |
# File 'lib/irb/ext/completion.rb', line 131 def (source) tokens = Ripper.lex(source) path = tokens[0][2] string_open = tokens[1][2] end_with_slash = path.length > 1 && path.end_with?('/') path = File.(path) path << '/' if end_with_slash Dir.glob("#{path}*", File::FNM_CASEFOLD).map { |f| "#{string_open}#{f}" } end |
#format_methods(receiver, methods, filter) ⇒ Object
172 173 174 |
# File 'lib/irb/ext/completion.rb', line 172 def format_methods(receiver, methods, filter) (filter ? methods.grep(/^#{filter}/) : methods).map { |m| "#{receiver}.#{m}" } end |
#global_variables ⇒ Object
66 67 68 |
# File 'lib/irb/ext/completion.rb', line 66 def global_variables super.map(&:to_s) end |
#instance_methods ⇒ Object
70 71 72 |
# File 'lib/irb/ext/completion.rb', line 70 def instance_methods context.object.methods.map(&:to_s) end |
#instance_methods_of(klass) ⇒ Object
74 75 76 |
# File 'lib/irb/ext/completion.rb', line 74 def instance_methods_of(klass) evaluate(klass).instance_methods end |
#instance_variables ⇒ Object
62 63 64 |
# File 'lib/irb/ext/completion.rb', line 62 def instance_variables context.object.instance_variables.map(&:to_s) end |
#local_variables ⇒ Object
58 59 60 |
# File 'lib/irb/ext/completion.rb', line 58 def local_variables evaluate('local_variables').map(&:to_s) end |
#match_methods_vars_or_consts_in_scope(symbol) ⇒ Object
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/irb/ext/completion.rb', line 151 def match_methods_vars_or_consts_in_scope(symbol) var = symbol[VALUE] filter = var[VALUE] result = case var[TYPE] when :@ident local_variables + instance_methods + RESERVED_DOWNCASE_WORDS when :@ivar instance_variables when :@gvar global_variables when :@const if symbol[TYPE] == :top_const_ref filter = "::#{filter}" Object.constants.map { |c| "::#{c}" } else constants + RESERVED_UPCASE_WORDS end end (result && filter) ? result.grep(/^#{Regexp.quote(filter)}/) : result end |
#methods_of_object(root) ⇒ Object
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/irb/ext/completion.rb', line 176 def methods_of_object(root) result = case root[TYPE] # [:unary, :-@, [x, …]] # ^ when :unary then return methods_of_object(root[2]) # TODO: do we really need this? when :var_ref, :top_const_ref then return methods_of_object_in_variable(root) when :array, :words_add, :qwords_add then Array when :@int then Fixnum when :@float then Float when :hash then Hash when :lambda then Proc when :dot2, :dot3 then Range when :regexp_literal then Regexp when :string_literal then String when :symbol_literal, :dyna_symbol then Symbol end.instance_methods end |
#methods_of_object_in_variable(path) ⇒ Object
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/irb/ext/completion.rb', line 194 def methods_of_object_in_variable(path) type, name = path[VALUE][0..1] if path[TYPE] == :top_const_ref if type == :@const && Object.constants.include?(name.to_sym) evaluate("::#{name}").methods end else case type when :@ident evaluate(name).methods if local_variables.include?(name) when :@ivar evaluate(name).methods if instance_variables.include?(name) when :@gvar eval(name).methods if global_variables.include?(name) when :@const evaluate(name).methods if constants.include?(name) end end end |
#results ⇒ Object
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 124 125 126 127 128 129 |
# File 'lib/irb/ext/completion.rb', line 84 def results return if @source.strip.empty? source = @source filter = nil # if ends with period, remove it to remove the syntax error it causes call = (source[-1,1] == '.') receiver = source = source[0..-2] if call # root node: # [:program, [:stmts_add, [:stmts_new], [x, …]]] # ^ if (sexp = Ripper::SexpBuilder.new(source).parse) && root = sexp[1][2] # [:call, [:hash, nil], :".", [:@ident, x, …]] if root[TYPE] == :call call = true stack = unwind_callstack(root) # [[:var_ref, [:@const, "Klass", [1, 0]]], [:call, "new"]] # [[:var_ref, [:@ident, "klass", [1, 0]]], [:call, "new"], [:call, "filter"]] if stack[1][VALUE] == 'new' klass = stack[0][VALUE][VALUE] filter = stack[2][VALUE] if stack[2] receiver = "#{klass}.new" methods = instance_methods_of(klass) else filter = root[CALLEE][VALUE] filter = stack[1][VALUE] receiver = source[0..-(filter.length + 2)] root = root[VALUE] end end result = if call if m = (methods || methods_of_object(root)) format_methods(receiver, m, filter) end elsif root[TYPE] == :string_literal && root[VALUE][TYPE] == :string_content # in the form of: "~/code/ (source) else match_methods_vars_or_consts_in_scope(root) end result.sort.uniq if result end end |
#unwind_callstack(root, stack = []) ⇒ Object
141 142 143 144 145 146 147 148 149 |
# File 'lib/irb/ext/completion.rb', line 141 def unwind_callstack(root, stack = []) if root[TYPE] == :call stack.unshift [:call, root[CALLEE][VALUE]] unwind_callstack(root[VALUE], stack) else stack.unshift root end stack end |