mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
parent
a6805771ec
commit
52cfb17086
11 changed files with 185 additions and 34 deletions
|
@ -750,8 +750,8 @@ class Binding
|
|||
#
|
||||
# Potato.new
|
||||
#
|
||||
# Running <code>ruby potato.rb</code> will open an IRB session where
|
||||
# +binding.irb+ is called, and you will see the following:
|
||||
# Running +ruby potato.rb+ will open an IRB session where +binding.irb+ is
|
||||
# called, and you will see the following:
|
||||
#
|
||||
# $ ruby potato.rb
|
||||
#
|
||||
|
@ -781,7 +781,7 @@ class Binding
|
|||
# irb(#<Potato:0x00007feea1916670>):004:0> @cooked = true
|
||||
# => true
|
||||
#
|
||||
# You can exit the IRB session with the +exit+ command. Note that exiting will
|
||||
# You can exit the IRB session with the `exit` command. Note that exiting will
|
||||
# resume execution where +binding.irb+ had paused it, as you can see from the
|
||||
# output printed to standard output in this example:
|
||||
#
|
||||
|
|
|
@ -21,7 +21,7 @@ module IRB
|
|||
class << self
|
||||
alias_method :exit, ExtendCommand.irb_original_method_name('exit')
|
||||
end
|
||||
if block_given?
|
||||
if iterator?
|
||||
begin
|
||||
yield
|
||||
ensure
|
||||
|
|
|
@ -17,24 +17,28 @@ module IRB # :nodoc:
|
|||
on_const: ['ENV'],
|
||||
}
|
||||
|
||||
TOKEN_SEQ_EXPRS = {
|
||||
on_CHAR: [[BLUE, BOLD], [Ripper::EXPR_END]],
|
||||
on_const: [[BLUE, BOLD, UNDERLINE], [Ripper::EXPR_ARG, Ripper::EXPR_CMDARG]],
|
||||
on_embexpr_beg: [[RED], [Ripper::EXPR_BEG, Ripper::EXPR_END]],
|
||||
on_embexpr_end: [[RED], [Ripper::EXPR_END, Ripper::EXPR_ENDFN]],
|
||||
on_ident: [[BLUE, BOLD], [Ripper::EXPR_ENDFN]],
|
||||
on_int: [[BLUE, BOLD], [Ripper::EXPR_END]],
|
||||
on_float: [[MAGENTA, BOLD], [Ripper::EXPR_END]],
|
||||
on_kw: [[GREEN], [Ripper::EXPR_ARG, Ripper::EXPR_CLASS, Ripper::EXPR_BEG, Ripper::EXPR_END, Ripper::EXPR_FNAME]],
|
||||
on_label: [[MAGENTA], [Ripper::EXPR_LABELED]],
|
||||
on_qwords_beg: [[RED], [Ripper::EXPR_BEG]],
|
||||
on_regexp_beg: [[RED, BOLD], [Ripper::EXPR_BEG]],
|
||||
on_regexp_end: [[RED, BOLD], [Ripper::EXPR_BEG]],
|
||||
on_symbeg: [[BLUE, BOLD], [Ripper::EXPR_FNAME]],
|
||||
on_tstring_beg: [[RED], [Ripper::EXPR_BEG, Ripper::EXPR_END, Ripper::EXPR_ARG, Ripper::EXPR_CMDARG]],
|
||||
on_tstring_content: [[RED], [Ripper::EXPR_BEG, Ripper::EXPR_ARG, Ripper::EXPR_CMDARG]],
|
||||
on_tstring_end: [[RED], [Ripper::EXPR_END]],
|
||||
}
|
||||
begin
|
||||
TOKEN_SEQ_EXPRS = {
|
||||
on_CHAR: [[BLUE, BOLD], [Ripper::EXPR_END]],
|
||||
on_const: [[BLUE, BOLD, UNDERLINE], [Ripper::EXPR_ARG, Ripper::EXPR_CMDARG]],
|
||||
on_embexpr_beg: [[RED], [Ripper::EXPR_BEG, Ripper::EXPR_END]],
|
||||
on_embexpr_end: [[RED], [Ripper::EXPR_END, Ripper::EXPR_ENDFN]],
|
||||
on_ident: [[BLUE, BOLD], [Ripper::EXPR_ENDFN]],
|
||||
on_int: [[BLUE, BOLD], [Ripper::EXPR_END]],
|
||||
on_float: [[MAGENTA, BOLD], [Ripper::EXPR_END]],
|
||||
on_kw: [[GREEN], [Ripper::EXPR_ARG, Ripper::EXPR_CLASS, Ripper::EXPR_BEG, Ripper::EXPR_END, Ripper::EXPR_FNAME]],
|
||||
on_label: [[MAGENTA], [Ripper::EXPR_LABELED]],
|
||||
on_qwords_beg: [[RED], [Ripper::EXPR_BEG]],
|
||||
on_regexp_beg: [[RED, BOLD], [Ripper::EXPR_BEG]],
|
||||
on_regexp_end: [[RED, BOLD], [Ripper::EXPR_BEG]],
|
||||
on_symbeg: [[BLUE, BOLD], [Ripper::EXPR_FNAME]],
|
||||
on_tstring_beg: [[RED], [Ripper::EXPR_BEG, Ripper::EXPR_END, Ripper::EXPR_ARG, Ripper::EXPR_CMDARG]],
|
||||
on_tstring_content: [[RED], [Ripper::EXPR_BEG, Ripper::EXPR_ARG, Ripper::EXPR_CMDARG]],
|
||||
on_tstring_end: [[RED], [Ripper::EXPR_END]],
|
||||
}
|
||||
rescue NameError
|
||||
TOKEN_SEQ_EXPRS = {}
|
||||
end
|
||||
|
||||
class << self
|
||||
def colorable?
|
||||
|
@ -85,7 +89,7 @@ module IRB # :nodoc:
|
|||
[BLUE, BOLD]
|
||||
elsif TOKEN_KEYWORDS.fetch(token, []).include?(str)
|
||||
[CYAN, BOLD]
|
||||
elsif (seq, exprs = TOKEN_SEQ_EXPRS[token]; exprs&.any? { |e| (expr & e) != Ripper::EXPR_NONE })
|
||||
elsif (seq, exprs = TOKEN_SEQ_EXPRS[token]; exprs&.any? { |e| (expr & e) != 0 })
|
||||
seq
|
||||
else
|
||||
nil
|
||||
|
|
|
@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
|
|||
spec.homepage = "https://github.com/ruby/irb"
|
||||
spec.license = "BSD-2-Clause"
|
||||
|
||||
spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "exe/irb", "irb.gemspec", "lib/irb.rb", "lib/irb/cmd/chws.rb", "lib/irb/cmd/fork.rb", "lib/irb/cmd/help.rb", "lib/irb/cmd/load.rb", "lib/irb/cmd/nop.rb", "lib/irb/cmd/pushws.rb", "lib/irb/cmd/subirb.rb", "lib/irb/completion.rb", "lib/irb/context.rb", "lib/irb/ext/change-ws.rb", "lib/irb/ext/history.rb", "lib/irb/ext/loader.rb", "lib/irb/ext/multi-irb.rb", "lib/irb/ext/save-history.rb", "lib/irb/ext/tracer.rb", "lib/irb/ext/use-loader.rb", "lib/irb/ext/workspaces.rb", "lib/irb/extend-command.rb", "lib/irb/frame.rb", "lib/irb/help.rb", "lib/irb/init.rb", "lib/irb/input-method.rb", "lib/irb/inspector.rb", "lib/irb/lc/.document", "lib/irb/lc/error.rb", "lib/irb/lc/help-message", "lib/irb/lc/ja/encoding_aliases.rb", "lib/irb/lc/ja/error.rb", "lib/irb/lc/ja/help-message", "lib/irb/locale.rb", "lib/irb/magic-file.rb", "lib/irb/notifier.rb", "lib/irb/output-method.rb", "lib/irb/ruby-lex.rb", "lib/irb/ruby-token.rb", "lib/irb/slex.rb", "lib/irb/src_encoding.rb", "lib/irb/version.rb", "lib/irb/workspace.rb", "lib/irb/ws-for-case-2.rb", "lib/irb/xmp.rb"]
|
||||
spec.files = ["LICENSE.txt", "README.md", "exe/irb", "irb.gemspec", "lib/irb.rb", "lib/irb/cmd/chws.rb", "lib/irb/cmd/fork.rb", "lib/irb/cmd/help.rb", "lib/irb/cmd/load.rb", "lib/irb/cmd/nop.rb", "lib/irb/cmd/pushws.rb", "lib/irb/cmd/subirb.rb", "lib/irb/completion.rb", "lib/irb/context.rb", "lib/irb/ext/change-ws.rb", "lib/irb/ext/history.rb", "lib/irb/ext/loader.rb", "lib/irb/ext/multi-irb.rb", "lib/irb/ext/save-history.rb", "lib/irb/ext/tracer.rb", "lib/irb/ext/use-loader.rb", "lib/irb/ext/workspaces.rb", "lib/irb/extend-command.rb", "lib/irb/frame.rb", "lib/irb/help.rb", "lib/irb/init.rb", "lib/irb/input-method.rb", "lib/irb/inspector.rb", "lib/irb/lc/.document", "lib/irb/lc/error.rb", "lib/irb/lc/help-message", "lib/irb/lc/ja/encoding_aliases.rb", "lib/irb/lc/ja/error.rb", "lib/irb/lc/ja/help-message", "lib/irb/locale.rb", "lib/irb/magic-file.rb", "lib/irb/notifier.rb", "lib/irb/output-method.rb", "lib/irb/ruby-lex.rb", "lib/irb/ruby-token.rb", "lib/irb/slex.rb", "lib/irb/src_encoding.rb", "lib/irb/version.rb", "lib/irb/workspace.rb", "lib/irb/ws-for-case-2.rb", "lib/irb/xmp.rb"]
|
||||
spec.bindir = "exe"
|
||||
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
||||
spec.require_paths = ["lib"]
|
||||
|
|
|
@ -49,7 +49,7 @@ EOF
|
|||
@binding = BINDING_QUEUE.pop
|
||||
|
||||
when 3 # binding in function on TOPLEVEL_BINDING(default)
|
||||
@binding = eval("self.class.remove_method(:irb_binding) if defined?(irb_binding); def irb_binding; private; binding; end; irb_binding",
|
||||
@binding = eval("def irb_binding; private; binding; end; irb_binding",
|
||||
TOPLEVEL_BINDING,
|
||||
__FILE__,
|
||||
__LINE__ - 3)
|
||||
|
@ -116,7 +116,11 @@ EOF
|
|||
end
|
||||
|
||||
def code_around_binding
|
||||
file, pos = @binding.source_location
|
||||
if @binding.respond_to?(:source_location)
|
||||
file, pos = @binding.source_location
|
||||
else
|
||||
file, pos = @binding.eval('[__FILE__, __LINE__]')
|
||||
end
|
||||
|
||||
if defined?(::SCRIPT_LINES__[file]) && lines = ::SCRIPT_LINES__[file]
|
||||
code = ::SCRIPT_LINES__[file].join('')
|
||||
|
|
|
@ -15,6 +15,11 @@ module TestIRB
|
|||
CYAN = "\e[36m"
|
||||
|
||||
def test_colorize_code
|
||||
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.5.0')
|
||||
assert_equal({}, IRB::Color::TOKEN_SEQ_EXPRS)
|
||||
skip "this Ripper version is not supported"
|
||||
end
|
||||
|
||||
{
|
||||
"1" => "#{BLUE}#{BOLD}1#{CLEAR}",
|
||||
"2.3" => "#{MAGENTA}#{BOLD}2.3#{CLEAR}",
|
||||
|
@ -23,11 +28,22 @@ module TestIRB
|
|||
"def self.foo; bar; end" => "#{GREEN}def#{CLEAR} #{CYAN}#{BOLD}self#{CLEAR}.#{BLUE}#{BOLD}foo#{CLEAR}; bar; #{GREEN}end#{CLEAR}",
|
||||
'ERB.new("a#{nil}b", trim_mode: "-")' => "#{BLUE}#{BOLD}#{UNDERLINE}ERB#{CLEAR}.new(#{RED}\"#{CLEAR}#{RED}a#{CLEAR}#{RED}\#{#{CLEAR}#{CYAN}#{BOLD}nil#{CLEAR}#{RED}}#{CLEAR}#{RED}b#{CLEAR}#{RED}\"#{CLEAR}, #{MAGENTA}trim_mode:#{CLEAR} #{RED}\"#{CLEAR}#{RED}-#{CLEAR}#{RED}\"#{CLEAR})",
|
||||
"# comment" => "#{BLUE}#{BOLD}# comment#{CLEAR}",
|
||||
'/r#{e}g/' => "#{RED}#{BOLD}/#{CLEAR}#{RED}r#{CLEAR}#{RED}\#{#{CLEAR}e}#{RED}g#{CLEAR}#{RED}#{BOLD}/#{CLEAR}",
|
||||
"yield(hello)" => "#{GREEN}yield#{CLEAR}(hello)",
|
||||
}.each do |code, result|
|
||||
assert_equal(result, with_term { IRB::Color.colorize_code(code) })
|
||||
end
|
||||
|
||||
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.6.0')
|
||||
{
|
||||
'/r#{e}g/' => "#{RED}#{BOLD}/#{CLEAR}#{RED}r#{CLEAR}#{RED}\#{#{CLEAR}e}#{RED}g#{CLEAR}#{RED}#{BOLD}/#{CLEAR}",
|
||||
}
|
||||
else
|
||||
{
|
||||
'/r#{e}g/' => "#{RED}#{BOLD}/#{CLEAR}#{RED}r#{CLEAR}#{RED}\#{#{CLEAR}e#{RED}}#{CLEAR}#{RED}g#{CLEAR}#{RED}#{BOLD}/#{CLEAR}",
|
||||
}
|
||||
end.each do |code, result|
|
||||
assert_equal(result, with_term { IRB::Color.colorize_code(code) })
|
||||
end
|
||||
end
|
||||
|
||||
def test_inspect_colorable
|
||||
|
|
22
test/irb/test_completion.rb
Normal file
22
test/irb/test_completion.rb
Normal file
|
@ -0,0 +1,22 @@
|
|||
# frozen_string_literal: false
|
||||
require 'test/unit'
|
||||
|
||||
module TestIRB
|
||||
class TestCompletion < Test::Unit::TestCase
|
||||
def test_nonstring_module_name
|
||||
begin
|
||||
require "irb/completion"
|
||||
bug5938 = '[ruby-core:42244]'
|
||||
cmds = %W[-rirb -rirb/completion -e IRB.setup(__FILE__)
|
||||
-e IRB.conf[:MAIN_CONTEXT]=IRB::Irb.new.context
|
||||
-e module\sFoo;def\sself.name;//;end;end
|
||||
-e IRB::InputCompletor::CompletionProc.call("[1].first.")
|
||||
-- -f --]
|
||||
status = assert_in_out_err(cmds, "", //, [], bug5938)
|
||||
assert(status.success?, bug5938)
|
||||
rescue LoadError
|
||||
skip "cannot load irb/completion"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -55,7 +55,6 @@ module TestIRB
|
|||
end
|
||||
|
||||
def test_eval_input
|
||||
verbose, $VERBOSE = $VERBOSE, nil
|
||||
input = TestInputMethod.new([
|
||||
"raise 'Foo'\n",
|
||||
"_\n",
|
||||
|
@ -72,8 +71,6 @@ module TestIRB
|
|||
:*, /0$/,
|
||||
:*, /0$/,
|
||||
/\s*/], out)
|
||||
ensure
|
||||
$VERBOSE = verbose
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,7 +4,7 @@ require 'test/unit'
|
|||
module TestIRB
|
||||
class TestRaiseNoBacktraceException < Test::Unit::TestCase
|
||||
def test_raise_exception
|
||||
assert_in_out_err(%w[-rirb -W1 -e IRB.start(__FILE__) -- -f --], <<-IRB, /Exception: foo/, [], success: true)
|
||||
status = assert_in_out_err(%w[-rirb -e IRB.start(__FILE__) -- -f --], <<-IRB, /Exception: foo/, [])
|
||||
e = Exception.new("foo")
|
||||
def e.backtrace; nil; end
|
||||
raise e
|
||||
|
|
108
test/irb/test_ruby-lex.rb
Normal file
108
test/irb/test_ruby-lex.rb
Normal file
|
@ -0,0 +1,108 @@
|
|||
# frozen_string_literal: false
|
||||
require 'test/unit'
|
||||
require 'irb/ruby-lex'
|
||||
require 'stringio'
|
||||
|
||||
module TestIRB
|
||||
class TestRubyLex < Test::Unit::TestCase
|
||||
def setup
|
||||
@scanner = RubyLex.new
|
||||
end
|
||||
|
||||
def teardown
|
||||
RubyLex.debug_level = 0
|
||||
end
|
||||
|
||||
def test_set_input_proc
|
||||
called = false
|
||||
@scanner.set_input(nil) {called = true; nil}
|
||||
@scanner.each_top_level_statement {}
|
||||
assert(called)
|
||||
end
|
||||
|
||||
def test_comment
|
||||
assert_equal([["#\n", 1]], top_level_statement("#\n"))
|
||||
end
|
||||
|
||||
def test_top_level_statement
|
||||
result = top_level_statement("#{<<-"begin;"}#{<<~"end;"}")
|
||||
begin;
|
||||
begin
|
||||
end
|
||||
begin
|
||||
end
|
||||
end;
|
||||
assert_equal([
|
||||
["begin\n""end\n", 1],
|
||||
["begin\n""end\n", 3],
|
||||
],
|
||||
result)
|
||||
end
|
||||
|
||||
def test_immature_statement
|
||||
src = "if false\n"
|
||||
assert_equal([[src, 1]], top_level_statement(src))
|
||||
end
|
||||
|
||||
def test_prompt
|
||||
prompts = []
|
||||
@scanner.set_prompt {|*a|
|
||||
a << @scanner.instance_variable_get(:@lex_state)
|
||||
unless prompts.last == a
|
||||
prompts << a
|
||||
end
|
||||
}
|
||||
src, lineno = "#{<<-"begin;"}#{<<~'end;'}", __LINE__+1
|
||||
begin;
|
||||
# #;# LTYPE:INDENT:CONTINUE
|
||||
x #;# -:0:-
|
||||
x( #;# -:0:-
|
||||
) #;# -:1:*
|
||||
a \ #;# -:0:-
|
||||
#;# -:0:*
|
||||
a; #;# -:0:-
|
||||
a #;# -:0:-
|
||||
#;# -:0:-
|
||||
a #;# -:0:-
|
||||
a = #;# -:0:-
|
||||
' #;# -:0:*
|
||||
' #;# ':0:*
|
||||
if false or #;# -:0:-
|
||||
true #;# -:1:*
|
||||
a #;# -:1:-
|
||||
" #;# -:1:-
|
||||
" #;# ":1:-
|
||||
begin #;# -:1:-
|
||||
a #;# -:2:-
|
||||
a #;# -:2:-
|
||||
end #;# -:2:-
|
||||
else #;# -:1:-
|
||||
nil #;# -:1:-
|
||||
end #;# -:1:-
|
||||
end;
|
||||
top_level_statement(src.gsub(/[ \t]*#;#.*/, ''))
|
||||
src.each_line.with_index(1) do |line, i|
|
||||
p = prompts.shift
|
||||
next unless /#;#\s*(?:-|(?<ltype>\S)):(?<indent>\d+):(?:(?<cont>\*)|-)(?:.*FIXME:(?<fixme>.*))?/ =~ line
|
||||
indent = indent.to_i
|
||||
cont = (fixme && /`continue'/.match?(fixme)) ^ cont
|
||||
assert_equal([ltype, indent, cont, i], p[0..3], "#{lineno+i}:#{p[4]}: #{line}")
|
||||
end
|
||||
end
|
||||
|
||||
def top_level_statement(lines)
|
||||
input = InputLines.new(lines, "r")
|
||||
scanned = []
|
||||
@scanner.set_input(input)
|
||||
@scanner.each_top_level_statement {|*e|
|
||||
scanned << e
|
||||
yield(*e) if defined?(yield)
|
||||
}
|
||||
scanned
|
||||
end
|
||||
|
||||
class InputLines < StringIO
|
||||
alias encoding external_encoding
|
||||
end
|
||||
end
|
||||
end
|
|
@ -7,7 +7,7 @@ require 'irb/color'
|
|||
module TestIRB
|
||||
class TestWorkSpace < Test::Unit::TestCase
|
||||
def test_code_around_binding
|
||||
Tempfile.create do |f|
|
||||
Tempfile.create('irb') do |f|
|
||||
code = <<~RUBY
|
||||
# 1
|
||||
# 2
|
||||
|
@ -37,7 +37,7 @@ module TestIRB
|
|||
skip 'chmod cannot make file unreadable on windows' if windows?
|
||||
skip 'skipped in root privilege' if Process.uid == 0
|
||||
|
||||
Tempfile.create do |f|
|
||||
Tempfile.create('irb') do |f|
|
||||
code = "IRB::WorkSpace.new(binding)\n"
|
||||
f.print(code)
|
||||
f.close
|
||||
|
@ -51,7 +51,7 @@ module TestIRB
|
|||
|
||||
def test_code_around_binding_with_script_lines__
|
||||
with_script_lines do |script_lines|
|
||||
Tempfile.create do |f|
|
||||
Tempfile.create('irb') do |f|
|
||||
code = "IRB::WorkSpace.new(binding)\n"
|
||||
script_lines[f.path] = code.split(/^/)
|
||||
|
||||
|
|
Loading…
Reference in a new issue