class TTY::Pager::SystemPager

A system pager is used on systems where native pagination exists

@api public

Public Class Methods

command_exists?(command) click to toggle source

Check if command exists

@example

command_exists?('less) # => true

@param [String] command

the command to check

@return [Boolean]

@api private

# File lib/tty/pager/system.rb, line 23
def self.command_exists?(command)
  TTY::Which.exist?(command)
end
exec_available?(*commands) click to toggle source

Check if command is available

@example Basic usage

available?  # => true

@example Usage with command

available?('less') # => true

@return [Boolean]

@api public

# File lib/tty/pager/system.rb, line 88
def self.exec_available?(*commands)
  !find_executable(*commands).nil?
end
executables() click to toggle source

List possible executables for output paging

@return [Array]

@api private

# File lib/tty/pager/system.rb, line 50
def self.executables
  [ENV['GIT_PAGER'], ENV['PAGER'],
   command_exists?('git') ? `git config --get-all core.pager` : nil,
   'less -r', 'more -r', 'most', 'cat', 'pager', 'pg'].compact
end
find_executable(*commands) click to toggle source

Find first available termainal pager program executable

@example Basic usage

find_executable # => 'less'

@example Usage with commands

find_executable('less', 'cat')  # => 'less'

@param [Array] commands

@return [String, nil]

the found executable or nil when not found

@api public

# File lib/tty/pager/system.rb, line 70
def self.find_executable(*commands)
  execs = commands.empty? ? executables : commands
  execs
    .compact.map(&:strip).reject(&:empty?).uniq
    .find { |cmd| command_exists?(cmd.split.first) }
end
new(**options) click to toggle source

Create a system pager

@param [Hash] options @option options [String] :command

the command to use for paging

@api public

Calls superclass method TTY::Pager::new
# File lib/tty/pager/system.rb, line 99
def initialize(**options)
  super
  @pager_command = nil
  commands = Array(options[:command])
  pager_command(*commands)

  if @pager_command.nil?
    raise TTY::Pager::Error, "#{self.class.name} cannot be used on your" \
                             " system due to lack of appropriate pager" \
                             " executable. Install `less` like pager or" \
                             " try using `BasicPager` instead." \
  end
end
run_command(*args) click to toggle source

Run pager command silently with no input and capture output

@return [nil, String]

command output or nil if command fails to run

@api private

# File lib/tty/pager/system.rb, line 33
def self.run_command(*args)
  require 'tempfile'
  out = Tempfile.new('tty-pager')
  result = system(*args, out: out.path, err: out.path, in: ::File::NULL)
  return if result.nil?
  out.rewind
  out.read
ensure
  out.close
  out.unlink
end

Public Instance Methods

page(text, &_callback) click to toggle source

Use system command to page output text

@example

page('some long text...')

@param [String] text

the text to paginate

@return [Boolean]

the success status of launching a process

@api public

# File lib/tty/pager/system.rb, line 125
def page(text, &_callback)
  return text unless output.tty?

  command = pager_command
  out = self.class.run_command(command)
  # Issue running command, e.g. unsupported flag, fallback to just command
  if !out.empty?
    command = pager_command.split.first
  end

  pager_io = open("|#{command}", 'w')
  pid      = pager_io.pid

  pager_io.write(text)
  pager_io.close

  _, status = Process.waitpid2(pid, Process::WNOHANG)
  status.success?
rescue Errno::ECHILD
  # on jruby 9x waiting on pid raises
  true
end
pager_command(*commands) click to toggle source

The pager command to run

@return [String]

the name of executable to run

@api private

# File lib/tty/pager/system.rb, line 154
def pager_command(*commands)
  @pager_command = if @pager_command && commands.empty?
                     @pager_command
                   else
                     self.class.find_executable(*commands)
                   end
end