Perch
Lua APIUtilities

Utilities

perch.log, perch.json, perch.text, perch.hash, perch.base64, perch.uuid and perch.locale. Always granted.

2 min readUpdated Sep 9, 2026

Small synchronous helpers that need no scope.

perch.log

perch.log(message: string): ()

Writes one line to Perch’s log as mod[<id>]: <value>. The value is serialized like any argument: a string appears quoted, a table as JSON. Lines show in the mod’s log window when you run from Perch Studio, and in %APPDATA%\perch\perch\logs\perch.log.

perch.log("refresh")
perch.log({ appid = appid, count = pc.count })

perch.json

perch.json.decode(text: string): any
perch.json.encode(value: any): string

decode returns the decoded value (a table for objects and arrays, else a string, number or boolean), or nil when the text is not valid JSON. A JSON null becomes nil, so a key holding null is absent from the table.

encode returns compact JSON, or nil if the value cannot be represented. An empty table encodes as []; keys 1..n as an array; anything else as an object with its string keys.

perch.net.http.get(url, function(res: http_response_t?, err: string?)
  if not res then return end
  local repo = perch.json.decode(res.body)
  if repo then stars:push({ count = tostring(repo.stargazers_count) }) end
end)

perch.text

perch.text.number(value: number | string, separator: string?): string
perch.text.truncate(text: string, limit: number, ellipsis: string?): string

number groups digits in threes (1436921 becomes "1,436,921"), keeps a decimal part and a sign intact, and takes another separator if you want one.

truncate trims to limit characters, never splitting a multi-byte character, and appends the ellipsis only when it cut something. The ellipsis defaults to a single .

w:push({ count_text = perch.text.number(pc.count), title = perch.text.truncate(title, 24) })

perch.hash

perch.hash.sha256(text: string): string
perch.hash.md5(text: string): string

Hex digests, lowercase. Reach for sha256; md5 is here only because some services still ask for it (a Gravatar URL is the md5 of an email address) and is not safe for anything that must resist tampering.

local url = "https://www.gravatar.com/avatar/" .. perch.hash.md5(email:lower())

perch.base64

perch.base64.encode(text: string): string
perch.base64.decode(text: string): string

Standard base64 with padding: a Basic auth header, a small blob inside JSON, a data URL you build yourself. decode skips whitespace and padding rather than raising.

perch.uuid

perch.uuid.generate(): string

A fresh random (version 4) identifier, "9f1c0e2a-...". For request ids and storage keys that need to be unique rather than meaningful.

perch.locale

perch.locale.read(): locale_t

What this machine prefers. Read it before defaulting a unit or a clock format.

local l = perch.locale.read()
w:push({ temp = if l.celsius then c else f, pill = { off = t.off, h24 = l.hour24 } })

Types

export type locale_t = { language: string, region: string, celsius: boolean, hour24: boolean }
FieldMeaning
languagethe language code, "en"
regionthe region code, "US"
celsiusthe region measures temperature in Celsius
hour24the clock format is 24 hour
esc
Type to search
navigate open