lib/tty/prompt/choices.rb
# frozen_string_literal: true
require "forwardable"
require_relative "choice"
module TTY
class Prompt
# A class responsible for storing a collection of choices
#
# @api private
class Choices
include Enumerable
extend Forwardable
def_delegators :choices, :length, :size, :to_ary, :empty?,
:values_at, :index, :==
# Convenience for creating choices
#
# @param [Array[Object]] choices
# the choice objects
#
# @return [Choices]
# the choices collection
#
# @api public
def self.[](*choices)
new(choices)
end
# Create Choices collection
#
# @param [Array[Choice]] choices
# the choices to add to collection
#
# @api public
def initialize(choices = [])
@choices = choices.map do |choice|
Choice.from(choice)
end
end
# Scope of choices which are not disabled
#
# @api public
def enabled
reject(&:disabled?)
end
def enabled_indexes
each_with_index.reduce([]) do |acc, (choice, idx)|
acc << idx unless choice.disabled?
acc
end
end
# Iterate over all choices in the collection
#
# @yield [Choice]
#
# @api public
def each(&block)
return to_enum unless block_given?
choices.each(&block)
end
# Add choice to collection
#
# @param [Object] choice
# the choice to add
#
# @api public
def <<(choice)
choices << Choice.from(choice)
end
# Access choice by index
#
# @param [Integer] index
#
# @return [Choice]
#
# @api public
def [](index)
@choices[index]
end
# Pluck a choice by its name from collection
#
# @param [String] name
# the label name for the choice
#
# @return [Choice]
#
# @api public
def pluck(name)
map { |choice| choice.public_send(name) }
end
# Find a matching choice
#
# @example
# choices.find_by(:name, "small")
#
# @param [Symbol] attr
# the attribute name
# @param [Object] value
#
# @return [Choice]
#
# @api public
def find_by(attr, value)
find { |choice| choice.public_send(attr) == value }
end
protected
# The actual collection choices
#
# @return [Array[Choice]]
#
# @api private
attr_reader :choices
end # Choices
end # Prompt
end # TTY