This file is indexed.

/usr/lib/ruby/vendor_ruby/pry/pager.rb is in pry 0.10.3-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
require 'pry/terminal'

# A pager is an `IO`-like object that accepts text and either prints it
# immediately, prints it one page at a time, or streams it to an external
# program to print one page at a time.
class Pry::Pager
  class StopPaging < StandardError
  end

  attr_reader :_pry_

  def initialize(_pry_)
    @_pry_ = _pry_
  end

  # Send the given text through the best available pager (if `Pry.config.pager` is
  # enabled).
  # If you want to send text through in chunks as you generate it, use `open` to
  # get a writable object instead.
  # @param [String] text A piece of text to run through a pager.
  # @param [IO] output (`$stdout`) An object to send output to.
  def page(text)
    open do |pager|
      pager << text
    end
  end

  # Yields a pager object (`NullPager`, `SimplePager`, or `SystemPager`).  All
  # pagers accept output with `#puts`, `#print`, `#write`, and `#<<`.
  # @param [IO] output (`$stdout`) An object to send output to.
  def open
    pager = best_available
    yield pager
  rescue StopPaging
  ensure
    pager.close if pager
  end

  private

  def enabled?; !!@enabled; end

  def output; @output; end

  # Return an instance of the "best" available pager class -- `SystemPager` if
  # possible, `SimplePager` if `SystemPager` isn't available, and `NullPager`
  # if the user has disabled paging. All pagers accept output with `#puts`,
  # `#print`, `#write`, and `#<<`. You must call `#close` when you're done
  # writing output to a pager, and you must rescue `Pry::Pager::StopPaging`.
  # These requirements can be avoided by using `.open` instead.
  # @param [#<<] output ($stdout) An object to send output to.
  def best_available
    if !_pry_.config.pager
      NullPager.new(_pry_.output)
    elsif !SystemPager.available? || Pry::Helpers::BaseHelpers.jruby?
      SimplePager.new(_pry_.output)
    else
      SystemPager.new(_pry_.output)
    end
  end

  # `NullPager` is a "pager" that actually just prints all output as it comes
  # in. Used when `Pry.config.pager` is false.
  class NullPager
    def initialize(out)
      @out = out
    end

    def puts(str)
      print "#{str.chomp}\n"
    end

    def print(str)
      write str
    end
    alias << print

    def write(str)
      @out.write str
    end

    def close
    end

    private

    def height
      @height ||= Pry::Terminal.height!
    end

    def width
      @width ||= Pry::Terminal.width!
    end
  end

  # `SimplePager` is a straightforward pure-Ruby pager. We use it on JRuby and
  # when we can't find a usable external pager.
  class SimplePager < NullPager
    def initialize(*)
      super
      @tracker = PageTracker.new(height - 3, width)
    end

    def write(str)
      str.lines.each do |line|
        @out.print line
        @tracker.record line

        if @tracker.page?
          @out.print "\n"
          @out.print "\e[0m"
          @out.print "<page break> --- Press enter to continue " \
                     "( q<enter> to break ) --- <page break>\n"
          raise StopPaging if Readline.readline("").chomp == "q"
          @tracker.reset
        end
      end
    end
  end

  # `SystemPager` buffers output until we're pretty sure it's at least a page
  # long, then invokes an external pager and starts streaming output to it. If
  # `#close` is called before then, it just prints out the buffered content.
  class SystemPager < NullPager
    def self.default_pager
      pager = ENV["PAGER"] || ""

      # Default to less, and make sure less is being passed the correct options
      if pager.strip.empty? or pager =~ /^less\b/
        pager = "less -R -F -X"
      end

      pager
    end

    def self.available?
      if @system_pager.nil?
        @system_pager = begin
          pager_executable = default_pager.split(' ').first
          `which #{pager_executable}`
          $?.success?
        rescue
          false
        end
      else
        @system_pager
      end
    end

    def initialize(*)
      super
      @tracker = PageTracker.new(height, width)
      @buffer  = ""
    end

    def write(str)
      if invoked_pager?
        write_to_pager str
      else
        @tracker.record str
        @buffer << str

        if @tracker.page?
          write_to_pager @buffer
        end
      end
    rescue Errno::EPIPE
      raise StopPaging
    end

    def close
      if invoked_pager?
        pager.close
      else
        @out.puts @buffer
      end
    end

    private

    def write_to_pager(text)
      pager.write @out.decolorize_maybe(text)
    end

    def invoked_pager?
      @pager
    end

    def pager
      @pager ||= IO.popen(self.class.default_pager, 'w')
    end
  end

  # `PageTracker` tracks output to determine whether it's likely to take up a
  # whole page. This doesn't need to be super precise, but we can use it for
  # `SimplePager` and to avoid invoking the system pager unnecessarily.
  #
  # One simplifying assumption is that we don't need `#page?` to return `true`
  # on the basis of an incomplete line. Long lines should be counted as
  # multiple lines, but we don't have to transition from `false` to `true`
  # until we see a newline.
  class PageTracker
    def initialize(rows, cols)
      @rows, @cols = rows, cols
      reset
    end

    def record(str)
      str.lines.each do |line|
        if line.end_with? "\n"
          @row += ((@col + line_length(line) - 1) / @cols) + 1
          @col  = 0
        else
          @col += line_length(line)
        end
      end
    end

    def page?
      @row >= @rows
    end

    def reset
      @row = 0
      @col = 0
    end

    private

    # Approximation of the printable length of a given line, without the
    # newline and without ANSI color codes.
    def line_length(line)
      line.chomp.gsub(/\e\[[\d;]*m/, '').length
    end
  end
end