diff options
author | Stan Lo <[email protected]> | 2023-07-26 09:31:58 +0100 |
---|---|---|
committer | git <[email protected]> | 2023-07-26 08:32:02 +0000 |
commit | 283b2fdab4be77d8721d7cf298168eb6e3798490 (patch) | |
tree | a660b377328de9a6aee25c859cf212a9e56a1865 | |
parent | 26aef1c73639718bc00c271ce7176bf3ee565c12 (diff) |
[ruby/irb] Page `ls`'s output (https://github.com/ruby/irb/pull/657)
* Page ls command's output
* Use Pager.page_content in show_cmds too
https://github.com/ruby/irb/commit/82d1687302
-rw-r--r-- | lib/irb/cmd/ls.rb | 17 | ||||
-rw-r--r-- | lib/irb/cmd/show_cmds.rb | 4 | ||||
-rw-r--r-- | lib/irb/pager.rb | 25 | ||||
-rw-r--r-- | test/irb/test_cmd.rb | 10 | ||||
-rw-r--r-- | test/irb/yamatanooroti/test_rendering.rb | 48 |
5 files changed, 96 insertions, 8 deletions
diff --git a/lib/irb/cmd/ls.rb b/lib/irb/cmd/ls.rb index 063a88d33f..791b1c1b21 100644 --- a/lib/irb/cmd/ls.rb +++ b/lib/irb/cmd/ls.rb @@ -1,7 +1,9 @@ # frozen_string_literal: true require "reline" +require "stringio" require_relative "nop" +require_relative "../pager" require_relative "../color" module IRB @@ -33,7 +35,7 @@ module IRB o.dump("instance variables", obj.instance_variables) o.dump("class variables", klass.class_variables) o.dump("locals", locals) - nil + o.print_result end def dump_methods(o, klass, obj) @@ -77,6 +79,11 @@ module IRB def initialize(grep: nil) @grep = grep @line_width = screen_width - MARGIN.length # right padding + @io = StringIO.new + end + + def print_result + Pager.page_content(@io.string) end def dump(name, strs) @@ -85,12 +92,12 @@ module IRB return if strs.empty? # Attempt a single line - print "#{Color.colorize(name, [:BOLD, :BLUE])}: " + @io.print "#{Color.colorize(name, [:BOLD, :BLUE])}: " if fits_on_line?(strs, cols: strs.size, offset: "#{name}: ".length) - puts strs.join(MARGIN) + @io.puts strs.join(MARGIN) return end - puts + @io.puts # Dump with the largest # of columns that fits on a line cols = strs.size @@ -99,7 +106,7 @@ module IRB end widths = col_widths(strs, cols: cols) strs.each_slice(cols) do |ss| - puts ss.map.with_index { |s, i| "#{MARGIN}%-#{widths[i]}s" % s }.join + @io.puts ss.map.with_index { |s, i| "#{MARGIN}%-#{widths[i]}s" % s }.join end end diff --git a/lib/irb/cmd/show_cmds.rb b/lib/irb/cmd/show_cmds.rb index 1c9f1ea19a..cef6254ca0 100644 --- a/lib/irb/cmd/show_cmds.rb +++ b/lib/irb/cmd/show_cmds.rb @@ -29,9 +29,7 @@ module IRB output.puts end - Pager.page do |io| - io.puts output.string - end + Pager.page_content(output.string) end end end diff --git a/lib/irb/pager.rb b/lib/irb/pager.rb index 16066cf273..1194e41f6f 100644 --- a/lib/irb/pager.rb +++ b/lib/irb/pager.rb @@ -7,6 +7,16 @@ module IRB PAGE_COMMANDS = [ENV['RI_PAGER'], ENV['PAGER'], 'less', 'more'].compact.uniq class << self + def page_content(content) + if content_exceeds_screen_height?(content) + page do |io| + io.puts content + end + else + $stdout.puts content + end + end + def page if STDIN.tty? && pager = setup_pager begin @@ -30,6 +40,21 @@ module IRB private + def content_exceeds_screen_height?(content) + screen_height, screen_width = begin + Reline.get_screen_size + rescue Errno::EINVAL + [24, 80] + end + + pageable_height = screen_height - 3 # leave some space for previous and the current prompt + + # If the content has more lines than the pageable height + content.lines.count > pageable_height || + # Or if the content is a few long lines + pageable_height * screen_width < Reline::Unicode.calculate_width(content, true) + end + def setup_pager require 'shellwords' diff --git a/test/irb/test_cmd.rb b/test/irb/test_cmd.rb index 71d64a0ec2..dcea020b1e 100644 --- a/test/irb/test_cmd.rb +++ b/test/irb/test_cmd.rb @@ -710,6 +710,16 @@ module TestIRB end class LsTest < CommandTestCase + def setup + STDIN.singleton_class.define_method :tty? do + false + end + end + + def teardown + STDIN.singleton_class.remove_method :tty? + end + def test_ls out, err = execute_lines( "class P\n", diff --git a/test/irb/yamatanooroti/test_rendering.rb b/test/irb/yamatanooroti/test_rendering.rb index 12467b0913..420339c452 100644 --- a/test/irb/yamatanooroti/test_rendering.rb +++ b/test/irb/yamatanooroti/test_rendering.rb @@ -270,6 +270,54 @@ class IRB::RenderingTest < Yamatanooroti::TestCase assert_match(/foobar/, screen) end + def test_pager_page_content_pages_output_when_it_does_not_fit_in_the_screen_because_of_total_length + 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("IRB::Pager.page_content('a' * (80 * 8))\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}/, screen) + # because pager is invoked, foobar will not be evaluated + assert_not_match(/foobar/, screen) + end + + def test_pager_page_content_pages_output_when_it_does_not_fit_in_the_screen_because_of_screen_height + 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("IRB::Pager.page_content('a\n' * 8)\n") + write("'foo' + 'bar'\n") # eval something to make sure IRB resumes + close + + screen = result.join("\n").sub(/\n*\z/, "\n") + assert_match(/(a\n){8}/, screen) + # because pager is invoked, foobar will not be evaluated + assert_not_match(/foobar/, screen) + end + + def test_pager_page_content_doesnt_page_output_when_it_fits_in_the_screen + 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("IRB::Pager.page_content('a' * (80 * 7))\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}/, screen) + # because pager is not invoked, foobar will be evaluated + assert_match(/foobar/, screen) + end + private def write_irbrc(content) |