1// Package triedemo is a small gnoweb demo of the prefix tree provided by the2// [p/moul/x/daily/trie](/p/moul/x/daily/trie/v0) library: type a prefix in the3// URL and it lists every dictionary word that completes it.4//5// It contains no trie logic of its own — the tree, the ordering and the limit6// all come from the library. The dictionary is a fixed, sorted word list so the7// realm has no mutable state and Render is fully deterministic.8package triedemo910import (11 "strconv"12 "strings"1314 "gno.land/p/moul/x/daily/trie/v0"15)1617// maxResults caps how many completions a single Render lists.18const maxResults = 251920// dictionary is the demo corpus: gno/Go vocabulary, deliberately clustered on21// a few prefixes ("co", "gn", "re", "tr") so completions are fun to explore.22var dictionary = []string{23 "chain", "coin", "collection", "commit", "compile", "complete", "concurrent",24 "consensus", "constant", "contract", "counter", "crossing", "deploy", "gas",25 "genesis", "gno", "gnodev", "gnokey", "gnoland", "gnoweb", "goroutine",26 "grc20", "hash", "interface", "keeper", "ledger", "mempool", "merkle",27 "module", "namespace", "package", "panic", "pointer", "prefix", "prove",28 "realm", "receiver", "recover", "reflect", "render", "replay", "rollback",29 "slice", "stdlib", "struct", "transaction", "transfer", "traverse", "tree",30 "trie", "type", "validator", "vault", "vm", "wallet",31}3233// dict is built once at init; the library keeps it sorted internally.34var dict = trie.FromWords(dictionary)3536// Render renders the autocomplete for gnoweb.37//38// Render("") / Render("/") -> the whole dictionary + usage39// Render("/<prefix>") -> every word completing <prefix>40func Render(path string) string {41 prefix := parsePrefix(path)4243 var b strings.Builder44 b.WriteString("# Trie Autocomplete\n\n")45 b.WriteString("A prefix tree over a ")46 b.WriteString(strconv.Itoa(dict.Len()))47 b.WriteString("-word dictionary, demoing the ")48 b.WriteString("[`p/moul/x/daily/trie`](/p/moul/x/daily/trie/v0) library.\n\n")4950 if prefix == "" {51 b.WriteString("Append a prefix to the path to complete it.\n\n")52 b.WriteString("## Try one\n\n")53 // Listing all 55 words here would bury the page (and the example test54 // that pins it); the interesting part is the prefix walk, so show a few55 // live counts and let /<prefix> do the listing.56 for _, p := range []string{"co", "gno", "re", "tr"} {57 b.WriteString("- [`/")58 b.WriteString(p)59 b.WriteString("`](/r/moul/x/daily/triedemo/v0:")60 b.WriteString(p)61 b.WriteString(") — ")62 b.WriteString(strconv.Itoa(len(dict.Complete(p, 0))))63 b.WriteString(" words\n")64 }65 return b.String()66 }6768 b.WriteString("## Completions for `")69 b.WriteString(prefix)70 b.WriteString("`\n\n")7172 if !dict.HasPrefix(prefix) {73 b.WriteString("_No word starts with `")74 b.WriteString(prefix)75 b.WriteString("`._\n\n> Try `/co`, `/gno`, `/tr` or `/re`.\n")76 return b.String()77 }7879 words := dict.Complete(prefix, maxResults)80 b.WriteString("**")81 b.WriteString(strconv.Itoa(len(words)))82 b.WriteString("** match")83 if len(words) != 1 {84 b.WriteString("es")85 }86 if len(words) == maxResults {87 b.WriteString(" (capped at ")88 b.WriteString(strconv.Itoa(maxResults))89 b.WriteString(")")90 }91 b.WriteString("\n\n")92 b.WriteString(list(words))9394 if dict.Contains(prefix) {95 b.WriteString("\n> `")96 b.WriteString(prefix)97 b.WriteString("` is itself a word in the dictionary.\n")98 }99 return b.String()100}101102// parsePrefix extracts the prefix from a Render path like "/gno", keeping only103// the first segment. Returns "" for the empty/root path.104func parsePrefix(path string) string {105 s := strings.TrimSpace(path)106 s = strings.TrimPrefix(s, "/")107 if i := strings.IndexByte(s, '/'); i >= 0 {108 s = s[:i]109 }110 return s111}112113// list renders words as a Markdown bullet list.114func list(words []string) string {115 if len(words) == 0 {116 return "_none_\n"117 }118 var b strings.Builder119 for _, w := range words {120 b.WriteString("- `")121 b.WriteString(w)122 b.WriteString("`\n")123 }124 return b.String()125}126Render(path string) string
Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.
vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.