irb-pager/lib/irb-pager.rb

72 lines
2.4 KiB
Ruby

module IRB
module Pager
extend IRB::Pager
module PagerHelper
# Parses options for `IRB::Pager::pager`
def self.options opts = nil
opts = opts.kind_of?( Hash) ? opts.dup : {}
stdout = opts[:stdout] || opts[:out] || $stdout
stderr = opts[:stderr] || opts[:err] || $stderr
stdin = opts[:stdin] || opts[:in] || $stdin
pager = opts[:pager] || opts[:less] || $PAGER || ENV['PAGER'] || 'less'
rescuing = opts[:rescuing].nil? ? opts[:exceptions].nil? ? $PAGER_RESCUE : opts[:exceptions] : opts[:rescuing]
[stdout, stderr, stdin, pager, rescuing]
end
# Exception formatter for `IRB::Pager::pager`.
def self.exception_formatter exception
["#{exception.class}: #{exception.message}", exception.backtrace.collect {|c| "\tfrom #{c}" }].join "\n"
end
end
# Starts pager (for example `less`).
# $stdin, $stderr and $stdout will be redirected to pager and your block will be called.
# On return or a raised exception, $stdin, $stderr and $stdout will be redirected to the original IOs.
# Instead of redirecting output for your block, you can inspect an object in pager.
# If pager will be exit, your program will be run like before.
#
# Possible Options:
# `opts[:stdout]`, `opts[:out]`: redirect this instead `$stdout`
# `opts[:stderr]`, `opts[:err]`: redirect this instead `$stderr`
# `opts[:stdin]`, `opts[:in]`: redirect this instead `$stdin`
# `opts[:pager]`, `opts[:less]`, `$PAGER`, `ENV['PAGER']`: use this pager instead less
# `opts[:rescuing]`, `opts[:exceptions]`, `$PAGER_RESCUE`: unless `false` or `nil` rescue exception and print it via pager, too
def pager obj = nil, opts = nil, &exe
if block_given?
stdout, stderr, stdin, pager, rescuing = PagerHelper.options( opts || obj)
pid, dupout, duperr, dupin = nil, stdout.dup, stderr.dup, stdin.dup
IO.pipe do |inrd, inwr|
begin
IO.pipe do |rd, wr|
pid = Process.fork do
stdin.reopen rd
wr.close
exec *pager
end
stdout.reopen wr
stderr.reopen wr
stdin.reopen inrd
if rescuing
begin
yield
rescue Object
stdout.puts PagerHelper.exception_formatter
end
else
yield
end
end
ensure
stdout.reopen dupout
stderr.reopen duperr
Process.wait pid
stdin.reopen dupin
end
end
else
pager( opts) { Kernel.p obj }
end
end
end
end