зеркало из https://github.com/github/ruby.git
[ruby/irb] Page evaluation result's output
(https://github.com/ruby/irb/pull/784) * Page evaluation result's output This will make it easier to work with long output that exceeds the terminal's height. * Use consistent TERM in rendering tests This makes sure we get consistent result on all platforms. https://github.com/ruby/irb/commit/4fedce93d3
This commit is contained in:
Родитель
cc393b4f80
Коммит
f193f96d31
|
@ -20,6 +20,7 @@ require_relative "irb/color"
|
||||||
require_relative "irb/version"
|
require_relative "irb/version"
|
||||||
require_relative "irb/easter-egg"
|
require_relative "irb/easter-egg"
|
||||||
require_relative "irb/debug"
|
require_relative "irb/debug"
|
||||||
|
require_relative "irb/pager"
|
||||||
|
|
||||||
# IRB stands for "interactive Ruby" and is a tool to interactively execute Ruby
|
# IRB stands for "interactive Ruby" and is a tool to interactively execute Ruby
|
||||||
# expressions read from the standard input.
|
# expressions read from the standard input.
|
||||||
|
@ -859,11 +860,12 @@ module IRB
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if multiline_p && @context.newline_before_multiline_output?
|
if multiline_p && @context.newline_before_multiline_output?
|
||||||
printf @context.return_format, "\n#{str}"
|
str = "\n" + str
|
||||||
else
|
|
||||||
printf @context.return_format, str
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Pager.page_content(format(@context.return_format, str), retain_content: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Outputs the local variables to this current session, including
|
# Outputs the local variables to this current session, including
|
||||||
|
|
|
@ -7,9 +7,9 @@ module IRB
|
||||||
PAGE_COMMANDS = [ENV['RI_PAGER'], ENV['PAGER'], 'less', 'more'].compact.uniq
|
PAGE_COMMANDS = [ENV['RI_PAGER'], ENV['PAGER'], 'less', 'more'].compact.uniq
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
def page_content(content)
|
def page_content(content, **options)
|
||||||
if content_exceeds_screen_height?(content)
|
if content_exceeds_screen_height?(content)
|
||||||
page do |io|
|
page(**options) do |io|
|
||||||
io.puts content
|
io.puts content
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
@ -17,8 +17,8 @@ module IRB
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def page
|
def page(retain_content: false)
|
||||||
if IRB.conf[:USE_PAGER] && STDIN.tty? && pager = setup_pager
|
if IRB.conf[:USE_PAGER] && STDIN.tty? && pager = setup_pager(retain_content: retain_content)
|
||||||
begin
|
begin
|
||||||
pid = pager.pid
|
pid = pager.pid
|
||||||
yield pager
|
yield pager
|
||||||
|
@ -55,19 +55,20 @@ module IRB
|
||||||
pageable_height * screen_width < Reline::Unicode.calculate_width(content, true)
|
pageable_height * screen_width < Reline::Unicode.calculate_width(content, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
def setup_pager
|
def setup_pager(retain_content:)
|
||||||
require 'shellwords'
|
require 'shellwords'
|
||||||
|
|
||||||
PAGE_COMMANDS.each do |pager|
|
PAGE_COMMANDS.each do |pager_cmd|
|
||||||
pager = Shellwords.split(pager)
|
cmd = Shellwords.split(pager_cmd)
|
||||||
next if pager.empty?
|
next if cmd.empty?
|
||||||
|
|
||||||
if pager.first == 'less'
|
if cmd.first == 'less'
|
||||||
pager << '-R' unless pager.include?('-R')
|
cmd << '-R' unless cmd.include?('-R')
|
||||||
|
cmd << '-X' if retain_content && !cmd.include?('-X')
|
||||||
end
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
io = IO.popen(pager, 'w')
|
io = IO.popen(cmd, 'w')
|
||||||
rescue
|
rescue
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
|
|
@ -93,6 +93,10 @@ module TestIRB
|
||||||
if ruby_core?
|
if ruby_core?
|
||||||
omit "This test works only under ruby/irb"
|
omit "This test works only under ruby/irb"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
write_rc <<~RUBY
|
||||||
|
IRB.conf[:USE_PAGER] = false
|
||||||
|
RUBY
|
||||||
end
|
end
|
||||||
|
|
||||||
def teardown
|
def teardown
|
||||||
|
@ -197,8 +201,14 @@ module TestIRB
|
||||||
end
|
end
|
||||||
|
|
||||||
def write_rc(content)
|
def write_rc(content)
|
||||||
@irbrc = Tempfile.new('irbrc')
|
# Append irbrc content if a tempfile for it already exists
|
||||||
@tmpfiles << @irbrc
|
if @irbrc
|
||||||
|
@irbrc = File.open(@irbrc, "a")
|
||||||
|
else
|
||||||
|
@irbrc = Tempfile.new('irbrc')
|
||||||
|
@tmpfiles << @irbrc
|
||||||
|
end
|
||||||
|
|
||||||
@irbrc.write(content)
|
@irbrc.write(content)
|
||||||
@irbrc.close
|
@irbrc.close
|
||||||
@envs['IRBRC'] = @irbrc.path
|
@envs['IRBRC'] = @irbrc.path
|
||||||
|
|
|
@ -11,6 +11,7 @@ module TestIRB
|
||||||
IRB.init_config(nil)
|
IRB.init_config(nil)
|
||||||
IRB.conf[:USE_SINGLELINE] = false
|
IRB.conf[:USE_SINGLELINE] = false
|
||||||
IRB.conf[:VERBOSE] = false
|
IRB.conf[:VERBOSE] = false
|
||||||
|
IRB.conf[:USE_PAGER] = false
|
||||||
workspace = IRB::WorkSpace.new(Object.new)
|
workspace = IRB::WorkSpace.new(Object.new)
|
||||||
@context = IRB::Context.new(nil, workspace, TestInputMethod.new)
|
@context = IRB::Context.new(nil, workspace, TestInputMethod.new)
|
||||||
|
|
||||||
|
|
|
@ -346,10 +346,6 @@ module TestIRB
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_show_cmds_display_different_content_when_debugger_is_enabled
|
def test_show_cmds_display_different_content_when_debugger_is_enabled
|
||||||
write_rc <<~RUBY
|
|
||||||
IRB.conf[:USE_PAGER] = false
|
|
||||||
RUBY
|
|
||||||
|
|
||||||
write_ruby <<~'ruby'
|
write_ruby <<~'ruby'
|
||||||
binding.irb
|
binding.irb
|
||||||
ruby
|
ruby
|
||||||
|
|
|
@ -6,10 +6,6 @@ require_relative "helper"
|
||||||
module TestIRB
|
module TestIRB
|
||||||
class InputTest < IntegrationTestCase
|
class InputTest < IntegrationTestCase
|
||||||
def test_symbol_aliases_are_handled_correctly
|
def test_symbol_aliases_are_handled_correctly
|
||||||
write_rc <<~RUBY
|
|
||||||
IRB.conf[:USE_PAGER] = false
|
|
||||||
RUBY
|
|
||||||
|
|
||||||
write_ruby <<~'RUBY'
|
write_ruby <<~'RUBY'
|
||||||
class Foo
|
class Foo
|
||||||
end
|
end
|
||||||
|
@ -26,7 +22,6 @@ module TestIRB
|
||||||
|
|
||||||
def test_symbol_aliases_are_handled_correctly_with_singleline_mode
|
def test_symbol_aliases_are_handled_correctly_with_singleline_mode
|
||||||
write_rc <<~RUBY
|
write_rc <<~RUBY
|
||||||
IRB.conf[:USE_PAGER] = false
|
|
||||||
IRB.conf[:USE_SINGLELINE] = true
|
IRB.conf[:USE_SINGLELINE] = true
|
||||||
RUBY
|
RUBY
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@ end
|
||||||
|
|
||||||
class IRB::RenderingTest < Yamatanooroti::TestCase
|
class IRB::RenderingTest < Yamatanooroti::TestCase
|
||||||
def setup
|
def setup
|
||||||
|
@original_term = ENV['TERM']
|
||||||
|
ENV['TERM'] = "xterm-256color"
|
||||||
@pwd = Dir.pwd
|
@pwd = Dir.pwd
|
||||||
suffix = '%010d' % Random.rand(0..65535)
|
suffix = '%010d' % Random.rand(0..65535)
|
||||||
@tmpdir = File.join(File.expand_path(Dir.tmpdir), "test_irb_#{$$}_#{suffix}")
|
@tmpdir = File.join(File.expand_path(Dir.tmpdir), "test_irb_#{$$}_#{suffix}")
|
||||||
|
@ -27,6 +29,7 @@ class IRB::RenderingTest < Yamatanooroti::TestCase
|
||||||
def teardown
|
def teardown
|
||||||
FileUtils.rm_rf(@tmpdir)
|
FileUtils.rm_rf(@tmpdir)
|
||||||
ENV['IRBRC'] = @irbrc_backup
|
ENV['IRBRC'] = @irbrc_backup
|
||||||
|
ENV['TERM'] = @original_term
|
||||||
ENV.delete('RELINE_TEST_PROMPT') if ENV['RELINE_TEST_PROMPT']
|
ENV.delete('RELINE_TEST_PROMPT') if ENV['RELINE_TEST_PROMPT']
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -377,6 +380,40 @@ class IRB::RenderingTest < Yamatanooroti::TestCase
|
||||||
assert_match(/foobar/, screen)
|
assert_match(/foobar/, screen)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_long_evaluation_output_is_paged
|
||||||
|
write_irbrc <<~'LINES'
|
||||||
|
puts 'start IRB'
|
||||||
|
require "irb/pager"
|
||||||
|
LINES
|
||||||
|
start_terminal(10, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
|
||||||
|
write("'a' * 80 * 11\n")
|
||||||
|
write("'foo' + 'bar'\n") # eval something to make sure IRB resumes
|
||||||
|
close
|
||||||
|
|
||||||
|
screen = result.join("\n").sub(/\n*\z/, "\n")
|
||||||
|
assert_match(/(a{80}\n){8}/, screen)
|
||||||
|
# because pager is invoked, foobar will not be evaluated
|
||||||
|
assert_not_match(/foobar/, screen)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_long_evaluation_output_is_preserved_after_paging
|
||||||
|
write_irbrc <<~'LINES'
|
||||||
|
puts 'start IRB'
|
||||||
|
require "irb/pager"
|
||||||
|
LINES
|
||||||
|
start_terminal(10, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
|
||||||
|
write("'a' * 80 * 11\n")
|
||||||
|
write("q") # quit pager
|
||||||
|
write("'foo' + 'bar'\n") # eval something to make sure IRB resumes
|
||||||
|
close
|
||||||
|
|
||||||
|
screen = result.join("\n").sub(/\n*\z/, "\n")
|
||||||
|
# confirm pager has exited
|
||||||
|
assert_match(/foobar/, screen)
|
||||||
|
# confirm output is preserved
|
||||||
|
assert_match(/(a{80}\n){6}/, screen)
|
||||||
|
end
|
||||||
|
|
||||||
def test_debug_integration_hints_debugger_commands
|
def test_debug_integration_hints_debugger_commands
|
||||||
write_irbrc <<~'LINES'
|
write_irbrc <<~'LINES'
|
||||||
IRB.conf[:USE_COLORIZE] = false
|
IRB.conf[:USE_COLORIZE] = false
|
||||||
|
|
Загрузка…
Ссылка в новой задаче