Created
February 22, 2026 16:06
-
-
Save gphg/b0d4dcbdba078dad531e038a89aabe2f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -- 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