Skip to content

Instantly share code, notes, and snippets.

@Kyonru
Last active February 7, 2026 23:05
Show Gist options
  • Select an option

  • Save Kyonru/3999bbd9ff788dd45f7d9ab302bedb08 to your computer and use it in GitHub Desktop.

Select an option

Save Kyonru/3999bbd9ff788dd45f7d9ab302bedb08 to your computer and use it in GitHub Desktop.
Cargo.lua Lua Language Server Types
local lfs = require("lfs")
local ROOT = "assets"
local OUTPUT = "types/assets.lua"
local typeMap = {
lua = "function",
png = "love.Image",
jpg = "love.Image",
dds = "love.Image",
ogv = "love.Video",
glsl = "love.Shader",
mp3 = "love.Source",
ogg = "love.Source",
wav = "love.Source",
flac = "love.Source",
txt = "string",
fnt = "love.Font",
}
local tree = {}
local function ensure(tbl, key)
tbl[key] = tbl[key] or {}
return tbl[key]
end
local function scan(dir, node)
for file in lfs.dir(dir) do
if file ~= "." and file ~= ".." then
local path = dir .. "/" .. file
local attr = lfs.attributes(path)
if attr.mode == "directory" then
local folder = ensure(node, file)
scan(path, folder)
else
local name, ext = file:match("^(.-)%.([^.]+)$")
if name and ext then
ext = ext:lower()
local t = typeMap[ext]
if t then
node[name] = t
end
end
end
end
end
end
scan(ROOT, tree)
local lines = {}
table.insert(lines, "---@diagnostic disable: missing-fields")
local classes = {}
local function writeClass(name, node)
-- sorted keys
local keys = {}
for k in pairs(node) do
table.insert(keys, k)
end
table.sort(keys)
-- First, define all nested classes
for _, k in ipairs(keys) do
local v = node[k]
if type(v) == "table" then
local childName = name .. "_" .. k
writeClass(childName, v) -- recurse first
end
end
-- Then define this class
table.insert(classes, "---@class " .. name)
for _, k in ipairs(keys) do
local v = node[k]
if type(v) == "table" then
local childName = name .. "_" .. k
table.insert(classes, string.format("---@field %s %s", k, childName))
else
table.insert(classes, string.format("---@field %s %s", k, v))
end
end
table.insert(classes, "") -- spacing
end
writeClass("GLOBAL_ASSETS", tree)
table.insert(lines, table.concat(classes, "\n"))
table.insert(lines, "---@type GLOBAL_ASSETS")
table.insert(lines, "ASSETS = {}")
local f = assert(io.open(OUTPUT, "w"))
f:write(table.concat(lines, "\n"))
f:close()
print("Generated " .. OUTPUT)
types:
# Generate the types for the assets
lua generate_assets_types.lua
watch:
# Watch for changes in the assets folder
sudo watchman-make -p 'assets/**' --run 'make types'
@Kyonru

Kyonru commented Dec 29, 2025

Copy link
Copy Markdown
Author

running make watch creates and update the types for https://github.com/bjornbytes/cargo allowing to auto complete new added files.

local cargo = require("lib.cargo")

function love.load()
  ASSETS = cargo.init("assets")
end

The scripts assigns the type to the ASSET Global variable, by the time love.load is executed, any subsequent usages of the ASSETS variable will be already initialize. Cargo.init be called and assigned before the load function if desired (but not recommended).

---@type GLOBAL_ASSETS
ASSETS = {}
image image

@Kyonru

Kyonru commented Dec 29, 2025

Copy link
Copy Markdown
Author

Watch function depends on watchman being installed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment