1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

[ruby/irb] Complete require and require_relative

1c61178b4c
This commit is contained in:
aycabta 2021-03-24 14:55:05 +09:00 committed by git
parent 0259ee6008
commit 0927756e58
3 changed files with 71 additions and 2 deletions

View file

@ -9,6 +9,8 @@
autoload :RDoc, "rdoc"
require_relative 'ruby-lex'
module IRB
module InputCompletor # :nodoc:
@ -38,8 +40,60 @@ module IRB
BASIC_WORD_BREAK_CHARACTERS = " \t\n`><=;|&{("
CompletionProc = proc { |input|
retrieve_completion_data(input).compact.map{ |i| i.encode(Encoding.default_external) }
CompletionRequireProc = lambda { |target, preposing = nil, postposing = nil|
if target =~ /\A(['"])([^'"]+)\Z/
quote = $1
actual_target = $2
else
return nil # It's not String literal
end
tokens = RubyLex.ripper_lex_without_warning(preposing.gsub(/\s*\z/, ''))
tok = nil
tokens.reverse_each do |t|
unless [:on_lparen, :on_sp, :on_ignored_sp, :on_nl, :on_ignored_nl, :on_comment].include?(t.event)
tok = t
break
end
end
if tok && tok.event == :on_ident && tok.state == Ripper::EXPR_CMDARG
case tok.tok
when 'require'
result = $LOAD_PATH.flat_map { |path|
begin
Dir.glob("**/*.{rb,#{RbConfig::CONFIG['DLEXT']}}", base: path)
rescue Errno::ENOENT
[]
end
}.uniq.map { |path|
path.sub(/\.(rb|#{RbConfig::CONFIG['DLEXT']})\z/, '')
}.select { |path|
path.start_with?(actual_target)
}.map { |path|
quote + path
}
when 'require_relative'
result = Dir.glob("**/*.{rb,#{RbConfig::CONFIG['DLEXT']}}", base: '.').map { |path|
path.sub(/\.(rb|#{RbConfig::CONFIG['DLEXT']})\z/, '')
}.select { |path|
path.start_with?(actual_target)
}.map { |path|
quote + path
}
end
end
result
}
CompletionProc = lambda { |target, preposing = nil, postposing = nil|
if preposing && postposing
result = CompletionRequireProc.(target, preposing, postposing)
unless result
result = retrieve_completion_data(target).compact.map{ |i| i.encode(Encoding.default_external) }
end
result
else
retrieve_completion_data(target).compact.map{ |i| i.encode(Encoding.default_external) }
end
}
def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace.binding, doc_namespace: false)

View file

@ -280,6 +280,7 @@ module IRB
Reline.basic_word_break_characters = IRB::InputCompletor::BASIC_WORD_BREAK_CHARACTERS
end
Reline.completion_append_character = nil
Reline.completer_quote_characters = ''
Reline.completion_proc = IRB::InputCompletor::CompletionProc
Reline.output_modifier_proc =
if IRB.conf[:USE_COLORIZE]

View file

@ -55,5 +55,19 @@ module TestIRB
namespace = IRB::InputCompletor.retrieve_completion_data("1.positive?", bind: binding, doc_namespace: true)
assert_equal "Integer.positive?", namespace
end
def test_complete_require
candidates = IRB::InputCompletor::CompletionProc.("'irb", "require ", "")
%w['irb/init 'irb/ruby-lex].each do |word|
assert_include candidates, word
end
end
def test_complete_require_relative
candidates = IRB::InputCompletor::CompletionProc.("'lib/irb", "require_relative ", "")
%w['lib/irb/init 'lib/irb/ruby-lex].each do |word|
assert_include candidates, word
end
end
end
end