Module: CommandKit::Pager

Includes:
Env, Env::Path, Stdio, Terminal
Defined in:
lib/command_kit/pager.rb

Overview

Allows opening a pager, such as less or more.

Examples

class CLI < CommandKit::Command

  include CommandKit::Pager

  def run
    pager do |io|
      io.puts "This goes into the pager screen"
    end
  end

end

Environment Variables

  • PAGER - The optional command to override the default pager (usually less -r or more -r).
  • PATH - The list of directories to search for the default pager program (either less or more).

Alternatives

Constant Summary collapse

PAGERS =

Common pager commands.

['less -r', 'more -r']

Constants included from Terminal

Terminal::DEFAULT_TERMINAL_HEIGHT, Terminal::DEFAULT_TERMINAL_WIDTH

Instance Attribute Summary

Attributes included from Env

#env

Attributes included from Env::Path

#path_dirs

Instance Method Summary collapse

Methods included from Terminal

#terminal, #terminal?, #terminal_height, #terminal_size, #terminal_width

Methods included from Stdio

#abort, #gets, #print, #printf, #putc, #puts, #readline, #readlines, #stderr, #stdin, #stdout

Methods included from Env::Path

#command_installed?, #find_command

Instance Method Details

#initialize(**kwargs) ⇒ Object

Note:

Respects the PAGER env variable, or attempts to find less or more by searching the PATH env variable.

Initializes the pager.

Parameters:

  • kwargs (Hash{Symbol => Object})

    Keyword arguments.



60
61
62
63
64
65
66
67
68
69
70
# File 'lib/command_kit/pager.rb', line 60

def initialize(**kwargs)
  super(**kwargs)

  @pager_command = env.fetch('PAGER') do
    PAGERS.find do |command|
      bin = command.split(' ',2).first

      command_installed?(bin)
    end
  end
end

#pager {|io| ... } ⇒ Object

Opens a pager pipe.

Examples:

pager do |io|
  io.puts "Hello world"
  # ...
end

Piping a command into the pager:

IO.peopn(["ping", ip]) do |ping|
  pager do |io|
    ping.each_line do |line|
      io.write line
    end
  end
end

Yields:

  • (io)

    The given block will be passed the IO pipe to the pager.

Yield Parameters:

  • The (IO)

    IO pipe to the pager.



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/command_kit/pager.rb', line 98

def pager
  if !stdout.tty? || @pager_command.nil?
    # fallback to stdout if the process does not have a terminal or we could
    # not find a suitable pager command.
    yield stdout
    return
  end

  io  = IO.popen(@pager_command,'w')
  pid = io.pid

  begin
    yield io
  rescue Errno::EPIPE
  ensure
    io.close

    begin
      Process.waitpid(pid)
    rescue Errno::EPIPE, Errno::ECHILD
    end
  end
end

#pipe_to_pager(command, *arguments) ⇒ Boolean

Note:

If multiple arguments are given, they will be shell-escaped and executed as a single command. If a single command is given, it will not be shell-escaped to allow executing compound shell commands.

Pipes a command into the pager.

Examples:

Pipe a single command into the pager:

run_in_pager 'find', '.', '-name', '*.md'

Pipe a compound command into the pager:

run_in_pager "wc -l /path/to/wordlists/*.txt | sort -n"

Parameters:

  • command (#to_s)

    The program or command to run.

  • arguments (Array<#to_s>)

    Additional arguments for the program.

Returns:

  • (Boolean)

    Indicates whether the command exited successfully or not.

Since:

  • 0.2.0



178
179
180
181
182
183
184
185
186
187
188
# File 'lib/command_kit/pager.rb', line 178

def pipe_to_pager(command,*arguments)
  if @pager_command
    unless arguments.empty?
      command = Shellwords.shelljoin([command, *arguments])
    end

    system("#{command} | #{@pager_command}")
  else
    system(command.to_s,*arguments.map(&:to_s))
  end
end

Pages the data if it's longer the terminal's height, otherwise prints the data to stdout.

Examples:

print_or_page(data)

Print or pages the contents of a file:

print_or_page(File.read(file))

Parameters:

  • data (Array<String>, #to_s)

    The data to print.



137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/command_kit/pager.rb', line 137

def print_or_page(data)
  line_count = case data
               when Array  then data.length
               else             data.to_s.each_line.count
               end

  if line_count > terminal_height
    pager { |io| io.puts(data) }
  else
    stdout.puts(data)
  end
end