textgauge.lua
local TextGauge = {width = 24, fillCharacter = ":", emptyCharacter = "-", showPercent = true, showPercentSymbol = true, format = "c", value = 50}
function TextGauge:new(options)
  options = options or {}
  local optionsType = type(options)
  assert(optionsType == "table" or optionsType == "nil", "TextGauge:new(options): options expected as table, got " .. optionsType)
  local me = table.deepcopy(options)
  setmetatable(me, self)
  self.__index = self
  me:setDefaultColors()
  return me
end
function TextGauge:setWidth(width)
  local widthType = type(width)
  assert(widthType == "number", string.format("TextGauge:setWidth(width): width as number expected, got %s", widthType))
  self.width = width
end
function TextGauge:setFormat(format)
  self.format = self:getColorType(format)
  self:setDefaultColors()
end
function TextGauge:setFillCharacter(character)
  assert(character ~= nil, "TextGauge:setFillCharacter(character): character required, got nil")
  assert(utf8.len(character) == 1, "TextGauge:setFillCharacter(character): character must be a single character")
  self.fillCharacter = character
end
function TextGauge:setOverflowCharacter(character)
  assert(character ~= nil, "TextGauge:setOverflowCharacter(character): character required, got nil")
  assert(utf8.len(character) == 1, "TextGauge:setOverflowCharacter(character): character must be a single character")
  self.overflowCharacter = character
end
function TextGauge:setEmptyCharacter(character)
  assert(character ~= nil, "TextGauge:setEmptyCharacter(character): character required, got nil")
  assert(utf8.len(character) == 1, "TextGauge:setEmptyCharacter(character): character must be a single character")
  self.emptyCharacter = character
end
function TextGauge:setFillColor(color)
  assert(color ~= nil, "TextGauge:setFillColor(color): color required, got nil")
  self.fillColor = color
end
function TextGauge:setOverflowColor(color)
  assert(color ~= nil, "TextGauge:setOverflowColor(color): color required, got nil")
  self.overflowColor = color
end
function TextGauge:setEmptyColor(color)
  assert(color ~= nil, "TextGauge:setEmptyColor(color): color required, got nil")
  self.emptyColor = color
end
function TextGauge:setPercentColor(color)
  assert(color ~= nil, "TextGauge:setPercentColor(color): color required, got nil")
  self.percentColor = color
end
function TextGauge:setPercentSymbolColor(color)
  assert(color ~= nil, "TextGauge:setPercentSymbolColor(color): color required, got nil")
  self.percentSymbolColor = color
end
function TextGauge:enableReverse()
  self.reverse = true
end
function TextGauge:disableReverse()
  self.reverse = false
end
function TextGauge:enableShowPercent()
  self.showPercent = true
end
function TextGauge:disableShowPercent()
  self.showPercent = false
end
function TextGauge:enableShowPercentSymbol()
  self.showPercentSymbol = true
end
function TextGauge:disableShowPercentSymbol()
  self.showPercentSymbol = false
end
function TextGauge:getColorType(format)
  format = format or self.format
  local dec = {"d", "decimal", "dec", "decho"}
  local hex = {"h", "hexidecimal", "hex", "hecho"}
  local col = {"c", "color", "colour", "col", "name", "cecho"}
  if table.contains(col, format) then
    return "c"
  elseif table.contains(dec, format) then
    return "d"
  elseif table.contains(hex, format) then
    return "h"
  else
    return ""
  end
