Module: FormatText

Includes:
GetText
Defined in:
lib/fto.rb

Defined Under Namespace

Classes: Context, Effector, FTO

Constant Summary collapse

FillAndJustify =

Handle filling, justifying, and truncating.

lambda {
  | eObj, rText, width, overflowChar |
  overflowChar = '*' if (overflowChar.nil?)
  if ((! width.nil?) && (width.to_s.length != 0))
    width = width.to_i
  else
    width = eObj.dWidth
  end
  return rText if (width.nil?)
  width = width.to_i
  if (rText.length > width)
    case eObj.truncate
    when :right
      rText = rText[0,width]
    when :left
      rText = rText[rText.length - width,width]
    else
      rText = overflowChar * width
    end
  else
    #
    # The result is shorter than the width.  How do we make up the
    # difference?
    #
    fill = eObj.fill * (width - rText.length)
    case eObj.justify
    when :left  then rText += fill
    when :right then rText = fill + rText
    end
  end
  rText
}
GetArgument =

Get the next argument, use the default, or raise an exception.

lambda {
  | eContext |
  if (! eContext.argList.empty?)
    arg = eContext.argList.first
  elsif ((arg = eContext.effectorObj.dValue).nil?)
    raise RuntimeError,
          _('Insufficient arguments to format ') + "'#{eContext.ftoObj}'"
  end
  arg
}
ConvertTBD =

Placeholder effector function.

lambda {
  | eContext |
  eContext.reuseArg = true
  return 'TBD'
}
ConvertFixedWindow =
lambda {
  | eContext |
  eObj = eContext.effectorObj
  parcels = eContext.sMatched.match(Regexp.new(eObj.reExtra))
  width = parcels.captures[0].sub(/</, '').to_i
  #
  # Clone the Context because we want to retain the arglist array
  # identities, but don't want to mess up any of the other aspects
  # needed by our caller.
  #
  f = FTO.new(parcels.captures[1], eContext.clone)
  sNext = f.format
  if ((diff = width - sNext.length) <= 0)
    sNext = sNext[diff.abs,width]
  else
    sNext = (' ' * diff) + sNext
  end
  eContext.reuseArg = true
  sNext
}
ConvertNumeric =

Convert a numeric argument of some sort.

lambda {
  | eContext |
  eObj = eContext.effectorObj
  #
  # This bit of funk is so we can correctly handle a string like
  # '0xABC'.
  #
  thisArg = eval("#{GetArgument.call(eContext)}").to_i & eObj.mask
  #
  # Sign-extend the value if appropriate.
  #
  if ((! eObj.signbit.nil?) && ((thisArg & eObj.signbit) != 0))
    thisArg |= ~ eObj.mask
  end
  #
  # See if we need to convert to a non-decimal base.
  #
  case true
  when eObj.data.include?(:octal) then replacement = thisArg.to_s(8)
  when eObj.data.include?(:hex)   then replacement = thisArg.to_s(16).upcase
  else                                 replacement = thisArg.to_s
  end
  width = eContext.sMatched.match(Regexp.new(eObj.reExtra)).captures[0]
  FillAndJustify.call(eObj, replacement, width, '*')
}
ConvertString =

Insert a string

lambda {
  | eContext |
  eObj = eContext.effectorObj
  if (eObj.data.include?(:lengthAsArg))
    strLen = GetArgument.call(eContext)
    eContext.usedArgs.push(eContext.argList.shift)
  end
  replacement = GetArgument.call(eContext)
  unless (strLen.nil?)
    if (strLen <= replacement.length)
      replacement = replacement[0,strLen]
    else
      replacement += "\000" * (strLen - replacement.length)
    end
  end
  replacement.gsub!(/[^[:print:]]/, '.') if (eObj.data.include?(:printable))
  eObj = eContext.effectorObj
  c = eContext.sMatched.match(Regexp.new(eObj.reExtra)).captures
  if (c.empty? || c[0].empty?)
    return replacement
  end
  FillAndJustify.call(eObj, replacement, c[0].to_i, '*')
}
ConvertRepeatChar =

Insert a repeating character.

lambda {
  | eContext |
  eContext.reuseArg = true
  eObj = eContext.effectorObj
  exInfo = eContext.sMatched.match(Regexp.new(eObj.reExtra))
  width = exInfo.captures[0].to_i
  replacement = exInfo.captures[1] * width
  return replacement
}
ConvertIsAre =
lambda {
  | eContext |
  #
  # We don't actually use the argument list, so we need to make sure
  # the argument pointer doesn't get advanced.
  #
  eContext.reuseArg = true
  result = (eContext.usedArgs.last == 1) ? _('is') : _('are')
  result.upcase! if (eContext.sMatched == '!%IS')
  return result
}
ConvertPlural =
lambda {
  | eContext |
  #
  # We don't actually use the argument list, so we need to make sure
  # the argument pointer doesn't get advanced.
  #
  eContext.reuseArg = true
  m2 = eContext.sMatched.match(Regexp.new(eContext.effectorObj.reExtra))
  return '' if (m2.captures[0].nil?)
  return m2.captures[0] if (eContext.usedArgs.last == 1)
  result = (m2.captures[0].upcase == 'S') ? 'es' : 's'
  result.upcase! if (m2.captures[0].match(/[A-Z]/))
  return m2.captures[0] + result
}