[macruby-changes] [4628] DietRB/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Fri Oct 8 03:50:52 PDT 2010
Revision: 4628
http://trac.macosforge.org/projects/ruby/changeset/4628
Author: eloy.de.enige at gmail.com
Date: 2010-10-08 03:50:50 -0700 (Fri, 08 Oct 2010)
Log Message:
-----------
Start writing a new completion extension, based on Ripper. Now handles the simple literal cases.
From: Eloy Duran <eloy.de.enige at gmail.com>
Modified Paths:
--------------
DietRB/trunk/lib/irb/ext/completion.rb
Added Paths:
-----------
DietRB/trunk/spec/completion_spec.rb
Modified: DietRB/trunk/lib/irb/ext/completion.rb
===================================================================
--- DietRB/trunk/lib/irb/ext/completion.rb 2010-10-08 10:50:40 UTC (rev 4627)
+++ DietRB/trunk/lib/irb/ext/completion.rb 2010-10-08 10:50:50 UTC (rev 4628)
@@ -1,209 +1,47 @@
-#
-# irb/completor.rb -
-# $Release Version: 0.9$
-# $Revision: 20880 $
-# by Keiju ISHITSUKA(keiju at ishitsuka.com)
-# From Original Idea of shugo at ruby-lang.org
-#
+require 'ripper'
-puts 'hiero!'
-require "readline"
-
module IRB
- module InputCompletor
-
- @RCS_ID='-$Id: completion.rb 20880 2008-12-19 11:37:41Z yugui $-'
-
- ReservedWords = [
- "BEGIN", "END",
- "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",
- ]
+ class Completion
+ attr_reader :source
+
+ def initialize(source)
+ @source = source
+ end
+
+ def results
+ src = @source
- CompletionProc = proc { |input|
- # bind = IRB.conf[:MAIN_CONTEXT].workspace.binding
- bind = IRB::Context.current.binding
+ # if ends with period, remove it to remove the syntax error it causes
+ call = (src[-1,1] == '.')
+ src = src[0..-2] if call
-# puts "input: #{input}"
-
- case input
- when /^(\/[^\/]*\/)\.([^.]*)$/
- # Regexp
- receiver = $1
- message = Regexp.quote($2)
-
- candidates = Regexp.instance_methods.collect{|m| m.to_s}
- select_message(receiver, message, candidates)
-
- when /^([^\]]*\])\.([^.]*)$/
- # Array
- receiver = $1
- message = Regexp.quote($2)
-
- candidates = Array.instance_methods.collect{|m| m.to_s}
- select_message(receiver, message, candidates)
-
- when /^([^\}]*\})\.([^.]*)$/
- # Proc or Hash
- receiver = $1
- message = Regexp.quote($2)
-
- candidates = Proc.instance_methods.collect{|m| m.to_s}
- candidates |= Hash.instance_methods.collect{|m| m.to_s}
- select_message(receiver, message, candidates)
-
- when /^(:[^:.]*)$/
- # Symbol
- if Symbol.respond_to?(:all_symbols)
- sym = $1
- candidates = Symbol.all_symbols.collect{|s| ":" + s.id2name}
- candidates.grep(/^#{sym}/)
- else
- []
- end
-
- when /^::([A-Z][^:\.\(]*)$/
- # Absolute Constant or class methods
- receiver = $1
- candidates = Object.constants.collect{|m| m.to_s}
- candidates.grep(/^#{receiver}/).collect{|e| "::" + e}
-
- when /^(((::)?[A-Z][^:.\(]*)+)::?([^:.]*)$/
- # Constant or class methods
- receiver = $1
- message = Regexp.quote($4)
- begin
- candidates = eval("#{receiver}.constants.collect{|m| m.to_s}", bind)
- candidates |= eval("#{receiver}.methods.collect{|m| m.to_s}", bind)
- rescue Exception
- candidates = []
- end
- candidates.grep(/^#{message}/).collect{|e| receiver + "::" + e}
-
- when /^(:[^:.]+)\.([^.]*)$/
- # Symbol
- receiver = $1
- message = Regexp.quote($2)
-
- candidates = Symbol.instance_methods.collect{|m| m.to_s}
- select_message(receiver, message, candidates)
-
- when /^(-?(0[dbo])?[0-9_]+(\.[0-9_]+)?([eE]-?[0-9]+)?)\.([^.]*)$/
- # Numeric
- receiver = $1
- message = Regexp.quote($5)
-
- begin
- candidates = eval(receiver, bind).methods.collect{|m| m.to_s}
- rescue Exception
- candidates = []
- end
- select_message(receiver, message, candidates)
-
- when /^(-?0x[0-9a-fA-F_]+)\.([^.]*)$/
- # Numeric(0xFFFF)
- receiver = $1
- message = Regexp.quote($2)
-
- begin
- candidates = eval(receiver, bind).methods.collect{|m| m.to_s}
- rescue Exception
- candidates = []
- end
- select_message(receiver, message, candidates)
-
- when /^(\$[^.]*)$/
- regmessage = Regexp.new(Regexp.quote($1))
- candidates = global_variables.collect{|m| m.to_s}.grep(regmessage)
-
-# when /^(\$?(\.?[^.]+)+)\.([^.]*)$/
- when /^((\.?[^.]+)+)\.([^.]*)$/
- # variable
- receiver = $1
- message = Regexp.quote($3)
-
- gv = eval("global_variables", bind).collect{|m| m.to_s}
- lv = eval("local_variables", bind).collect{|m| m.to_s}
- cv = eval("self.class.constants", bind).collect{|m| m.to_s}
-
- if (gv | lv | cv).include?(receiver)
- # foo.func and foo is local var.
- candidates = eval("#{receiver}.methods", bind).collect{|m| m.to_s}
- elsif /^[A-Z]/ =~ receiver and /\./ !~ receiver
- # Foo::Bar.func
- begin
- candidates = eval("#{receiver}.methods", bind).collect{|m| m.to_s}
- rescue Exception
- candidates = []
- end
- else
- # func1.func2
- candidates = []
- ObjectSpace.each_object(Module){|m|
- begin
- name = m.name
- rescue Exception
- name = ""
- end
- next if name != "IRB::Context" and
- /^(IRB|SLex|RubyLex|RubyToken)/ =~ name
- candidates.concat m.instance_methods(false).collect{|x| x.to_s}
- }
- candidates.sort!
- candidates.uniq!
- end
- select_message(receiver, message, candidates)
-
- when /^\.([^.]*)$/
- # unknown(maybe String)
-
- receiver = ""
- message = Regexp.quote($1)
-
- candidates = String.instance_methods(true).collect{|m| m.to_s}
- select_message(receiver, message, candidates)
-
- else
- candidates = eval("methods | private_methods | local_variables | self.class.constants", bind).collect{|m| m.to_s}
-
- (candidates|ReservedWords).grep(/^#{Regexp.quote(input)}/)
+ # p src, call
+ results = Ripper::SexpBuilder.new(src).parse
+ # p results
+
+ # [:program, [:stmts_add, [:stmts_new], [x, …]]]
+ # ^
+ sub = results[1][2]
+ klass = case sub[0]
+ when :regexp_literal then Regexp
+ when :array, :words_add, :qwords_add then Array
+ when :lambda then Proc
+ when :hash then Hash
+ when :symbol_literal, :dyna_symbol then Symbol
+ when :string_literal then String
+ when :dot2, :dot3 then Range
+ when :@int then Fixnum
+ when :@float then Float
+ when :unary then
+ # [:program, [:stmts_add, [:stmts_new], [:unary, :-@, [x, …]]]]
+ # ^
+ case sub[2][0]
+ when :@int then Fixnum
+ when :@float then Float
+ end
end
- }
-
- Operators = ["%", "&", "*", "**", "+", "-", "/",
- "<", "<<", "<=", "<=>", "==", "===", "=~", ">", ">=", ">>",
- "[]", "[]=", "^",]
-
- def self.select_message(receiver, message, candidates)
- candidates.grep(/^#{message}/).collect do |e|
- case e
- when /^[a-zA-Z_]/
- receiver + "." + e
- when /^[0-9]/
- when *Operators
- #receiver + " " + e
- end
- end
+
+ klass.instance_methods.map(&:to_s)
end
end
end
-
-if Readline.respond_to?("basic_word_break_characters=")
- Readline.basic_word_break_characters= " \t\n\"\\'`><=;|&{("
-end
-Readline.completion_append_character = nil
-Readline.completion_proc = IRB::InputCompletor::CompletionProc
Added: DietRB/trunk/spec/completion_spec.rb
===================================================================
--- DietRB/trunk/spec/completion_spec.rb (rev 0)
+++ DietRB/trunk/spec/completion_spec.rb 2010-10-08 10:50:50 UTC (rev 4628)
@@ -0,0 +1,118 @@
+require File.expand_path('../spec_helper', __FILE__)
+require 'irb/ext/completion'
+
+module CompletionHelper
+ def complete(str)
+ IRB::Completion.new(str).results
+ end
+
+ def imethods(klass)
+ klass.instance_methods.map(&:to_s)
+ end
+end
+
+describe "IRB::Completion, returns all instance methods if the source ends with a period and" do
+ extend CompletionHelper
+
+ it "matches a Regexp literal" do
+ complete('//.').should == imethods(Regexp)
+ complete('/^(:[^:.]+)\.([^.]*)$/.').should == imethods(Regexp)
+ complete('/^(#{oops})\.([^.]*)$/.').should == imethods(Regexp)
+ complete('%r{/foo/.*/bar}.').should == imethods(Regexp)
+ end
+
+ it "matches an Array literal" do
+ complete('[].').should == imethods(Array)
+ complete('[:ok, {}, "foo",].').should == imethods(Array)
+ complete('[*foo].').should == imethods(Array)
+ complete('%w{foo}.').should == imethods(Array)
+ complete('%W{#{:foo}}.').should == imethods(Array)
+ end
+
+ # fails on MacRuby
+ it "matches a lambda literal" do
+ complete('->{}.').should == imethods(Proc)
+ complete('->{x=:ok}.').should == imethods(Proc)
+ complete('->(x){x=:ok}.').should == imethods(Proc)
+ end
+
+ it "matches a Hash literal" do
+ complete('{}.').should == imethods(Hash)
+ complete('{:foo=>:bar,}.').should == imethods(Hash)
+ complete('{foo:"bar"}.').should == imethods(Hash)
+ end
+
+ it "matches a Symbol literal" do
+ complete(':foo.').should == imethods(Symbol)
+ complete(':"foo.bar".').should == imethods(Symbol)
+ complete(':"foo.#{"bar"}".').should == imethods(Symbol)
+ complete(':\'foo.#{"bar"}\'.').should == imethods(Symbol)
+ complete('%s{foo.bar}.').should == imethods(Symbol)
+ end
+
+ it "matches a String literal" do
+ complete("'foo\\'bar'.").should == imethods(String)
+ complete('"foo\"bar".').should == imethods(String)
+ complete('"foo#{"bar"}".').should == imethods(String)
+ complete('%{foobar}.').should == imethods(String)
+ complete('%q{foo#{:bar}}.').should == imethods(String)
+ complete('%Q{foo#{:bar}}.').should == imethods(String)
+ end
+
+ it "matches a Range literal" do
+ complete('1..10.').should == imethods(Range)
+ complete('1...10.').should == imethods(Range)
+ complete('"a".."z".').should == imethods(Range)
+ complete('"a"..."z".').should == imethods(Range)
+ end
+
+ it "matches a Fixnum literal" do
+ complete('42.').should == imethods(Fixnum)
+ complete('+42.').should == imethods(Fixnum)
+ complete('-42.').should == imethods(Fixnum)
+ complete('42_000.').should == imethods(Fixnum)
+ end
+
+ it "matches a Bignum literal as a Fixnum" do
+ complete('100_000_000_000_000_000_000.').should == imethods(Fixnum)
+ complete('-100_000_000_000_000_000_000.').should == imethods(Fixnum)
+ complete('+100_000_000_000_000_000_000.').should == imethods(Fixnum)
+ end
+
+ it "matches a Float with exponential literal" do
+ complete('1.2e-3.').should == imethods(Float)
+ complete('+1.2e-3.').should == imethods(Float)
+ complete('-1.2e-3.').should == imethods(Float)
+ end
+
+ it "matches a hex literal as a Fixnum" do
+ complete('0xffff').should == imethods(Fixnum)
+ complete('+0xffff').should == imethods(Fixnum)
+ complete('-0xffff').should == imethods(Fixnum)
+ end
+
+ it "matches a binary literal as a Fixnum" do
+ complete('0b01011').should == imethods(Fixnum)
+ complete('-0b01011').should == imethods(Fixnum)
+ complete('+0b01011').should == imethods(Fixnum)
+ end
+
+ it "matches an octal literal as a Fixnum" do
+ complete('0377').should == imethods(Fixnum)
+ complete('-0377').should == imethods(Fixnum)
+ complete('+0377').should == imethods(Fixnum)
+ end
+
+ it "matches a Float literal" do
+ complete('42.0.').should == imethods(Float)
+ complete('-42.0.').should == imethods(Float)
+ complete('+42.0.').should == imethods(Float)
+ complete('42_000.0.').should == imethods(Float)
+ end
+
+ it "matches a Bignum float literal as a Float" do
+ complete('100_000_000_000_000_000_000.0.').should == imethods(Float)
+ complete('+100_000_000_000_000_000_000.0.').should == imethods(Float)
+ complete('-100_000_000_000_000_000_000.0.').should == imethods(Float)
+ end
+end
\ No newline at end of file
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20101008/3ef8c67f/attachment-0001.html>
More information about the macruby-changes
mailing list