end
function TextGauge:setDefaultColors()
  local colorType = self:getColorType()
  if colorType == "c" then
    self.percentColor = self.percentColor or "white"
    self.percentSymbolColor = self.percentSymbolColor or self.percentColor
    self.fillColor = self.fillColor or "DarkOrange"
    self.emptyColor = self.emptyColor or "white"
    self.resetColor = "<reset>"
  elseif colorType == "d" then
    self.percentColor = self.percentColor or "<255,255,255>"
    self.percentSymbolColor = self.percentSymbolColor or self.percentColor
    self.fillColor = self.fillColor or "<255,140,0>"
    self.emptyColor = self.emptyColor or "<255,255,255>"
    self.resetColor = "<r>"
  elseif colorType == "h" then
    self.percentColor = self.percentColor or "#ffffff"
    self.percentSymbolColor = self.percentSymbolColor or self.percentColor
    self.fillColor = self.fillColor or "#ff8c00"
    self.emptyColor = self.emptyColor or "#ffffff"
    self.resetColor = "#r"
  else
    self.percentColor = self.percentColor or ""
    self.percentSymbolColor = self.percentSymbolColor or self.percentColor
    self.fillColor = self.fillColor or ""
    self.emptyColor = self.emptyColor or ""
    self.resetColor = ""
  end
  self.overflowColor = self.overflowColor or self.fillColor
end
function TextGauge:getColor(color)
  local colorType = self:getColorType()
  if colorType == "c" then
    return string.format("<%s>", color)   elseif colorType == "d" then
    return Geyser.Color.hdec(color)   elseif colorType == "h" then
    return Geyser.Color.hex(color)   else
    return ""   end
end
function TextGauge:setValue(current, max)
  current = current or self.value
  assert(type(current) == "number", "TextGauge:setValue(current,max) current as number expected, got " .. type(current))
  assert(max == nil or type(max) == "number", "TextGauge:setValue(current, max) option max as number expected, got " .. type(max))
  if current < 0 then
    current = 0
  end
  max = max or 100
  local value = math.floor(current / max * 100)
  self.value = value
  local width = self.width
  local percentString = ""
  local percentSymbolString = ""
  local fillCharacter = self.fillCharacter
  local overflowCharacter = self.overflowCharacter or fillCharacter
  local emptyCharacter = self.emptyCharacter
  local fillColor = self:getColor(self.fillColor)
  local overflowColor = self:getColor(self.overflowColor)
  local emptyColor = self:getColor(self.emptyColor)
  local percentColor = self:getColor(self.percentColor)
  local percentSymbolColor = self:getColor(self.percentSymbolColor)
  local resetColor = self.resetColor
  if self.showPercent then
    percentString = string.format("%s%02d%s", percentColor, value, resetColor)
    width = width - 2
  end
  if self.showPercentSymbol then
    percentSymbolString = string.format("%s%s%s", percentSymbolColor, "%", resetColor)
    width = width - 1
  end
  local perc = value / 100
  local overflow = perc - 1
  if overflow < 0 then
    overflow = 0
  end
  if overflow > 1 then
    perc = 2
    overflow = 1
  end
  local overflowWidth = math.floor(overflow * width)
  local fillWidth = math.floor((perc - overflow) * width)
  local emptyWidth = width - fillWidth
  fillWidth = fillWidth - overflowWidth
  if value >= 100 and self.showPercent then
    fillWidth = fillWidth - 1
  end
  if value >= 200 and self.showPercent then
    overflowWidth = overflowWidth - 1
  end
  local result = ""
  if self.reverse then
    result = string.format("%s%s%s%s%s%s%s%s%s%s%s", emptyColor, string.rep(emptyCharacter, emptyWidth), resetColor,fillColor, string.rep(fillCharacter, fillWidth), resetColor, overflowColor, string.rep(overflowCharacter, overflowWidth), resetColor, percentString, percentSymbolString, resetColor)
  else
    result = string.format("%s%s%s%s%s%s%s%s%s%s%s", overflowColor, string.rep(overflowCharacter, overflowWidth), fillColor,
                  string.rep(fillCharacter, fillWidth), resetColor, emptyColor, string.rep(emptyCharacter, emptyWidth), resetColor,
                  percentString, percentSymbolString, resetColor)
  end
  return result
end
function TextGauge:print(...)
  self:setValue(...)
end
return TextGauge