Skip to content

Commit 1b20991

Browse files
authored
Sort remaining completion candidates in RegexpCompletor (#1230)
#379 sorted local variables and string method candidates, but receiver.method completion (the most common case), symbols, global variables and absolute constants were still returned in method table order, which looks random in the completion dialog. Sort them too. Candidates starting with an underscore go last, so that completing `u.` does not begin with __id__, __send__ and other internals.
1 parent fba3999 commit 1b20991

2 files changed

Lines changed: 38 additions & 6 deletions

File tree

lib/irb/completion.rb

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ def retrieve_completion_data(input, bind:, doc_namespace:)
302302
rescue EncodingError
303303
# ignore
304304
end
305-
candidates.grep(/^#{Regexp.quote(sym)}/)
305+
candidates.grep(/^#{Regexp.quote(sym)}/).sort
306306
end
307307
when /^::([A-Z][^:\.\(\)]*)$/
308308
# Absolute Constant or class methods
@@ -313,7 +313,7 @@ def retrieve_completion_data(input, bind:, doc_namespace:)
313313
if doc_namespace
314314
candidates.find { |i| i == receiver }
315315
else
316-
candidates.grep(/^#{Regexp.quote(receiver)}/).collect{|e| "::" + e}
316+
candidates.grep(/^#{Regexp.quote(receiver)}/).sort.collect{|e| "::" + e}
317317
end
318318

319319
when /^([A-Z].*)::([^:.]*)$/
@@ -331,7 +331,7 @@ def retrieve_completion_data(input, bind:, doc_namespace:)
331331
candidates = []
332332
end
333333

334-
select_message(receiver, message, candidates.sort, "::")
334+
select_message(receiver, message, candidates, "::")
335335
end
336336

337337
when /^(:[^:.]+)(\.|::)([^.]*)$/
@@ -400,7 +400,7 @@ def retrieve_completion_data(input, bind:, doc_namespace:)
400400
if doc_namespace
401401
all_gvars.find{ |i| i == gvar }
402402
else
403-
all_gvars.grep(Regexp.new(Regexp.quote(gvar)))
403+
all_gvars.grep(Regexp.new(Regexp.quote(gvar))).sort
404404
end
405405

406406
when /^([^.:"].*)(\.|::)([^.]*)$/
@@ -452,7 +452,7 @@ def retrieve_completion_data(input, bind:, doc_namespace:)
452452
if doc_namespace
453453
"String.#{candidates.find{ |i| i == message }}"
454454
else
455-
select_message(receiver, message, candidates.sort)
455+
select_message(receiver, message, candidates)
456456
end
457457
when /^\s*$/
458458
# empty input
@@ -491,7 +491,11 @@ def retrieve_completion_data(input, bind:, doc_namespace:)
491491
Operators = %w[% & * ** + - / < << <= <=> == === =~ > >= >> [] []= ^ ! != !~]
492492

493493
def select_message(receiver, message, candidates, sep = ".")
494-
candidates.grep(/^#{Regexp.quote(message)}/).collect do |e|
494+
sorted_candidates = candidates.grep(/^#{Regexp.quote(message)}/).sort_by do |e|
495+
# Alphabetical order, but internal methods (leading underscore) last
496+
[e.start_with?('_') ? 1 : 0, e]
497+
end
498+
sorted_candidates.collect do |e|
495499
case e
496500
when /^[a-zA-Z_]/
497501
receiver + sep + e

test/irb/test_completion.rb

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,17 @@ def test_complete_class
9595
assert_include(completion_candidates("String.ne", binding), "String.new")
9696
assert_equal("String.new", doc_namespace("String.new", binding))
9797
end
98+
99+
def test_complete_methods_are_sorted
100+
u = ''
101+
u.clear
102+
103+
candidates = completion_candidates("u.", binding)
104+
assert_include(candidates, "u.__id__")
105+
underscore, regular = candidates.partition { |c| c.start_with?("u._") }
106+
# Alphabetical order, internal methods (leading underscore) last
107+
assert_equal(regular.sort + underscore.sort, candidates)
108+
end
98109
end
99110

100111
class RequireComepletionTest < CompletionTest
@@ -215,6 +226,11 @@ def test_complete_sort_variables
215226
candidates = completion_candidates("xz", binding)
216227
assert_equal(%w[xzy xzy2 xzy_1], candidates)
217228
end
229+
230+
def test_complete_sort_global_variables
231+
candidates = completion_candidates("$std", binding)
232+
assert_equal(%w[$stderr $stdin $stdout], candidates)
233+
end
218234
end
219235

220236
class ConstantCompletionTest < CompletionTest
@@ -255,6 +271,18 @@ def test_complete_symbol
255271
assert_empty(completion_candidates(":", binding))
256272
end
257273

274+
def test_complete_symbols_are_sorted
275+
candidates = completion_candidates(":a", binding)
276+
refute_empty(candidates)
277+
assert_equal(candidates.sort, candidates)
278+
end
279+
280+
def test_complete_absolute_constants_are_sorted
281+
candidates = completion_candidates("::S", binding)
282+
refute_empty(candidates)
283+
assert_equal(candidates.sort, candidates)
284+
end
285+
258286
def test_complete_invalid_three_colons
259287
assert_empty(completion_candidates(":::A", binding))
260288
assert_empty(completion_candidates(":::", binding))

0 commit comments

Comments
 (0)