L
ling-miao
↓ 0 ダウンロードmiao: a Ling-native version control system — temples, souls, rites and talismans instead of repos, branches, commits and tags; adaptive whole/delta/chunk storage; SSH temple fairs for sharing; a LingStationX-themed GUI; ROYGBIV everywhere
キーワード vcs, version-control, git, miao, ling
lingfu install ling-miaoコード / ファイル (268)
ling/gui.ling
# ━━━ gui.ling — LingMiao 灵庙: the temple window, in the LingStationX look ━━━
# Chrome and widgets come from theme.ling / core.ling / ds.ling / icons.ling
# (the LingDev design system). The repo logic is the same store/rites code
# the CLI uses; the GUI narrates its ceremonies to the terminal it was
# launched from. fns prefixed gx_.
use "theme.ling"
use "core.ling"
use "ds.ling"
use "icons.ling"
# core.ling's text_size_set calls this; the CLI has nothing to save.
fn settings_save() { return 0.0 }
# ── data refresh ──────────────────────────────────────────────────────
fn gx_refresh() {
bind d = rt_status_data()
bind rows_p = list_new()
bind rows_k = list_new()
bind sp = list_get(d, 0.0)
bind ss = list_get(d, 1.0)
bind i = 0.0
while i < len(sp) {
bind rows_p = list_push(rows_p, list_get(sp, i))
bind rows_k = list_push(rows_k, "altar:" + list_get(ss, i))
bind i = i + 1.0
}
bind rp = list_get(d, 2.0)
bind rs = list_get(d, 3.0)
bind i = 0.0
while i < len(rp) {
bind rows_p = list_push(rows_p, list_get(rp, i))
bind rows_k = list_push(rows_k, "restless:" + list_get(rs, i))
bind i = i + 1.0
}
bind wander = list_get(d, 4.0)
bind i = 0.0
while i < len(wander) {
bind rows_p = list_push(rows_p, list_get(wander, i))
bind rows_k = list_push(rows_k, "wander:new")
bind i = i + 1.0
}
st_set("gx_rows_p", rows_p)
st_set("gx_rows_k", rows_k)
st_set("gx_diff_for", "")
# lineage
bind tips = list_new()
bind souls = sx_souls()
bind i = 0.0
while i < len(souls) {
bind t = sx_tip(list_get(souls, i))
if t != "" {
if ut_contains(tips, t) == false { bind tips = list_push(tips, t) }
}
bind i = i + 1.0
}
bind seen = list_new()
bind queue = tips
bind qi = 0.0
while qi < len(queue) {
bind id = list_get(queue, qi)
if ut_contains(seen, id) == false {
bind seen = list_push(seen, id)
bind r = sx_rite_read(id)
bind ps = list_get(r, 1.0)
bind k = 0.0
while k < len(ps) {
bind queue = list_push(queue, list_get(ps, k))
bind k = k + 1.0
}
}
bind qi = qi + 1.0
}
# order by time, newest first (insertion sort on small n)
bind ord = list_new()
bind times = list_new()
bind i = 0.0
while i < len(seen) {
bind r = sx_rite_read(list_get(seen, i))
bind t = list_get(r, 3.0)
bind at = 0.0
bind go = true
while go {
if at >= len(ord) {
bind go = false
} else if list_get(times, at) < t {
bind go = false
} else {
bind at = at + 1.0
}
}
# insert at position `at`
bind no = list_new()
bind nt = list_new()
bind q = 0.0
while q < at {
bind no = list_push(no, list_get(ord, q))
bind nt = list_push(nt, list_get(times, q))
bind q = q + 1.0
}
bind no = list_push(no, list_get(seen, i))
bind nt = list_push(nt, t)
while q < len(ord) {
bind no = list_push(no, list_get(ord, q))
bind nt = list_push(nt, list_get(times, q))
bind q = q + 1.0
}
bind ord = no
bind times = nt
bind i = i + 1.0
}
st_set("gx_rites", ord)
st_set("gx_flashT", 0.0)
return 0.0
}
fn gx_flash(msg) {
st_set("gx_flash", msg)
st_set("gx_flashT", time_now())
return 0.0
}
# ── diff cache for the selected file ──────────────────────────────────
fn gx_make_diff(p, kind) {
bind head = sx_rite_manifest(sx_head_rite())
bind a = sx_altar()
bind oid = ""
bind at = ut_index_of(list_get(a, 1.0), p)
if at >= 0.0 { bind oid = list_get(list_get(a, 0.0), at) }
if oid == "" || oid == "-" {
bind hat = ut_index_of(list_get(head, 1.0), p)
if hat >= 0.0 { bind oid = list_get(list_get(head, 0.0), hat) }
}
bind old_txt = ""
if oid != "" {
if oid != "-" {
if rt_is_bin_spirit(oid) {
st_set("gx_dk", ["h"])
st_set("gx_dt", ["binary spirit — no yinyang to read"])
st_set("gx_diff_for", p)
return 0.0
}
bind old_txt = rt_spirit_text_or(oid)
}
}
bind new_txt = ""
if file_exists(sx_root() + "/" + p) {
bind new_txt = rt_worktree_text(p)
if new_txt == "" {
bind hr = file_read_hex(sx_root() + "/" + p)
if ut_is_bad(hr) == false {
if len(hr.unwrap()) > 0.0 {
st_set("gx_dk", ["h"])
st_set("gx_dt", ["binary spirit — no yinyang to read"])
st_set("gx_diff_for", p)
return 0.0
}
}
}
}
bind la = split(old_txt, "\n")
bind lb = split(new_txt, "\n")
bind ops = dy_ops(la, lb)
bind dk = list_new()
bind dt = list_new()
bind apos = 0.0
bind bpos = 0.0
bind k = 0.0
while k < len(ops) {
bind kind2 = list_get(ops, k)
bind n = list_get(ops, k + 1.0)
if kind2 == "=" {
bind lead = min(3.0, n)
bind tail = min(3.0, n - lead)
bind q = 0.0
while q < lead {
bind dk = list_push(dk, "c")
bind dt = list_push(dt, " " + list_get(la, apos + q))
bind q = q + 1.0
}
if n > 6.0 {
bind dk = list_push(dk, "h")
bind dt = list_push(dt, " ⋯ " + (n - 6.0) + " serene lines ⋯")
}
bind q = n - tail
while q < n {
bind dk = list_push(dk, "c")
bind dt = list_push(dt, " " + list_get(la, apos + q))
bind q = q + 1.0
}
bind apos = apos + n
bind bpos = bpos + n
} else if kind2 == "-" {
bind q = 0.0
while q < n {
bind dk = list_push(dk, "-")
bind dt = list_push(dt, "− " + list_get(la, apos + q))
bind q = q + 1.0
}
bind apos = apos + n
} else {
bind q = 0.0
while q < n {
bind dk = list_push(dk, "+")
bind dt = list_push(dt, "+ " + list_get(lb, bpos + q))
bind q = q + 1.0
}
bind bpos = bpos + n
}
bind k = k + 2.0
}
st_set("gx_dk", dk)
st_set("gx_dt", dt)
st_set("gx_diff_for", p)
return 0.0
}
# a rite's aura: 7 tiles colored by its leading hex digits
fn gx_aura(x, y, id) {
bind i = 0.0
while i < 7.0 {
bind c = hex_to_number(str_slice(id, i, 1.0))
g_rrect(x + i * 10.0, y, 8.0, 8.0, 2.0, c_pal(c))
bind i = i + 1.0
}
return 0.0
}
fn gx_row_col(k) {
if str_starts_with(k, "altar:") { return C_YELLOW }
if str_starts_with(k, "restless:") { return C_ORANGE }
return C_VIOLET
}
fn gx_row_tag(k) {
if k == "altar:new" { return "new on altar" }
if k == "altar:gone" { return "release staged" }
if str_starts_with(k, "altar:") { return "on the altar" }
if k == "restless:gone" { return "departed" }
if str_starts_with(k, "restless:") { return "restless" }
return "wandering"
}
# ── tab 0: divine (status / offer / rite) ─────────────────────────────
fn gx_tab_divine(W, H) {
bind top = TABS_H
bind bot = H - STATUS_H - 44.0
bind lw = 330.0
# left: the spirits
g_rect(0.0, top, lw, bot - top, C_BG_SIDE)
u_vsep(lw - 1.0, top, bot - top)
ds_word(10.0, top + 8.0, 9.0, "SPIRITS", ds_col("call"), true)
if u_button("gx_offer_all", lw - 150.0, top + 4.0, 68.0, 20.0, "offer all", 0.0) {
rt_offer(["."])
gx_refresh()
gx_flash("every spirit placed on the altar")
}
if u_button("gx_refresh", lw - 76.0, top + 4.0, 66.0, 20.0, "divine", 0.0) {
gx_refresh()
gx_flash("the oracle has been consulted")
}
u_hsep(6.0, top + 30.0, lw - 12.0)
bind rows_p = st_get("gx_rows_p", [])
bind rows_k = st_get("gx_rows_k", [])
bind n = len(rows_p)
bind ltop = top + 36.0
bind lh = bot - ltop - 4.0
bind rh = 22.0
bind off = u_scroll_y("gx_sc0", 0.0, ltop, lw - 1.0, lh, n * rh + 8.0, st_get("gx_off0", 0.0))
st_set("gx_off0", off)
u_clip(0.0, ltop, lw - 1.0, lh)
bind sel_p = st_get("gx_sel", "")
bind i = 0.0
while i < n {
bind ry = ltop + 4.0 + i * rh - off
if ry + rh >= ltop && ry <= ltop + lh {
bind p = list_get(rows_p, i)
bind k = list_get(rows_k, i)
bind hot = u_hot(0.0, ry, lw - 14.0, rh)
if sel_p == p { g_rect(0.0, ry, lw - 1.0, rh, C_SEL_ROW) }
else if hot { g_rect(0.0, ry, lw - 1.0, rh, C_HOVER_ROW) }
g_rrect(8.0, ry + 6.0, 10.0, 10.0, 2.0, gx_row_col(k))
g_text_fit(26.0, ry + 5.0, lw - 140.0, 12.0, sel(sel_p == p, C_TEXT_STRONG, C_TEXT), p)
g_text_r(lw - 16.0, ry + 6.0, 10.0, C_TEXT_DIM, gx_row_tag(k))
if hot && u_pressed() {
st_set("gx_sel", p)
gx_make_diff(p, k)
}
if hot && u_double() {
if str_starts_with(k, "altar:") {
rt_withdraw([p])
} else {
rt_offer_one(p)
}
gx_refresh()
}
}
bind i = i + 1.0
}
if n < 0.5 {
g_text_c(lw * 0.5, ltop + 30.0, 12.0, C_TEXT_DIM, "the temple is serene")
}
u_unclip()
# right: the yinyang of the selected spirit
bind rx = lw + 8.0
bind rw = W - rx - 8.0
ds_frame(rx, top + 6.0, rw, bot - top - 12.0, ds_col("ink"), "YINYANG")
if sel_p != "" {
if st_get("gx_diff_for", "") != sel_p { gx_make_diff(sel_p, "") }
# per-row buttons
if u_button("gx_b_offer", rx + rw - 240.0, top + 12.0, 70.0, 20.0, "offer", C_YELLOW) {
rt_offer_one(sel_p)
gx_refresh()
gx_flash(sel_p + " placed on the altar")
}
if u_button("gx_b_withdraw", rx + rw - 164.0, top + 12.0, 78.0, 20.0, "withdraw", 0.0) {
rt_withdraw([sel_p])
gx_refresh()
}
if u_button("gx_b_restore", rx + rw - 80.0, top + 12.0, 70.0, 20.0, "restore", C_RED) {
rt_restore([sel_p])
gx_refresh()
gx_flash(sel_p + " returned to its enshrined form")
}
g_text_fit(rx + 14.0, top + 14.0, rw - 260.0, 12.0, C_TEXT_STRONG, sel_p)
bind dk = st_get("gx_dk", [])
bind dt = st_get("gx_dt", [])
bind dn = len(dk)
bind dtop = top + 40.0
bind dh = bot - dtop - 14.0
bind drh = 16.0
bind doff = u_scroll_y("gx_sc0d", rx + 4.0, dtop, rw - 8.0, dh, dn * drh + 8.0, st_get("gx_offd", 0.0))
st_set("gx_offd", doff)
u_clip(rx + 4.0, dtop, rw - 8.0, dh)
bind i = 0.0
while i < dn {
bind ry = dtop + 2.0 + i * drh - doff
if ry + drh >= dtop && ry <= dtop + dh {
bind k = list_get(dk, i)
bind c = C_TEXT_DIM
if k == "-" { bind c = C_RED }
if k == "+" { bind c = C_GREEN }
if k == "h" { bind c = C_INDIGO }
g_text_fit(rx + 14.0, ry, rw - 40.0, 11.0, c, list_get(dt, i))
}
bind i = i + 1.0
}
u_unclip()
} else {
g_text_c(rx + rw * 0.5, top + (bot - top) * 0.5, 12.0, C_TEXT_DIM, "choose a spirit to read its yinyang")
}
# bottom: the rite bar
bind by = bot + 6.0
g_rect(0.0, bot, W, H - STATUS_H - bot, C_BG_PANEL)
u_hsep(0.0, bot, W)
bind msg = u_textfield("gx_msg", 12.0, by + 2.0, W - 180.0, 26.0, st_get("gx_msg", ""))
st_set("gx_msg", msg)
if msg == "" {
if st_get("focus", "") != "gx_msg" { g_text(20.0, by + 9.0, 12.0, C_TEXT_DIM, "the rite's inscription…") }
}
if u_button("gx_seal", W - 156.0, by + 2.0, 144.0, 26.0, "✦ seal the rite", C_GREEN) {
if msg == "" {
gx_flash("a rite needs an inscription")
} else {
rt_rite(msg)
st_set("gx_msg", "")
gx_refresh()
gx_flash("the rite is sealed")
}
}
return 0.0
}
# ── tab 1: lineage ────────────────────────────────────────────────────
fn gx_tab_lineage(W, H) {
bind top = TABS_H
bind bot = H - STATUS_H
bind rites = st_get("gx_rites", [])
bind n = len(rites)
bind lw = floor(W * 0.56)
g_rect(0.0, top, lw, bot - top, C_BG_SIDE)
u_vsep(lw - 1.0, top, bot - top)
ds_word(10.0, top + 8.0, 9.0, "LINEAGE", ds_col("bind"), true)
u_hsep(6.0, top + 30.0, lw - 12.0)
bind ltop = top + 36.0
bind lh = bot - ltop - 4.0
bind rh = 40.0
bind off = u_scroll_y("gx_sc1", 0.0, ltop, lw - 1.0, lh, n * rh + 8.0, st_get("gx_off1", 0.0))
st_set("gx_off1", off)
u_clip(0.0, ltop, lw - 1.0, lh)
bind souls = sx_souls()
bind selr = st_get("gx_selr", "")
bind i = 0.0
while i < n {
bind ry = ltop + 4.0 + i * rh - off
if ry + rh >= ltop && ry <= ltop + lh {
bind id = list_get(rites, i)
bind r = sx_rite_read(id)
bind hot = u_hot(0.0, ry, lw - 14.0, rh)
if selr == id { g_rect(0.0, ry, lw - 1.0, rh, C_SEL_ROW) }
else if hot { g_rect(0.0, ry, lw - 1.0, rh, C_HOVER_ROW) }
gx_aura(8.0, ry + 6.0, id)
g_text(8.0, ry + 20.0, 10.0, C_TEXT_DIM, ut_short(id))
g_text_fit(86.0, ry + 4.0, lw - 240.0, 12.0, sel(selr == id, C_TEXT_STRONG, C_TEXT), ut_first_line(list_get(r, 4.0)))
g_text(86.0, ry + 20.0, 10.0, C_TEXT_DIM, ut_fmt_time(list_get(r, 3.0)) + " · " + list_get(r, 2.0))
if len(list_get(r, 1.0)) > 1.5 { g_text(lw - 130.0, ry + 20.0, 10.0, C_VIOLET, "☯ union") }
bind decx = lw - 130.0
bind s = 0.0
while s < len(souls) {
if sx_tip(list_get(souls, s)) == id {
bind nm = list_get(souls, s)
bind wn = g_text_w(10.0, nm) + 10.0
g_rrect(decx, ry + 3.0, wn, 14.0, 3.0, C_SEL)
g_text(decx + 5.0, ry + 5.0, 10.0, C_TEXT_STRONG, nm)
bind decx = decx + wn + 4.0
}
bind s = s + 1.0
}
if hot && u_pressed() { st_set("gx_selr", id) }
}
bind i = i + 1.0
}
if n < 0.5 { g_text_c(lw * 0.5, ltop + 30.0, 12.0, C_TEXT_DIM, "no rites have been sealed yet") }
u_unclip()
# right: manifest of the selected rite
bind rx = lw + 8.0
bind rw = W - rx - 8.0
ds_frame(rx, top + 6.0, rw, bot - top - 12.0, ds_col("mod"), "MANIFEST")
if selr != "" {
bind r = sx_rite_read(selr)
gx_aura(rx + 14.0, top + 16.0, selr)
g_text(rx + 90.0, top + 12.0, 12.0, C_TEXT_STRONG, ut_short(selr))
g_text(rx + 14.0, top + 32.0, 11.0, C_TEXT_DIM, ut_fmt_time(list_get(r, 3.0)) + " · " + list_get(r, 2.0))
g_text_wrap(rx + 14.0, top + 50.0, rw - 28.0, 12.0, C_TEXT, list_get(r, 4.0))
if u_button("gx_summon_r", rx + rw - 110.0, top + 12.0, 96.0, 20.0, "summon", C_INDIGO) {
rt_summon([selr])
gx_refresh()
gx_flash("wandering at " + ut_short(selr) + " (detached)")
}
bind m = sx_rite_manifest(selr)
bind ids = list_get(m, 0.0)
bind paths = list_get(m, 1.0)
bind mtop = top + 96.0
bind mh = bot - mtop - 16.0
bind mn = len(paths)
bind moff = u_scroll_y("gx_sc1m", rx + 4.0, mtop, rw - 8.0, mh, mn * 18.0 + 8.0, st_get("gx_offm", 0.0))
st_set("gx_offm", moff)
u_clip(rx + 4.0, mtop, rw - 8.0, mh)
bind i = 0.0
while i < mn {
bind ry = mtop + 2.0 + i * 18.0 - moff
if ry + 18.0 >= mtop && ry <= mtop + mh {
bind info = sx_spirit_info(list_get(ids, i))
bind strat = list_get(info, 0.0)
bind c = C_GREEN
bind glyph = "○"
if strat == "delta" {
bind c = C_BLUE
bind glyph = "◐"
}
if strat == "chunks" {
bind c = C_VIOLET
bind glyph = "◍"
}
g_text(rx + 14.0, ry, 11.0, c, glyph + " " + strat)
g_text_fit(rx + 90.0, ry, rw - 180.0, 11.0, C_TEXT, list_get(paths, i))
g_text_r(rx + rw - 16.0, ry, 10.0, C_TEXT_DIM, "" + list_get(info, 3.0) + " B")
}
bind i = i + 1.0
}
u_unclip()
} else {
g_text_c(rx + rw * 0.5, top + (bot - top) * 0.5, 12.0, C_TEXT_DIM, "choose a rite to read its manifest")
}
return 0.0
}
# ── tab 2: souls ──────────────────────────────────────────────────────
fn gx_tab_souls(W, H) {
bind top = TABS_H
bind bot = H - STATUS_H
bind souls = sx_souls()
bind h = sx_head()
bind cur = ""
if list_get(h, 0.0) == "soul" { bind cur = list_get(h, 1.0) }
bind lw = floor(W * 0.6)
g_rect(0.0, top, lw, bot - top, C_BG_SIDE)
u_vsep(lw - 1.0, top, bot - top)
ds_word(10.0, top + 8.0, 9.0, "SOULS", ds_col("ctl"), true)
u_hsep(6.0, top + 30.0, lw - 12.0)
bind sels = st_get("gx_sels", "")
bind i = 0.0
while i < len(souls) {
bind s = list_get(souls, i)
bind ry = top + 38.0 + i * 34.0
bind hot = u_hot(0.0, ry, lw - 8.0, 32.0)
if sels == s { g_rect(0.0, ry, lw - 1.0, 32.0, C_SEL_ROW) }
else if hot { g_rect(0.0, ry, lw - 1.0, 32.0, C_HOVER_ROW) }
bind c = c_pal(i)
if s == cur { bind c = C_GREEN }
g_disc(16.0, ry + 16.0, 6.0, c)
if s == cur { g_ring(16.0, ry + 16.0, 9.0, C_TEXT_STRONG) }
g_text(32.0, ry + 4.0, 13.0, sel(s == cur, C_TEXT_STRONG, C_TEXT), s + sel(s == cur, " (the living soul)", ""))
bind tip = sx_tip(s)
if tip != "" {
bind r = sx_rite_read(tip)
g_text_fit(32.0, ry + 19.0, lw - 60.0, 10.0, C_TEXT_DIM, ut_short(tip) + " · " + ut_first_line(list_get(r, 4.0)))
} else {
g_text(32.0, ry + 19.0, 10.0, C_TEXT_DIM, "(unborn)")
}
if hot && u_pressed() { st_set("gx_sels", s) }
bind i = i + 1.0
}
# right: actions
bind rx = lw + 8.0
bind rw = W - rx - 8.0
ds_frame(rx, top + 6.0, rw, bot - top - 12.0, ds_col("ctl"), "CEREMONIES")
bind ay = top + 26.0
if sels != "" {
g_text(rx + 14.0, ay, 12.0, C_TEXT_STRONG, "chosen soul: " + sels)
if u_button("gx_s_summon", rx + 14.0, ay + 24.0, rw - 28.0, 26.0, "summon " + sels, C_BLUE) {
rt_summon([sels])
gx_refresh()
gx_flash("soul summoned: " + sels)
}
if u_button("gx_s_harm", rx + 14.0, ay + 56.0, rw - 28.0, 26.0, "harmonize " + sels + " into " + cur, C_GREEN) {
rt_harmonize([sels])
gx_refresh()
gx_flash("harmony sought with " + sels)
}
if u_button("gx_s_del", rx + 14.0, ay + 88.0, rw - 28.0, 26.0, "release " + sels, C_RED) {
rt_soul(["-d", sels])
st_set("gx_sels", "")
gx_refresh()
}
bind ay = ay + 128.0
}
u_hsep(rx + 10.0, ay, rw - 20.0)
g_text(rx + 14.0, ay + 10.0, 11.0, C_TEXT_DIM, "kindle a new soul at the current rite:")
bind nm = u_textfield("gx_newsoul", rx + 14.0, ay + 28.0, rw - 120.0, 24.0, st_get("gx_newsoul", ""))
st_set("gx_newsoul", nm)
if u_button("gx_s_new", rx + rw - 96.0, ay + 28.0, 82.0, 24.0, "kindle", C_YELLOW) {
if nm != "" {
rt_soul([nm])
st_set("gx_newsoul", "")
gx_refresh()
gx_flash("new soul kindled: " + nm)
}
}
return 0.0
}
# ── tab 3: fair (share over SSH) ──────────────────────────────────────
fn gx_fair_tick() {
if st_get("gx_fair_on", 0.0) < 0.5 { return 0.0 }
bind handled = 0.0
bind go = true
while go {
bind msg = ssh_serve_recv()
if msg == "" {
bind go = false
} else {
bind sp = str_find(msg, "|")
bind cid = to_number(str_slice(msg, 0.0, sp))
bind cmd = str_trim(str_slice(msg, sp + 1.0, 99999999.0))
nx_fair_handle(cid, cmd, path_name(sx_root()), st_get("gx_fair_trib", 0.0) > 0.5, st_get("gx_fair_wpw", ""))
st_set("gx_fair_served", st_get("gx_fair_served", 0.0) + 1.0)
bind handled = handled + 1.0
if handled >= 4.0 { bind go = false }
}
}
return 0.0
}
fn gx_tab_fair(W, H) {
bind top = TABS_H
bind bot = H - STATUS_H
bind rx = 12.0
bind rw = W - 24.0
ds_frame(rx, top + 8.0, rw, bot - top - 16.0, ds_col("asm"), "TEMPLE FAIR 庙会")
bind y = top + 34.0
bind on = st_get("gx_fair_on", 0.0) > 0.5
if on == false {
g_text(rx + 16.0, y, 12.0, C_TEXT, "open your temple over SSH — pilgrims pull with a one-time link.")
g_text(rx + 16.0, y + 18.0, 11.0, C_TEXT_DIM, "its own host key, its own credentials; your personal SSH keys are never touched.")
g_text(rx + 16.0, y + 46.0, 11.0, C_TEXT_DIM, "gate (port):")
bind ports = u_textfield("gx_fair_port", rx + 100.0, y + 40.0, 90.0, 24.0, st_get("gx_fair_port", "7447"))
st_set("gx_fair_port", ports)
bind trib = st_get("gx_fair_trib", 0.0) > 0.5
if u_check("gx_fair_tribc", rx + 210.0, y + 44.0, "accept tribute (push)", trib) {
st_set("gx_fair_trib", sel(trib, 0.0, 1.0))
}
if u_button("gx_fair_open", rx + 16.0, y + 80.0, 180.0, 28.0, "⛩ open the gates", C_GREEN) {
bind port = to_number(ports)
if port < 1.0 { bind port = 7447.0 }
bind pw = random_hex(9.0)
bind wpw = random_hex(9.0)
make_dir(sx_dir() + "/fair")
ssh_config(port, "pilgrim", pw, sx_dir() + "/fair/host_ed25519")
bind okd = ssh_serve()
if okd == false {
gx_flash("the gates would not open — port busy?")
} else {
bind host = env_get("COMPUTERNAME", env_get("HOSTNAME", "<your-ip>"))
bind link = "miao+ssh://pilgrim:" + pw + "@" + host + ":" + port + "/" + path_name(sx_root())
st_set("gx_fair_on", 1.0)
st_set("gx_fair_link", link)
st_set("gx_fair_wpw", wpw)
st_set("gx_fair_served", 0.0)
write_file(sx_dir() + "/fair/link.txt", link + "\n")
bind svg = qr_svg(link)
if svg != "" { write_file(sx_dir() + "/fair/link.svg", svg) }
net_announce(7448.0, "miao|" + path_name(sx_root()) + "|" + port)
gx_flash("the fair is open")
}
}
} else {
g_text(rx + 16.0, y, 13.0, C_GREEN, "⛩ the fair is OPEN — pilgrims may pull")
g_text(rx + 16.0, y + 26.0, 11.0, C_TEXT_DIM, "share this link (also in .miao/fair/link.txt, QR in link.svg):")
g_rrect(rx + 14.0, y + 44.0, rw - 28.0, 26.0, 3.0, C_BG_DEEP)
g_text_fit(rx + 22.0, y + 50.0, rw - 44.0, 12.0, C_YELLOW, st_get("gx_fair_link", ""))
if st_get("gx_fair_trib", 0.0) > 0.5 {
g_text(rx + 16.0, y + 80.0, 11.0, C_ORANGE, "tribute link (push access — guard it):")
g_rrect(rx + 14.0, y + 96.0, rw - 28.0, 26.0, 3.0, C_BG_DEEP)
g_text_fit(rx + 22.0, y + 102.0, rw - 44.0, 11.0, C_ORANGE, st_get("gx_fair_link", "") + "?tribute=" + st_get("gx_fair_wpw", ""))
}
g_text(rx + 16.0, y + 134.0, 11.0, C_TEXT_DIM, "ceremonies served: " + st_get("gx_fair_served", 0.0))
if u_button("gx_fair_close", rx + 16.0, y + 158.0, 180.0, 28.0, "close the gates", C_RED) {
ssh_stop()
net_announce_stop()
st_set("gx_fair_on", 0.0)
gx_flash("the fair has closed")
}
}
# mothers + pilgrimage/tribute
bind my = y + 210.0
u_hsep(rx + 10.0, my - 10.0, rw - 20.0)
ds_word(rx + 16.0, my, 9.0, "INCENSE NETWORK", ds_col("func"), true)
bind lines = ut_read_lines(sx_dir() + "/mothers")
bind i = 0.0
while i < len(lines) {
bind ln = list_get(lines, i)
bind sp = str_find(ln, "|")
bind mname = str_slice(ln, 0.0, sp)
bind link = str_slice(ln, sp + 1.0, 99999.0)
bind at = str_find(link, "@")
bind safe = link
if at >= 0.0 { bind safe = "…@" + str_slice(link, at + 1.0, 99999.0) }
g_text(rx + 16.0, my + 22.0 + i * 30.0, 12.0, C_BLUE, "祖 " + mname)
g_text_fit(rx + 120.0, my + 23.0 + i * 30.0, rw - 420.0, 11.0, C_TEXT_DIM, safe)
if u_button("gx_pil" + mname, rx + rw - 280.0, my + 18.0 + i * 30.0, 120.0, 24.0, "pilgrimage", C_BLUE) {
nx_pilgrimage([mname])
gx_refresh()
gx_flash("pilgrimage to " + mname + " complete — see the terminal for details")
}
if u_button("gx_tri" + mname, rx + rw - 150.0, my + 18.0 + i * 30.0, 120.0, 24.0, "tribute", C_ORANGE) {
nx_tribute([mname])
gx_refresh()
gx_flash("tribute carried to " + mname + " — see the terminal")
}
bind i = i + 1.0
}
if len(lines) < 0.5 {
g_text(rx + 16.0, my + 24.0, 11.0, C_TEXT_DIM, "no ancestral temples — enshrine a link from the CLI, or add one with `miao mother add`")
}
# entrusted keepers (selected pushers, verified by their seals)
bind ey = my + 48.0 + max(1.0, len(lines)) * 30.0
bind ent = nx_entrusted()
bind en = list_get(ent, 0.0)
u_hsep(rx + 10.0, ey - 10.0, rw - 20.0)
if len(en) > 0.0 {
g_text(rx + 16.0, ey, 12.0, C_VIOLET, "印 entrusted keepers: ")
g_text(rx + 170.0, ey + 1.0, 12.0, C_TEXT_STRONG, list_join(en, " · "))
g_text(rx + 16.0, ey + 18.0, 10.0, C_TEXT_DIM, "their sealed pushes are accepted even while the fair is read-only · manage with `miao entrust`")
} else {
g_text(rx + 16.0, ey, 10.5, C_TEXT_DIM, "no entrusted keepers — `miao entrust <name> <seal print>` lets chosen people push without any shared secret")
}
return 0.0
}
# ── chrome ────────────────────────────────────────────────────────────
fn gx_tabs(W) {
g_rect(0.0, 0.0, W, TABS_H, C_BG_PANEL)
u_hsep(0.0, TABS_H - 1.0, W)
bind names = ["Divine 问", "Lineage 谱", "Souls 魂", "Fair 庙会"]
bind cols = [C_YELLOW, C_INDIGO, C_GREEN, C_RED]
bind x = 10.0
bind i = 0.0
while i < len(names) {
bind nm = list_get(names, i)
bind w = g_text_w(12.0, nm) + 24.0
if u_tab("gx_tab" + num_str(i), x, 3.0, w, 22.0, nm, st_get("gx_tab", 0.0) == i, list_get(cols, i)) {
st_set("gx_tab", i)
gx_refresh()
}
bind x = x + w + 3.0
bind i = i + 1.0
}
# temple + soul, right-aligned
bind h = sx_head()
bind where = ""
if list_get(h, 0.0) == "soul" { bind where = "魂 " + list_get(h, 1.0) }
if list_get(h, 0.0) == "rite" { bind where = "wandering · " + ut_short(list_get(h, 1.0)) }
bind label = path_name(sx_root()) + " · " + where
g_text_r(W - 12.0, 7.0, 12.0, C_TEXT_DIM, label)
return 0.0
}
fn gx_status(W, H) {
bind y = H - STATUS_H
g_rect(0.0, y, W, STATUS_H, C_BG_PANEL)
u_hsep(0.0, y, W)
# seven tiny ROYGBIV beads, the miao signature
bind i = 0.0
while i < 7.0 {
g_disc(12.0 + i * 12.0, y + 11.0, 3.0, c_pal(i))
bind i = i + 1.0
}
bind rows = st_get("gx_rows_p", [])
bind state = "serene"
if len(rows) > 0.5 { bind state = "" + len(rows) + " spirit(s) stirring" }
if st_get("gx_fair_on", 0.0) > 0.5 { bind state = state + " · fair open" }
g_text(100.0, y + 5.0, 10.0, C_TEXT_DIM, sx_root() + " · keeper " + sx_author() + " · " + state)
bind fl = st_get("gx_flash", "")
if fl != "" {
if time_now() - st_get("gx_flashT", 0.0) < 4.0 {
g_text_r(W - 12.0, y + 5.0, 10.0, C_YELLOW, fl)
}
}
return 0.0
}
# ── no-temple greeting ────────────────────────────────────────────────
fn gx_no_temple(W, H) {
bind cy = H * 0.5 - 60.0
bind i = 0.0
while i < 7.0 {
g_disc(W * 0.5 - 42.0 + i * 14.0, cy - 30.0, 5.0, c_pal(i))
bind i = i + 1.0
}
g_text_c(W * 0.5, cy, 18.0, C_TEXT_STRONG, "no temple stands here")
g_text_c(W * 0.5, cy + 26.0, 12.0, C_TEXT_DIM, absolute_path("."))
if u_button("gx_found", W * 0.5 - 130.0, cy + 60.0, 260.0, 30.0, "✦ consecrate this ground", C_GREEN) {
sx_init(ut_norm(absolute_path(".")))
st_set("sx_root", ut_norm(absolute_path(".")))
gx_refresh()
gx_flash("the ground is consecrated")
}
return 0.0
}
# ── entry ─────────────────────────────────────────────────────────────
fn gx_main(args) {
bind shot = ""
bind fairopen = false
bind ai = 0.0
while ai < len(args) {
if list_get(args, ai) == "--shot" { bind shot = list_get(args, ai + 1.0) }
if list_get(args, ai) == "--tab" { st_set("gx_tab", to_number(list_get(args, ai + 1.0))) }
if list_get(args, ai) == "--sel" { st_set("gx_sel", list_get(args, ai + 1.0)) }
if list_get(args, ai) == "--fairopen" { bind fairopen = true }
bind ai = ai + 1.0
}
open_window(1240.0, 800.0, "LingMiao — 灵庙", 1)
px_flat()
bind home = env_get("MIAO_HOME", "")
if home != "" { bind home = str_replace(home, "\\", "/") }
bind f = font_load("assets/font.ttf")
if f < 0.0 { bind f = font_load("../assets/font.ttf") }
if f < 0.0 { bind f = font_load(home + "assets/font.ttf") }
if f < 0.0 { bind f = font_load("C:/Users/User/Programs/ling-source/assets/font.ttf") }
bind uf = font_load("assets/fonts/DaemonSans.ttf")
if uf < 0.0 { bind uf = font_load(home + "assets/fonts/DaemonSans.ttf") }
if uf < 0.0 { bind uf = font_load("C:/Users/User/Programs/ling-source/assets/fonts/DaemonSans.ttf") }
if f >= 0.0 {
if uf >= 0.0 { font_fallback(f, uf, 0.88) }
}
if f < 0.0 { bind f = uf }
st_set("font", f)
if sx_root() != "" { gx_refresh() }
if st_get("gx_sel", "") != "" { gx_make_diff(st_get("gx_sel", ""), "") }
if fairopen {
if sx_root() != "" {
bind pw = random_hex(9.0)
make_dir(sx_dir() + "/fair")
ssh_config(7447.0, "pilgrim", pw, sx_dir() + "/fair/host_ed25519")
if ssh_serve() {
bind host = env_get("COMPUTERNAME", "yourhost")
st_set("gx_fair_on", 1.0)
st_set("gx_fair_trib", 1.0)
st_set("gx_fair_wpw", random_hex(9.0))
st_set("gx_fair_link", "miao+ssh://pilgrim:" + pw + "@" + host + ":7447/" + path_name(sx_root()))
}
}
}
bind frame = 0.0
while window_is_open() && st_get("gx_quit", 0.0) < 0.5 {
st_set("frame", frame)
px_theme(0.0)
u_begin()
bind W = get_width()
bind H = get_height()
g_rect(0.0, 0.0, W, H, C_BG_APP)
if sx_root() == "" {
gx_no_temple(W, H)
} else {
gx_fair_tick()
bind tab = st_get("gx_tab", 0.0)
if tab == 0.0 { gx_tab_divine(W, H) }
if tab == 1.0 { gx_tab_lineage(W, H) }
if tab == 2.0 { gx_tab_souls(W, H) }
if tab == 3.0 { gx_tab_fair(W, H) }
gx_status(W, H)
}
gx_tabs(W)
# tooltip
bind tip = st_get("tip", "")
if tip != "" {
bind tw = g_text_w(11.0, tip) + 14.0
bind tx = min(u_mx() + 14.0, W - tw - 4.0)
g_rrect(tx, u_my() + 18.0, tw, 20.0, 4.0, C_POPUP)
g_rframe(tx, u_my() + 18.0, tw, 20.0, 4.0, C_POPUP_LINE)
g_text(tx + 7.0, u_my() + 22.0, 11.0, C_TEXT, tip)
}
if st_get("focus", "") == "" {
if key_pressed("f5") {
gx_refresh()
gx_flash("the oracle has been consulted")
}
if u_ctrl() {
if key_pressed("q") { st_set("gx_quit", 1.0) }
}
}
combo_overlay()
u_end()
present()
if shot != "" {
if frame == 30.0 {
screenshot(shot)
st_set("gx_quit", 1.0)
}
}
bind frame = frame + 1.0
}
if st_get("gx_fair_on", 0.0) > 0.5 {
ssh_stop()
net_announce_stop()
}
return 0.0
}