(local {: must} (require :lib.utils)) (fn empty? [str] (or (= str nil) (= (# str) 0))) (fn letters [str] (assert (= "string" (type str)) (string.format "letters(): str must be string, %s given" (type str))) (var result []) (for [i 1 (must (luna.utf8.len str))] (table.insert result (must (luna.utf8.sub str i 1)))) result) (fn split [str delimiter] (if (empty? str) [] (do (local result {}) (local len (# str)) (var cursor 1) (var (start end) (str:find delimiter)) (while start (when (< cursor start) (table.insert result (str:sub cursor (- start 1)))) (set cursor (+ end 1)) (set (start end) (str:find delimiter cursor))) (when (<= cursor len) (table.insert result (str:sub cursor len))) result))) (fn ends-with [str end] (= (string.sub str (- (# end))) end)) (fn trim [str pattern] (local pattern (or pattern "%s")) (str:match (.. "^" pattern "*(.-)" pattern "*$"))) (fn truncate [str len ellipsis] (if (and (= (type str) "string") (< 0 (# str))) (if (< (must (luna.utf8.len str)) len) str (.. (trim (must (luna.utf8.sub str 1 len))) (or ellipsis "..."))) "")) (fn insert [str substr pos] (.. (str:sub 1 pos) substr (str:sub (+ 1 pos)))) (fn format-price [price] (var price-str (tostring price)) (local dot-position (price-str:find "%.")) (local price-len (if dot-position (- (pick-values 1 dot-position) 1) (# price-str))) (var cursor (- price-len 3)) (while (< 0 cursor) (set price-str (insert price-str " " cursor)) (set cursor (- cursor 3))) price-str) (fn test-format-price [] (assert (= (format-price 5123450.50689140) "5 123 450.5068914")) (assert (= (format-price 123450.50689140) "123 450.5068914")) (assert (= (format-price 1450.50689140) "1 450.5068914")) (assert (= (format-price 14350) "14 350")) (assert (= (format-price 100) "100")) (assert (= (format-price 0) "0")) (assert (= (format-price 0.5) "0.5"))) {: letters : empty? : split : ends-with : trim : truncate : format-price}