class Puppet::Pops::Types::StringConverter::Format
Format represents one format specification that is textually represented by %<flags><width>.<precision><format> Format parses and makes the individual parts available when an instance is created.
@api private
Constants
- DELIMITERS
- DELIMITER_MAP
- FMT_PATTERN
- FMT_PATTERN_STR
Attributes
Boolean, alternate form (varies in meaning)
Boolean, alternate form (varies in meaning)
Map of type to format for elements contained in an object this format applies to
Delimiters for containers, a “left” char representing the pair <[{(
One char symbol denoting the format
Boolean, left adjust in given width or not
Symbol, :space, :plus, :ignore
Nil or Integer precisions
Separator string inserted between elements in a container
Separator string inserted between sub elements in a container
Nil or Integer with width of field > 0
Boolean left_pad with zero instead of space
Public Class Methods
Merges two formats where the `higher` format overrides the `lower`. Produces a new `Format` @param [Format] lower @param [Format] higher @returns [Format] the merged result
# File lib/puppet/pops/types/string_converter.rb 154 def self.merge(lower, higher) 155 unless lower && higher 156 return lower || higher 157 end 158 lower.merge(higher) 159 end
Merges a type => format association and returns a new merged and sorted association. @param [Format] lower @param [Format] higher @returns [Hash] the merged type => format result
# File lib/puppet/pops/types/string_converter.rb 166 def self.merge_string_formats(lower, higher) 167 unless lower && higher 168 return lower || higher 169 end 170 171 # drop all formats in lower than is more generic in higher. Lower must never 172 # override higher 173 lower = lower.reject { |lk, _| higher.keys.any? { |hk| hk != lk && hk.assignable?(lk) }} 174 175 merged = (lower.keys + higher.keys).uniq.map do |k| 176 [k, merge(lower[k], higher[k])] 177 end 178 sort_formats(merged) 179 end
# File lib/puppet/pops/types/string_converter.rb 103 def initialize(fmt) 104 @orig_fmt = fmt 105 match = FMT_PATTERN.match(fmt) 106 unless match 107 raise ArgumentError, "The format '#{fmt}' is not a valid format on the form '%<flags><width>.<prec><format>'" 108 end 109 110 @format = match[4] 111 unless @format.is_a?(String) && @format.length == 1 112 raise ArgumentError, "The format must be a one letter format specifier, got '#{@format}'" 113 end 114 @format = @format.to_sym 115 flags = match[1].split('') || [] 116 unless flags.uniq.size == flags.size 117 raise ArgumentError, "The same flag can only be used once, got '#{fmt}'" 118 end 119 @left = flags.include?('-') 120 @alt = flags.include?('#') 121 @plus = (flags.include?(' ') ? :space : (flags.include?('+') ? :plus : :ignore)) 122 @zero_pad = flags.include?('0') 123 124 @delimiters = nil 125 DELIMITERS.each do |d| 126 next unless flags.include?(d) 127 if !@delimiters.nil? 128 raise ArgumentError, "Only one of the delimiters [ { ( < | can be given in the format flags, got '#{fmt}'" 129 end 130 @delimiters = d 131 end 132 133 @width = match[2] ? match[2].to_i : nil 134 @prec = match[3] ? match[3].to_i : nil 135 end
Sorts format based on generality of types - most specific types before general
# File lib/puppet/pops/types/string_converter.rb 183 def self.sort_formats(format_map) 184 format_map = format_map.sort do |(a,_),(b,_)| 185 ab = b.assignable?(a) 186 ba = a.assignable?(b) 187 if a == b 188 0 189 elsif ab && !ba 190 -1 191 elsif !ab && ba 192 1 193 else 194 # arbitrary order if disjunct (based on name of type) 195 rank_a = type_rank(a) 196 rank_b = type_rank(b) 197 if rank_a == 0 || rank_b == 0 198 a.to_s <=> b.to_s 199 else 200 rank_a <=> rank_b 201 end 202 end 203 end 204 Hash[format_map] 205 end
Ranks type on specificity where it matters lower number means more specific
# File lib/puppet/pops/types/string_converter.rb 209 def self.type_rank(t) 210 case t 211 when PStructType 212 1 213 when PHashType 214 2 215 when PTupleType 216 3 217 when PArrayType 218 4 219 when PPatternType 220 10 221 when PEnumType 222 11 223 when PStringType 224 12 225 else 226 0 227 end 228 end
Public Instance Methods
Returns an array with a delimiter pair derived from the format. If format does not contain a delimiter specification the given default is returned
@param [Array<String>] the default delimiters @returns [Array<String>] a tuple with left, right delimiters
# File lib/puppet/pops/types/string_converter.rb 235 def delimiter_pair(default = StringConverter::DEFAULT_ARRAY_DELIMITERS) 236 DELIMITER_MAP[ @delimiters || @plus ] || default 237 end
Merges one format into this and returns a new `Format`. The `other` format overrides this. @param [Format] other @returns [Format] a merged format
# File lib/puppet/pops/types/string_converter.rb 141 def merge(other) 142 result = Format.new(other.orig_fmt) 143 result.separator = other.separator || separator 144 result.separator2 = other.separator2 || separator2 145 result.container_string_formats = Format.merge_string_formats(container_string_formats, other.container_string_formats) 146 result 147 end
# File lib/puppet/pops/types/string_converter.rb 239 def to_s 240 "%#{@flags}#{@width}.#{@prec}#{@format}" 241 end