class TTY::Prompt::Paginator

Constants

DEFAULT_PAGE_SIZE

Attributes

current_index[R]

The 0-based index of the active item on this page

end_index[R]

The 0-based index of the last item on this page

last_index[R]

The 0-based index of the previously active item on this page

start_index[RW]

The 0-based index of the first item on this page

Public Class Methods

new(**options) click to toggle source

Create a Paginator

@api private

# File lib/tty/prompt/paginator.rb, line 23
def initialize(**options)
  @last_index  = Array(options[:default]).flatten.first || 0
  @per_page    = options[:per_page]
  @start_index = Array(options[:default]).flatten.first
end

Public Instance Methods

check_page_size!() click to toggle source

Check if page size is valid

@raise [InvalidArgument]

@api private

# File lib/tty/prompt/paginator.rb, line 42
def check_page_size!
  raise InvalidArgument, "per_page must be > 0" if @per_page < 1
end
paginate(list, active, per_page = nil, &block) click to toggle source

Paginate collection given an active index

@param [Array] list

a collection of choice items

@param [Integer] active

current choice active index

@param [Integer] per_page

number of choice items per page

@return [Enumerable]

the list between start and end index

@api public

# File lib/tty/prompt/paginator.rb, line 59
def paginate(list, active, per_page = nil, &block)
  current_index = active - 1
  default_size = (list.size <= DEFAULT_PAGE_SIZE ? list.size : DEFAULT_PAGE_SIZE)
  @per_page = @per_page || per_page || default_size
  check_page_size!
  @start_index ||= (current_index / @per_page) * @per_page
  @end_index ||= @start_index + @per_page - 1

  # Don't paginate short lists
  if list.size <= @per_page
    @start_index = 0
    @end_index = list.size - 1
    if block
      return list.each_with_index(&block)
    else
      return list.each_with_index.to_enum
    end
  end

  step = (current_index - @last_index).abs
  if current_index > @last_index # going up
    if current_index >= @end_index && current_index < list.size - 1
      last_page = list.size - @per_page
      @start_index = [@start_index + step, last_page].min
    end
  elsif current_index < @last_index # going down
    if current_index <= @start_index && current_index > 0
      @start_index = [@start_index - step, 0].max
    end
  end

  # Cycle list
  if current_index.zero?
    @start_index = 0
  elsif current_index == list.size - 1
    @start_index = list.size - 1 - (@per_page - 1)
  end

  @end_index = @start_index + (@per_page - 1)
  @last_index = current_index

  sliced_list = list[@start_index..@end_index]
  page_range = (@start_index..@end_index)

  return sliced_list.zip(page_range).to_enum unless block_given?

  sliced_list.each_with_index do |item, index|
    block[item, @start_index + index]
  end
end
reset!() click to toggle source

Reset current page indexes

@api private

# File lib/tty/prompt/paginator.rb, line 32
def reset!
  @start_index = nil
  @end_index   = nil
end