# frozen_string_literal: true module MakeMenu # A set of FIELDS to display above the menu class FieldSet def initialize @fields = [] @max_widths = {} end # Add a new field to the set # @param [String] label Optional label to print to the left of the field value # @param [String,Symbol] value_from_file If set, read the field value from a file # in the current directory. A String is used literally, a Symbol is assumed # to be a hidden file (i.e. starts with `.`) # @param [String,Symbol,Integer] color Formatting to apply to the value # @param [String] none Text to display if the file does not exist, or is empty # @param [Proc] block Block to return the value to display def add(label = '', value_from_file: nil, color: :normal, none: '[none]'.dark, &block) if value_from_file if value_from_file.is_a? Symbol value_from_file = ".#{value_from_file}" end block = lambda do if File.exist? value_from_file value = File.read(value_from_file).strip return none if value.empty? return value.color(color) else return none end end end @fields << { label: label, handler: block } end # Print fields in an aligned vertical stack def display build @fields.each do |field| label_cell = field[:label] .align( :right, width: @max_widths[:label] ) value_cel = field[:value] .align( :left, width: @max_widths[:value], pad_right: true ) puts "#{label_cell}#{value_cel}".align(:center) end puts end private # Calculate maximum sizes of labels and rendered values def build @max_widths[:label] = 0 @max_widths[:value] = 0 @fields.each do |field| label = field[:label] value = field[:value] = field[:handler].call label_width = label.decolor.size value_width = value.decolor.size @max_widths[:label] = label_width if label_width > @max_widths[:label] @max_widths[:value] = value_width if value_width > @max_widths[:value] end end end end