Class: IRB::Pager
Overview
The implementation of this class is borrowed from RDoc’s lib/rdoc/ri/driver.rb. Please do NOT use this class directly outside of IRB.
Defined Under Namespace
Classes: PageOverflowIO
Constant Summary collapse
- PAGE_COMMANDS =
[ENV['RI_PAGER'], ENV['PAGER'], 'less', 'more'].compact.uniq
Class Method Summary collapse
- .page(retain_content: false) ⇒ Object
- .page_content(content, **options) ⇒ Object
- .page_with_preview(width, height, formatter_proc) {|out| ... } ⇒ Object
- .should_page? ⇒ Boolean
- .take_first_page(width, height) {|out| ... } ⇒ Object
Class Method Details
.page(retain_content: false) ⇒ Object
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/irb/pager.rb', line 22 def page(retain_content: false) if should_page? && pager = setup_pager(retain_content: retain_content) begin pid = pager.pid yield pager ensure pager.close end else yield $stdout end # When user presses Ctrl-C, IRB would raise `IRB::Abort` # But since Pager is implemented by running paging commands like `less` in another process with `IO.popen`, # the `IRB::Abort` exception only interrupts IRB's execution but doesn't affect the pager # So to properly terminate the pager with Ctrl-C, we need to catch `IRB::Abort` and kill the pager process rescue IRB::Abort begin begin Process.kill("TERM", pid) if pid rescue Errno::EINVAL # SIGTERM not supported (windows) Process.kill("KILL", pid) end begin # Wait for the pager process to terminate. # Reading next input from Reline before the pager process is fully terminated # may cause issues like raw/cooked mode not being controlled properly. Process.waitpid(pid) if pid rescue Errno::ECHILD, Errno::ESRCH end rescue Errno::ESRCH # Pager process already terminated end nil rescue Errno::EPIPE end |
.page_content(content, **options) ⇒ Object
12 13 14 15 16 17 18 19 20 |
# File 'lib/irb/pager.rb', line 12 def page_content(content, **) if content_exceeds_screen_height?(content) page(**) do |io| io.puts content end else $stdout.puts content end end |
.page_with_preview(width, height, formatter_proc) {|out| ... } ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/irb/pager.rb', line 64 def page_with_preview(width, height, formatter_proc) overflow_callback = ->(lines) do modified_output = formatter_proc.call(lines.join, true) content, = take_first_page(width, [height - 2, 0].max) {|o| o.write modified_output } content = content.chomp content = "#{content}\e[0m" if Color.colorable? $stdout.puts content $stdout.puts 'Preparing full inspection value...' end out = PageOverflowIO.new(width, height, overflow_callback, delay: 0.1) yield out content = formatter_proc.call(out.string, out.multipage?) if out.multipage? page(retain_content: true) do |io| io.puts content end else $stdout.puts content end end |
.should_page? ⇒ Boolean
60 61 62 |
# File 'lib/irb/pager.rb', line 60 def should_page? IRB.conf[:USE_PAGER] && STDIN.tty? && (ENV.key?("TERM") && ENV["TERM"] != "dumb") end |
.take_first_page(width, height) {|out| ... } ⇒ Object
85 86 87 88 89 90 91 92 |
# File 'lib/irb/pager.rb', line 85 def take_first_page(width, height) overflow_callback = proc do |lines| return lines.join, true end out = Pager::PageOverflowIO.new(width, height, overflow_callback) yield out [out.string, false] end |