Class: IRB::Pager
Relationships & Source Files | |
Namespace Children | |
Classes:
| |
Inherits: | Object |
Defined in: | lib/irb/pager.rb |
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
.
Constant Summary
-
PAGE_COMMANDS =
# File 'lib/irb/pager.rb', line 9[ENV['RI_PAGER'], ENV['PAGER'], 'less', 'more'].compact.uniq
Class Attribute Summary
- .should_page? ⇒ Boolean readonly
Class Method Summary
Class Attribute Details
.should_page? ⇒ Boolean
(readonly)
[ GitHub ]
Class Method Details
.content_exceeds_screen_height?(content) ⇒ Boolean
(private)
# File 'lib/irb/pager.rb', line 88
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 return true if content.lines.size > pageable_height _, overflow = take_first_page(screen_width, pageable_height) {|out| out.write content } overflow end
.page(retain_content: false)
[ GitHub ]# 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 rescue Errno::ESRCH # Pager process already terminated end nil rescue Errno::EPIPE end
.page_content(content, **options)
[ GitHub ]# 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| ... }
# File 'lib/irb/pager.rb', line 56
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
.setup_pager(retain_content:) (private)
[ GitHub ]# File 'lib/irb/pager.rb', line 103
def setup_pager(retain_content:) require 'shellwords' PAGE_COMMANDS.each do |pager_cmd| cmd = Shellwords.split(pager_cmd) next if cmd.empty? if cmd.first == 'less' cmd << '-R' unless cmd.include?('-R') cmd << '-X' if retain_content && !cmd.include?('-X') end begin io = IO.popen(cmd, 'w') rescue next end if $? && $?.pid == io.pid && $?.exited? # pager didn't work next end return io end nil end
.take_first_page(width, height) {|out| ... }
# File 'lib/irb/pager.rb', line 77
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