lib/brakeman/report/pager.rb
module Brakeman
class Pager
def initialize tracker, pager = :less, output = $stdout
@tracker = tracker
@pager = pager
@output = output
@less_available = @less_options = nil
end
def page_report report, format
if @pager == :less
set_color
end
text = report.format(format)
if in_ci?
no_pager text
else
page_output text
end
end
def page_output text
case @pager
when :none
no_pager text
when :highline
page_via_highline text
when :less
if less_available?
page_via_less text
else
page_via_highline text
end
else
no_pager text
end
end
def no_pager text
@output.puts text
end
def page_via_highline text
Brakeman.load_brakeman_dependency 'highline'
h = ::HighLine.new($stdin, @output)
h.page_at = :auto
h.say text
end
def page_via_less text
# Adapted from https://github.com/piotrmurach/tty-pager/
write_io = IO.popen("less #{less_options.join}", 'w')
pid = write_io.pid
write_io.write(text)
write_io.close
Process.waitpid2(pid, Process::WNOHANG)
rescue Errno::ECHILD
# on jruby 9x waiting on pid raises (per tty-pager)
true
rescue => e
warn "[Error] #{e}"
warn "[Error] Could not use pager. Set --no-pager to avoid this issue."
no_pager text
end
def in_ci?
ci = ENV["CI"]
ci.is_a? String and ci.downcase == "true"
end
def less_available?
return @less_available unless @less_available.nil?
@less_available = system("which less > /dev/null")
end
def less_options
# -R show colors
# -F exit if output fits on one screen
# -X do not clear screen after less exits
return @less_options if @less_options
@less_options = []
if system("which less > /dev/null")
less_help = `less -?`
["-R ", "-F ", "-X "].each do |opt|
if less_help.include? opt
@less_options << opt
end
end
end
@less_options
end
def set_color
return unless @tracker
unless less_options.include? "-R " or @tracker.options[:output_color] == :force
@tracker.options[:output_color] = false
end
end
end
end