diff --git a/lib/irb/completion.rb b/lib/irb/completion.rb index 3dc2fa22a..3fbbf988a 100644 --- a/lib/irb/completion.rb +++ b/lib/irb/completion.rb @@ -302,7 +302,7 @@ def retrieve_completion_data(input, bind:, doc_namespace:) rescue EncodingError # ignore end - candidates.grep(/^#{Regexp.quote(sym)}/) + candidates.grep(/^#{Regexp.quote(sym)}/).sort end when /^::([A-Z][^:\.\(\)]*)$/ # Absolute Constant or class methods @@ -313,7 +313,7 @@ def retrieve_completion_data(input, bind:, doc_namespace:) if doc_namespace candidates.find { |i| i == receiver } else - candidates.grep(/^#{Regexp.quote(receiver)}/).collect{|e| "::" + e} + candidates.grep(/^#{Regexp.quote(receiver)}/).sort.collect{|e| "::" + e} end when /^([A-Z].*)::([^:.]*)$/ @@ -331,7 +331,7 @@ def retrieve_completion_data(input, bind:, doc_namespace:) candidates = [] end - select_message(receiver, message, candidates.sort, "::") + select_message(receiver, message, candidates, "::") end when /^(:[^:.]+)(\.|::)([^.]*)$/ @@ -400,7 +400,7 @@ def retrieve_completion_data(input, bind:, doc_namespace:) if doc_namespace all_gvars.find{ |i| i == gvar } else - all_gvars.grep(Regexp.new(Regexp.quote(gvar))) + all_gvars.grep(Regexp.new(Regexp.quote(gvar))).sort end when /^([^.:"].*)(\.|::)([^.]*)$/ @@ -452,7 +452,7 @@ def retrieve_completion_data(input, bind:, doc_namespace:) if doc_namespace "String.#{candidates.find{ |i| i == message }}" else - select_message(receiver, message, candidates.sort) + select_message(receiver, message, candidates) end when /^\s*$/ # empty input @@ -491,7 +491,11 @@ def retrieve_completion_data(input, bind:, doc_namespace:) Operators = %w[% & * ** + - / < << <= <=> == === =~ > >= >> [] []= ^ ! != !~] def select_message(receiver, message, candidates, sep = ".") - candidates.grep(/^#{Regexp.quote(message)}/).collect do |e| + sorted_candidates = candidates.grep(/^#{Regexp.quote(message)}/).sort_by do |e| + # Alphabetical order, but internal methods (leading underscore) last + [e.start_with?('_') ? 1 : 0, e] + end + sorted_candidates.collect do |e| case e when /^[a-zA-Z_]/ receiver + sep + e diff --git a/test/irb/test_completion.rb b/test/irb/test_completion.rb index 8959604cb..a08767f81 100644 --- a/test/irb/test_completion.rb +++ b/test/irb/test_completion.rb @@ -95,6 +95,17 @@ def test_complete_class assert_include(completion_candidates("String.ne", binding), "String.new") assert_equal("String.new", doc_namespace("String.new", binding)) end + + def test_complete_methods_are_sorted + u = '' + u.clear + + candidates = completion_candidates("u.", binding) + assert_include(candidates, "u.__id__") + underscore, regular = candidates.partition { |c| c.start_with?("u._") } + # Alphabetical order, internal methods (leading underscore) last + assert_equal(regular.sort + underscore.sort, candidates) + end end class RequireComepletionTest < CompletionTest @@ -215,6 +226,11 @@ def test_complete_sort_variables candidates = completion_candidates("xz", binding) assert_equal(%w[xzy xzy2 xzy_1], candidates) end + + def test_complete_sort_global_variables + candidates = completion_candidates("$std", binding) + assert_equal(%w[$stderr $stdin $stdout], candidates) + end end class ConstantCompletionTest < CompletionTest @@ -255,6 +271,18 @@ def test_complete_symbol assert_empty(completion_candidates(":", binding)) end + def test_complete_symbols_are_sorted + candidates = completion_candidates(":a", binding) + refute_empty(candidates) + assert_equal(candidates.sort, candidates) + end + + def test_complete_absolute_constants_are_sorted + candidates = completion_candidates("::S", binding) + refute_empty(candidates) + assert_equal(candidates.sort, candidates) + end + def test_complete_invalid_three_colons assert_empty(completion_candidates(":::A", binding)) assert_empty(completion_candidates(":::", binding))