class TTY::Pager::SystemPager

A system pager is used on systems where native pagination exists

@api public

Public Class Methods

command_exist?(command) click to toggle source

Check if command exists

@example

command_exist?("less") # => true

@param [String] command

the command to check

@return [Boolean]

@api private

# File lib/tty/pager/system.rb, line 26
def self.command_exist?(command)
  exts = ENV.fetch("PATHEXT", "").split(::File::PATH_SEPARATOR)
  if Pathname.new(command).absolute?
    ::File.exist?(command) ||
      exts.any? { |ext| ::File.exist?("#{command}#{ext}")}
  else
    ENV.fetch("PATH", "").split(::File::PATH_SEPARATOR).any? do |dir|
      file = ::File.join(dir, command)
      ::File.exist?(file) ||
        exts.any? { |ext| ::File.exist?("#{file}#{ext}") }
    end
  end
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 110
def self.exec_available?(*commands)
  !find_executable(*commands).nil?
end
executables() click to toggle source

List possible executables for output paging

The UNIX systems often come with “pg” and “more” but no “less” utility. The Linux usually provides “less” and “more” pager, but often no “pg”. MacOS comes with “less” and “more” pager and no “pg”. Windows provides “more”. The “more” pager is the oldest utility and thus most compatible with many systems.

@return [Array]

@api private

# File lib/tty/pager/system.rb, line 65
def self.executables
  [ENV["GIT_PAGER"], ENV["PAGER"], git_pager,
   "less -r", "more -r", "most", "pg", "cat", "pager"].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 92
def self.find_executable(*commands)
  execs = commands.empty? ? executables : commands
  execs
    .compact.map(&:strip).reject(&:empty?).uniq
    .find { |cmd| command_exist?(cmd.split.first) }
end
new(command: nil, **options) click to toggle source

Create a system pager

@param [String] :command

the command to use for paging

@api public

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

  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 [Boolean]

true if command runs successfully, false otherwise

@api private

# File lib/tty/pager/system.rb, line 46
def self.run_command(*args)
  _, err, status = Open3.capture3(*args)
  err.empty? && status.success?
rescue Errno::ENOENT
  false
end

Private Class Methods

git_pager() click to toggle source

Finds git pager configuration

@api private

# File lib/tty/pager/system.rb, line 73
def self.git_pager
  command_exist?("git") ? `git config --get-all core.pager` : nil
end

Public Instance Methods

<<(*args)
Alias for: write
close() click to toggle source

Stop the pager, wait for the process to finish. If no pager has been started, returns true.

@return [Boolean]

the exit status of the child process

@api public

# File lib/tty/pager/system.rb, line 173
def close
  return true unless @pager_io

  success = @pager_io.close
  @pager_io = nil
  success
end
puts(text) click to toggle source

Send a line of text, ending in a newline, to the pager process. Starts a new process if it hasn't been started yet.

@raise [PagerClosed]

if the pager was closed

@return [SystemPager]

@api public

# File lib/tty/pager/system.rb, line 160
def puts(text)
  @pager_io ||= spawn_pager
  @pager_io.puts(text)
  self
end
write(*args) click to toggle source

Send text to the pager process. Starts a new process if it hasn't been started yet.

@param [Array<String>] *args

strings to send to the pager

@raise [PagerClosed]

strings to send to the pager

@api public

# File lib/tty/pager/system.rb, line 144
def write(*args)
  @pager_io ||= spawn_pager
  @pager_io.write(*args)
  self
end
Also aliased as: <<

Private Instance Methods

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 189
def pager_command(*commands)
  if @pager_command && commands.empty?
    @pager_command
  else
    @pager_command = self.class.find_executable(*commands)
  end
end
spawn_pager() click to toggle source

Spawn the pager process

@return [PagerIO]

A wrapper for the external pager

@api private

# File lib/tty/pager/system.rb, line 203
def spawn_pager
  # In case there's a previous pager running:
  close

  command = pager_command
  status = self.class.run_command(command)
  # Issue running command, e.g. unsupported flag, fallback to just command
  unless status
    command = pager_command.split.first
  end

  PagerIO.new(command)
end