Skip to content

Instantly share code, notes, and snippets.

@gphg
Created February 22, 2026 16:06
Show Gist options
  • Select an option

  • Save gphg/b0d4dcbdba078dad531e038a89aabe2f to your computer and use it in GitHub Desktop.

Select an option

Save gphg/b0d4dcbdba078dad531e038a89aabe2f to your computer and use it in GitHub Desktop.
-- formatter.yue
import global
{:modf, :abs, :floor, :ceil, :log10, :pow} = math
{:insert, :concat} = table
{:format, :gsub, :sub} = string
-- Constants
DOT_NOTATION = "."
COMMA_NOTATION = ","
MINUS_SIGN = "-"
clean_pattern = (s) -> gsub s, "([^%w])", "%%%1"
-- Creates a core formatting function for numbers
make_formatter = (thousand_sep, decimal_point, precision = 0) ->
grouping_pattern = "^(-?%d+)(%d%d%d)"
replacement = "%1#{thousand_sep}%2"
frac_pattern = "%.#{precision}f"
return (n) ->
str_buff = {}
insert(str_buff, MINUS_SIGN) if n < 0
int_part, frac = modf abs n
str_int = tostring int_part
-- Apply thousand separators recursively
while true
str_int, k = gsub str_int, grouping_pattern, replacement
break if k == 0
insert str_buff, str_int
-- Handle fractional digits
if precision > 0
str_frac = format frac_pattern, frac
-- Extract digits after "0."
insert str_buff, decimal_point .. sub str_frac, 3
return concat str_buff
-- Helper for compact number notation (K, M, B, T, etc.)
compact_notation = do
scales = [
{ threshold: 1e12, suffix: "T" } -- Trillion
{ threshold: 1e9, suffix: "B" } -- Billion
{ threshold: 1e6, suffix: "M" } -- Million
{ threshold: 1e3, suffix: "K" } -- Thousand
]
(n, precision = 1) ->
abs_n = abs n
sign = if n < 0 then MINUS_SIGN else ""
for scale in *scales
if abs_n >= scale.threshold
scaled = abs_n / scale.threshold
int_part, frac = modf scaled
if precision > 0
frac_pattern = "%.#{precision}f"
str_val = format frac_pattern, scaled
return format "%s%s%s", sign, str_val, scale.suffix
else
return format "%s%d%s", sign, int_part, scale.suffix
return format "%s%d", sign, floor(abs_n)
-- Base styles available for use
style_map =
comma: make_formatter COMMA_NOTATION, DOT_NOTATION
dot: make_formatter DOT_NOTATION, COMMA_NOTATION
none: (n) ->
int, _ = modf n
return format "%d", int
-- compact notation (Balatro style)
compact: (n) -> compact_notation n, 1
compact_precise: (n) -> compact_notation n, 2
-- memory notation (accepts KB, returns MB or GB)
memory_mb: (n) =>
-- Convert KB to MB immediately
mb = ceil n / 1024
if mb >= 1024
gb = mb / 1024
return format "%.2f GB", gb
return format "%d MB", mb
-- score with compact notation
score_compact: (n) ->
sign = if n < 0 then MINUS_SIGN else ""
return format "%s%s", sign, sub(compact_notation(abs n, 2), 1)
-- health bar representation (0-100)
health_percent: (n) ->
clamped = if n < 0 then 0 elseif n > 100 then 100 else n
return format "%.0f%%", clamped
-- time format (HH:MM:SS)
time_detailed: (t) ->
sign = if t < 0 then MINUS_SIGN else ""
t_abs = floor abs t
hours = floor t_abs / 3600
minutes = floor (t_abs % 3600) / 60
seconds = t_abs % 60
return format "%s%02d:%02d:%02d", sign, hours, minutes, seconds
-- frames per second
fps: (n) -> format "%d FPS", n
-- damage/stat notation with symbol
damage: (n) ->
sign = if n < 0 then MINUS_SIGN else "+"
return format "%s%s DMG", sign, sub(compact_notation(abs n, 1), 1)
-- percentage with precision
percent: (n) ->
return format "%.1f%%", n
-- Time format for speedrun (MM:SS.ms)
time: (t) ->
sign = if t < 0 then "-" else ""
t_abs = floor abs t
minutes = floor t_abs / 60
seconds = t_abs % 60
return format "%s%d:%02d", sign, minutes, seconds
-- dynamic scientific notation
scientific: (n) =>
abs_n = abs n
if abs_n < 1e15
return compact_notation n, 1
-- Use standard math.log10 to find the exponent
exponent = floor log10 abs_n
mantissa = abs_n / pow 10, exponent
sign = if n < 0 then MINUS_SIGN else ""
return format "%s%.2fe%d", sign, mantissa, exponent
-- hex representation (useful for bitwise or memory debugging)
hex: (n) ->
return format "0x%X", floor n
-- Logic to determine which formatter to use
get_formatter = (style, precision) ->
if target_fmt := style_map[style]
p = tonumber(precision) or 0
-- If precision is requested for notation, we must create a new one
if p > 0 and (style == "comma" or style == "dot")
t_sep = if style == "dot" then DOT_NOTATION else COMMA_NOTATION
d_sep = if style == "dot" then COMMA_NOTATION else DOT_NOTATION
return make_formatter t_sep, d_sep, p
return target_fmt
return tostring
-- Tracking health with weak table for debugging
created_closures = setmetatable {}, {__mode: "k"}
-- API to check closure state
export status = (fn) -> created_closures[fn] or "invalid"
-- The Factory
export create = (style = "none", precision = 0, limit = 16384) ->
p_num = tonumber(precision) or 0
limit_num = tonumber(limit) or 999
cache = {}
count = 0
shift = 10 ^ p_num
-- Assign formatter based on input type
formatter = if type(style) == "function"
style
else
get_formatter style, p_num
-- The actual memoized function
fn = (n) ->
if n == nil then return ""
if type(n) != "number" then return tostring n
-- Rounding Away From Zero (Commercial Rounding)
temp = n * shift
rounded = (if temp >= 0 then floor(temp + 0.5) else ceil(temp - 0.5)) / shift
-- Cache hit
if val := cache[rounded]
return val
-- Cache miss
formatted = formatter rounded
-- Limit enforcement
if count > limit_num
created_closures[fn] = "full"
return formatted
cache[rounded] = formatted
count += 1
return formatted
created_closures[fn] = "alive"
return fn
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment