Kouhei Sutou
kous****@users*****
Wed May 10 17:43:19 JST 2006
Index: kazehakase/data/ext/ruby/kz/Makefile.am diff -u kazehakase/data/ext/ruby/kz/Makefile.am:1.1 kazehakase/data/ext/ruby/kz/Makefile.am:1.2 --- kazehakase/data/ext/ruby/kz/Makefile.am:1.1 Sat Jan 14 19:34:55 2006 +++ kazehakase/data/ext/ruby/kz/Makefile.am Wed May 10 17:43:19 2006 @@ -5,6 +5,7 @@ extrubydir = $(datadir)/$(PACKAGE)/ext/ruby/kz extruby_DATA = \ ruby-dialog.rb \ + ruby-completion.rb \ actions.rb EXTRA_DIST = \ Index: kazehakase/data/ext/ruby/kz/ruby-completion.rb diff -u /dev/null kazehakase/data/ext/ruby/kz/ruby-completion.rb:1.1 --- /dev/null Wed May 10 17:43:19 2006 +++ kazehakase/data/ext/ruby/kz/ruby-completion.rb Wed May 10 17:43:19 2006 @@ -0,0 +1,152 @@ +# based on irb/completion.rb + +module Kz + module RubyCompletion + RESERVED_WORDS = [ + "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", + ] + + module_function + def complete(input, bind) + case input + when /^(\/[^\/]*\/)\.([^.]*)$/ + # Regexp + receiver = $1 + message = Regexp.quote($2) + + candidates = Regexp.instance_methods(true) + select_message(receiver, message, candidates) + when /^([^\]]*\])\.([^.]*)$/ + # Array + receiver = $1 + message = Regexp.quote($2) + + candidates = Array.instance_methods(true) + select_message(receiver, message, candidates) + when /^([^\}]*\})\.([^.]*)$/ + # Proc or Hash + receiver = $1 + message = Regexp.quote($2) + + candidates = Proc.instance_methods(true) | Hash.instance_methods(true) + 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 + candidates.grep(/^#{receiver}/).collect{|e| "::" + e} + when /^(((::)?[A-Z][^:.\(]*)+)::?([^:.]*)$/ + # Constant or class methods + receiver = $1 + message = Regexp.quote($4) + begin + candidates = eval("#{receiver}.constants | #{receiver}.methods", bind) + rescue Exception + candidates = [] + end + candidates.grep(/^#{message}/).collect{|e| receiver + "::" + e} + when /^(:[^:.]+)\.([^.]*)$/ + # Symbol + receiver = $1 + message = Regexp.quote($2) + + candidates = Symbol.instance_methods(true) + select_message(receiver, message, candidates) + when /^([0-9_]+(\.[0-9_]+)?(e[0-9]+)?)\.([^.]*)$/ + # Numeric + receiver = $1 + message = Regexp.quote($4) + + begin + candidates = eval(receiver, bind).methods + rescue Exception + [] + end + select_message(receiver, message, candidates) + when /^((\"|\').*\2)\.([^.]*)$/ + # String + receiver = $1 + message = Regexp.quote($3) + + candidates = String.instance_methods(true) + select_message(receiver, message, candidates) + when /^(\$[^.]*)$/ + candidates = global_variables.grep(Regexp.new(Regexp.quote($1))) + when /^((\.?[^.]+)+)\.([^.]*)$/ + # variable + receiver = $1 + message = Regexp.quote($3) + + gv = eval("global_variables", bind) + lv = eval("local_variables", bind) + cv = eval("self.class.constants", bind) + + if (gv | lv | cv).include?(receiver) + # foo.func and foo is local var. + candidates = eval("#{receiver}.methods", bind) + elsif /^[A-Z]/ =~ receiver and /\./ !~ receiver + # Foo::Bar.func + begin + candidates = eval("#{receiver}.methods", bind) + rescue Exception + candidates = [] + end + else + # func1.func2 + candidates = [] + end + select_message(receiver, message, candidates) + else + methods_exp = "methods | private_methods | local_variables" + constants_exp = "self.class.constants" + exp = "#{methods_exp} | #{constants_exp}" + candidates = eval(exp, bind) + + (candidates | RESERVED_WORDS).grep(/^#{Regexp.quote(input)}/) + end + end + + OPERATORS = [ + "%", "&", "*", "**", "+", "-", "/", + "<", "<<", "<=", "<=>", "==", "===", "=~", ">", ">=", ">>", + "[]", "[]=", "^", + ] + + def 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 + end + end +end Index: kazehakase/data/ext/ruby/kz/ruby-dialog.rb diff -u kazehakase/data/ext/ruby/kz/ruby-dialog.rb:1.7 kazehakase/data/ext/ruby/kz/ruby-dialog.rb:1.8 --- kazehakase/data/ext/ruby/kz/ruby-dialog.rb:1.7 Wed May 10 17:20:41 2006 +++ kazehakase/data/ext/ruby/kz/ruby-dialog.rb Wed May 10 17:43:19 2006 @@ -16,11 +16,14 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # +require "kz/ruby-completion" + module Kz class SandBox + attr_reader :binding def initialize(kz) @kz = kz - @binding = binding + @binding = Kernel.binding end def evaluate(statements, file=__FILE__, line=__LINE__) @@ -149,6 +152,12 @@ end end update_widget_font(@entry, nil, "monospace") + @ruby_exp_completion = Gtk::EntryCompletion.new + @ruby_exp_model = Gtk::ListStore.new(String) + @ruby_exp_completion.model = @ruby_exp_model + @ruby_exp_completion.text_column = 0 + @ruby_exp_completion.inline_completion = true + @entry.completion = @ruby_exp_completion @entry_last_text = nil @entry end @@ -202,6 +211,17 @@ when Gdk::Keyval::GDK_Down handled = next_history handled = true + when Gdk::Keyval::GDK_i + @ruby_exp_completion.insert_prefix if event.state.control_mask? + else + if !@entry.text.strip.empty? + @ruby_exp_model.clear + result = Kz::RubyCompletion.complete(@entry.text, @sandbox.binding) + result.compact.sort.each do |item| + iter = @ruby_exp_model.append + iter[0] = item + end + end end handled end