Skip to content

LuaCatalog.kt

src/jvmMain/kotlin/afield/lang/lua/LuaCatalog.kt · 56 lines

package afield.lang.lua

The signatures and one-line descriptions that completion shows for Lua names, held to a live LuaJIT by LuaCatalogTest.

object LuaCatalog

What completion says about a Lua name: its signature and one line on what it does.

Two catalogs, both resources beside the prelude: lua-stdlib.txt for the Lua 5.1 library and LuaJIT 2.1's additions (bit, jit, table.move, ...), and lua-field.txt for what Field's prelude adds (display, line, play, field.*, the methods of a line). Neither is generated from a header, because Lua's headers say nothing about Lua functions; instead LuaCatalogTest holds each to a live LuaJIT state in both directions, the way Pd's object list is held to its pinned sources: a function the state has and the catalog does not fails, and so does a line naming a function the state no longer has.

object LuaCatalog {

class Entry(val name: String, val signature: String, val doc: String, val fromField: Boolean)

One catalogued function: name as it is reached (string.format, Line.moveTo, print).

    private fun read(resource: String, fromField: Boolean): Map<String, Entry> {
        val text = LuaCatalog::class.java.getResource(resource)?.readText() ?: return emptyMap()
        val out = LinkedHashMap<String, Entry>()
        for (raw in text.lines()) {
            val line = raw.trim()
            if (line.isEmpty() || line.startsWith("#")) continue
            val signature = line.substringBefore("|").trim()
            val doc = line.substringAfter("|", "").trim()
            val name = signature.substringBefore("(").trim()
            out[name] = Entry(name, signature, doc, fromField)
        }
        return out
    }

val stdlib: Map<String, Entry> by lazy { read("/afield/lua/lua-stdlib.txt", fromField = false) }

The Lua and LuaJIT library.

val field: Map<String, Entry> by lazy { read("/afield/lua/lua-field.txt", fromField = true) }

What Field's prelude adds.

fun lookup(path: String, name: String): Entry?

The entry for name reached at path ("" for a global, "string", "field", "field.Line"). Field's entry wins where both have one — print goes to the box, not stdout.

    fun lookup(path: String, name: String): Entry? {
        val key = when (path) {
            "" -> name
            "field.Line" -> "Line.$name"
            else -> "$path.$name"
        }
        return field[key] ?: stdlib[key]
    }
}