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 153 def self.merge(lower, higher) 154 unless lower && higher 155 return lower || higher 156 end 157 lower.merge(higher) 158 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 165 def self.merge_string_formats(lower, higher) 166 unless lower && higher 167 return lower || higher 168 end 169 170 # drop all formats in lower than is more generic in higher. Lower must never 171 # override higher 172 lower = lower.reject { |lk, _| higher.keys.any? { |hk| hk != lk && hk.assignable?(lk) }} 173 174 merged = (lower.keys + higher.keys).uniq.map do |k| 175 [k, merge(lower[k], higher[k])] 176 end 177 sort_formats(merged) 178 end
# File lib/puppet/pops/types/string_converter.rb 102 def initialize(fmt) 103 @orig_fmt = fmt 104 match = FMT_PATTERN.match(fmt) 105 unless match 106 raise ArgumentError, "The format '#{fmt}' is not a valid format on the form '%<flags><width>.<prec><format>'" 107 end 108 109 @format = match[4] 110 unless @format.is_a?(String) && @format.length == 1 111 raise ArgumentError, "The format must be a one letter format specifier, got '#{@format}'" 112 end 113 @format = @format.to_sym 114 flags = match[1].split('') || [] 115 unless flags.uniq.size == flags.size 116 raise ArgumentError, "The same flag can only be used once, got '#{fmt}'" 117 end 118 @left = flags.include?('-') 119 @alt = flags.include?('#') 120 @plus = (flags.include?(' ') ? :space : (flags.include?('+') ? :plus : :ignore)) 121 @zero_pad = flags.include?('0') 122 123 @delimiters = nil 124 DELIMITERS.each do |d| 125 next unless flags.include?(d) 126 if !@delimiters.nil? 127 raise ArgumentError, "Only one of the delimiters [ { ( < | can be given in the format flags, got '#{fmt}'" 128 end 129 @delimiters = d 130 end 131 132 @width = match[2] ? match[2].to_i : nil 133 @prec = match[3] ? match[3].to_i : nil 134 end
Sorts format based on generality of types - most specific types before general
# File lib/puppet/pops/types/string_converter.rb 182 def self.sort_formats(format_map) 183 format_map = format_map.sort do |(a,_),(b,_)| 184 ab = b.assignable?(a) 185 ba = a.assignable?(b) 186 if a == b 187 0 188 elsif ab && !ba 189 -1 190 elsif !ab && ba 191 1 192 else 193 # arbitrary order if disjunct (based on name of type) 194 rank_a = type_rank(a) 195 rank_b = type_rank(b) 196 if rank_a == 0 || rank_b == 0 197 a.to_s <=> b.to_s 198 else 199 rank_a <=> rank_b 200 end 201 end 202 end 203 Hash[format_map] 204 end
Ranks type on specificity where it matters lower number means more specific
# File lib/puppet/pops/types/string_converter.rb 208 def self.type_rank(t) 209 case t 210 when PStructType 211 1 212 when PHashType 213 2 214 when PTupleType 215 3 216 when PArrayType 217 4 218 when PPatternType 219 10 220 when PEnumType 221 11 222 when PStringType 223 12 224 else 225 0 226 end 227 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 234 def delimiter_pair(default = StringConverter::DEFAULT_ARRAY_DELIMITERS) 235 DELIMITER_MAP[ @delimiters || @plus ] || default 236 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 140 def merge(other) 141 result = Format.new(other.orig_fmt) 142 result.separator = other.separator || separator 143 result.separator2 = other.separator2 || separator2 144 result.container_string_formats = Format.merge_string_formats(container_string_formats, other.container_string_formats) 145 result 146 end
# File lib/puppet/pops/types/string_converter.rb 238 def to_s 239 "%#{@flags}#{@width}.#{@prec}#{@format}" 240 end