89 lines
4 KiB
Text
89 lines
4 KiB
Text
# keys.ludic - a key as the game carries it: the compiler's Key (k"..." is its text behind byte 1, kn"..."
|
|
# behind byte 2), made into a string with holes as byte 31 then each argument, a plural's count first.
|
|
# Nothing here needs the language: the text is made where it is drawn (L), never taking I18nState.
|
|
export const I18N_KEY: int = 1 # k"pause.resume" is "\\x01pause.resume"
|
|
export const I18N_PLURAL: int = 2 # kn"catch.count": a count chooses the form
|
|
export const I18N_SEP: int = 31 # between the key and each argument
|
|
export const I18N_ESC: int = 27 # inside an argument, before a 27 or a 31 of its own (a key with its own holes)
|
|
|
|
# is this a key (or a key with its arguments), rather than English
|
|
export function i18n_is_key(s: string) -> bool { return len(s) > 0 and (s[0] == I18N_KEY or s[0] == I18N_PLURAL) }
|
|
|
|
# a key named at run time (a test, a table's own key): "pause.resume" marked
|
|
@alloc_ok("a key made from its name: a test's, or a table's once")
|
|
export function i18n_key(name: string) -> string { return kx_join(I18N_KEY, name, "", "", "", "", 0) }
|
|
@alloc_ok("a plural key made from its name: a test's")
|
|
export function i18n_key_plural(name: string) -> string { return kx_join(I18N_PLURAL, name, "", "", "", "", 0) }
|
|
|
|
# the key's name without its marker ("pause.resume"), or the string as it is
|
|
@alloc_ok("a key's name: a slice of text already made, kept by whoever holds the key")
|
|
export function key_text(k: string) -> string {
|
|
if not i18n_is_key(k) { return k }
|
|
var e = 1
|
|
while e < len(k) and k[e] != I18N_SEP { e += 1 }
|
|
return k[1..e]
|
|
}
|
|
|
|
# the text of a key: drawn translated where it is drawn (its marked text, a free cast)
|
|
@alloc_ok("a cast: the key's own marked text, nothing is made")
|
|
export function tr(k: Key) -> string { return string(k) }
|
|
# a key's text with its holes, {1} .. {4}, filled by strings already made (a number, a name, another key)
|
|
@alloc_ok("a line with its holes, made when something happens and kept by what shows it")
|
|
export function trf(k: Key, a: string, b: string, c: string, d: string) -> string {
|
|
let s = string(k)
|
|
return kx_join(I18N_KEY, key_text(s), a, b, c, d, kx_count(a, b, c, d))
|
|
}
|
|
# a plural key's text by n: the count is {1}, a .. c are {2} .. {4}
|
|
@alloc_ok("a count's line, made when something happens and kept by what shows it")
|
|
export function trn(k: Key, n: int, a: string, b: string, c: string) -> string { return kx_join(I18N_PLURAL, key_text(string(k)), `{n}`, a, b, c, 1 + kx_count(a, b, c, "")) }
|
|
|
|
function kx_count(a: string, b: string, c: string, d: string) -> int {
|
|
if len(d) > 0 { return 4 }
|
|
if len(c) > 0 { return 3 }
|
|
if len(b) > 0 { return 2 }
|
|
if len(a) > 0 { return 1 }
|
|
return 0
|
|
}
|
|
|
|
# the marker, the name, then each of the first `n` arguments after a byte 31
|
|
function kx_join(mark: int, name: string, a: string, b: string, c: string, d: string, n: int) -> string {
|
|
var size = 1 + len(name)
|
|
if n > 0 { size += 1 + kx_len(a) }
|
|
if n > 1 { size += 1 + kx_len(b) }
|
|
if n > 2 { size += 1 + kx_len(c) }
|
|
if n > 3 { size += 1 + kx_len(d) }
|
|
let buf = buffer(size)
|
|
buf[0] = mark
|
|
var at = kx_put(buf, 1, name)
|
|
if n > 0 { at = kx_arg(buf, kx_sep(buf, at), a) }
|
|
if n > 1 { at = kx_arg(buf, kx_sep(buf, at), b) }
|
|
if n > 2 { at = kx_arg(buf, kx_sep(buf, at), c) }
|
|
if n > 3 { at = kx_arg(buf, kx_sep(buf, at), d) }
|
|
return text_of(buf, size)
|
|
}
|
|
function kx_sep(buf: []byte, at: int) -> int {
|
|
buf[at] = I18N_SEP
|
|
return at + 1
|
|
}
|
|
# an argument's bytes, a 27 before each 27 or 31 of its own, so a key with holes can be one
|
|
function kx_len(s: string) -> int {
|
|
var n = len(s)
|
|
for i in 0 .. len(s) { if s[i] == I18N_SEP or s[i] == I18N_ESC { n += 1 } }
|
|
return n
|
|
}
|
|
function kx_arg(buf: []byte, at: int, s: string) -> int {
|
|
var j = at
|
|
for i in 0 .. len(s) {
|
|
if s[i] == I18N_SEP or s[i] == I18N_ESC {
|
|
buf[j] = I18N_ESC
|
|
j += 1
|
|
}
|
|
buf[j] = s[i]
|
|
j += 1
|
|
}
|
|
return j
|
|
}
|
|
function kx_put(buf: []byte, at: int, s: string) -> int {
|
|
for i in 0 .. len(s) { buf[at + i] = s[i] }
|
|
return at + len(s)
|
|
}
|