diff options
author | Stan Lo <[email protected]> | 2023-11-30 15:22:17 +0000 |
---|---|---|
committer | git <[email protected]> | 2023-11-30 15:22:22 +0000 |
commit | f193f96d31ffcd02d91f135ba765d92c23b52c55 (patch) | |
tree | 758eb77f0fc698b691dfa9275bdd3d48c12af3bf | |
parent | cc393b4f80be7eccdc84785f684dc7899b0510e4 (diff) |
[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
-rw-r--r-- | lib/irb.rb | 8 | ||||
-rw-r--r-- | lib/irb/pager.rb | 23 | ||||
-rw-r--r-- | test/irb/helper.rb | 14 | ||||
-rw-r--r-- | test/irb/test_context.rb | 1 | ||||
-rw-r--r-- | test/irb/test_debug_cmd.rb | 4 | ||||
-rw-r--r-- | test/irb/test_irb.rb | 5 | ||||
-rw-r--r-- | test/irb/yamatanooroti/test_rendering.rb | 37 |
7 files changed, 67 insertions, 25 deletions
diff --git a/lib/irb.rb b/lib/irb.rb index 66149eb455..1ba335c087 100644 --- a/lib/irb.rb +++ b/lib/irb.rb @@ -20,6 +20,7 @@ require_relative "irb/color" require_relative "irb/version" require_relative "irb/easter-egg" require_relative "irb/debug" +require_relative "irb/pager" # IRB stands for "interactive Ruby" and is a tool to interactively execute Ruby # expressions read from the standard input. @@ -859,11 +860,12 @@ module IRB end end end + if multiline_p && @context.newline_before_multiline_output? - printf @context.return_format, "\n#{str}" - else - printf @context.return_format, str + str = "\n" + str end + + Pager.page_content(format(@context.return_format, str), retain_content: true) end # Outputs the local variables to this current session, including diff --git a/lib/irb/pager.rb b/lib/irb/pager.rb index e38d97e3c7..a0db5e93b4 100644 --- a/lib/irb/pager.rb +++ b/lib/irb/pager.rb @@ -7,9 +7,9 @@ module IRB PAGE_COMMANDS = [ENV['RI_PAGER'], ENV['PAGER'], 'less', 'more'].compact.uniq class << self - def page_content(content) + def page_content(content, **options) if content_exceeds_screen_height?(content) - page do |io| + page(**options) do |io| io.puts content end else @@ -17,8 +17,8 @@ module IRB end end - def page - if IRB.conf[:USE_PAGER] && STDIN.tty? && pager = setup_pager + def page(retain_content: false) + if IRB.conf[:USE_PAGER] && STDIN.tty? && pager = setup_pager(retain_content: retain_content) begin pid = pager.pid yield pager @@ -55,19 +55,20 @@ module IRB pageable_height * screen_width < Reline::Unicode.calculate_width(content, true) end - def setup_pager + def setup_pager(retain_content:) require 'shellwords' - PAGE_COMMANDS.each do |pager| - pager = Shellwords.split(pager) - next if pager.empty? + PAGE_COMMANDS.each do |pager_cmd| + cmd = Shellwords.split(pager_cmd) + next if cmd.empty? - if pager.first == 'less' - pager << '-R' unless pager.include?('-R') + if cmd.first == 'less' + cmd << '-R' unless cmd.include?('-R') + cmd << '-X' if retain_content && !cmd.include?('-X') end begin - io = IO.popen(pager, 'w') + io = IO.popen(cmd, 'w') rescue next end diff --git a/test/irb/helper.rb b/test/irb/helper.rb index ede48be649..38bdbb4c31 100644 --- a/test/irb/helper.rb +++ b/test/irb/helper.rb @@ -93,6 +93,10 @@ module TestIRB if ruby_core? omit "This test works only under ruby/irb" end + + write_rc <<~RUBY + IRB.conf[:USE_PAGER] = false + RUBY end def teardown @@ -197,8 +201,14 @@ module TestIRB end def write_rc(content) - @irbrc = Tempfile.new('irbrc') - @tmpfiles << @irbrc + # Append irbrc content if a tempfile for it already exists + if @irbrc + @irbrc = File.open(@irbrc, "a") + else + @irbrc = Tempfile.new('irbrc') + @tmpfiles << @irbrc + end + @irbrc.write(content) @irbrc.close @envs['IRBRC'] = @irbrc.path diff --git a/test/irb/test_context.rb b/test/irb/test_context.rb index f4a19ee3c4..79186f13a1 100644 --- a/test/irb/test_context.rb +++ b/test/irb/test_context.rb @@ -11,6 +11,7 @@ module TestIRB IRB.init_config(nil) IRB.conf[:USE_SINGLELINE] = false IRB.conf[:VERBOSE] = false + IRB.conf[:USE_PAGER] = false workspace = IRB::WorkSpace.new(Object.new) @context = IRB::Context.new(nil, workspace, TestInputMethod.new) diff --git a/test/irb/test_debug_cmd.rb b/test/irb/test_debug_cmd.rb index 53d40f7297..0fb45af478 100644 --- a/test/irb/test_debug_cmd.rb +++ b/test/irb/test_debug_cmd.rb @@ -346,10 +346,6 @@ module TestIRB end def test_show_cmds_display_different_content_when_debugger_is_enabled - write_rc <<~RUBY - IRB.conf[:USE_PAGER] = false - RUBY - write_ruby <<~'ruby' binding.irb ruby diff --git a/test/irb/test_irb.rb b/test/irb/test_irb.rb index e6eb3d5da1..fb8b5c2bfa 100644 --- a/test/irb/test_irb.rb +++ b/test/irb/test_irb.rb @@ -6,10 +6,6 @@ require_relative "helper" module TestIRB class InputTest < IntegrationTestCase def test_symbol_aliases_are_handled_correctly - write_rc <<~RUBY - IRB.conf[:USE_PAGER] = false - RUBY - write_ruby <<~'RUBY' class Foo end @@ -26,7 +22,6 @@ module TestIRB def test_symbol_aliases_are_handled_correctly_with_singleline_mode write_rc <<~RUBY - IRB.conf[:USE_PAGER] = false IRB.conf[:USE_SINGLELINE] = true RUBY diff --git a/test/irb/yamatanooroti/test_rendering.rb b/test/irb/yamatanooroti/test_rendering.rb index ca8176dfe6..b18b95bbbd 100644 --- a/test/irb/yamatanooroti/test_rendering.rb +++ b/test/irb/yamatanooroti/test_rendering.rb @@ -10,6 +10,8 @@ end class IRB::RenderingTest < Yamatanooroti::TestCase def setup + @original_term = ENV['TERM'] + ENV['TERM'] = "xterm-256color" @pwd = Dir.pwd suffix = '%010d' % Random.rand(0..65535) @tmpdir = File.join(File.expand_path(Dir.tmpdir), "test_irb_#{$$}_#{suffix}") @@ -27,6 +29,7 @@ class IRB::RenderingTest < Yamatanooroti::TestCase def teardown FileUtils.rm_rf(@tmpdir) ENV['IRBRC'] = @irbrc_backup + ENV['TERM'] = @original_term ENV.delete('RELINE_TEST_PROMPT') if ENV['RELINE_TEST_PROMPT'] end @@ -377,6 +380,40 @@ class IRB::RenderingTest < Yamatanooroti::TestCase assert_match(/foobar/, screen) 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 write_irbrc <<~'LINES' IRB.conf[:USE_COLORIZE] = false |