Skip to content

Commit 1ae54ba

Browse files
committed
docs: Worse than epstein?
1 parent f8d1c5c commit 1ae54ba

18 files changed

Lines changed: 750 additions & 7 deletions

File tree

.config/docs.luau

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
return {
2+
directory = "docs",
3+
zensical = "zensical.toml",
4+
5+
-- paths are assumed to start from docs
6+
documentationPaths = {
7+
mechanics = "reference/mechanics",
8+
libraries = "reference/libraries",
9+
},
10+
11+
header = "<!-- This file was automatically @generated and should not be modified manually. -->",
12+
}

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ site
1515
src/*/generated/**/*.luau
1616
!src/shared/generated/types/roblox.luau
1717

18+
# lute typedefs
19+
.lute/typedefs
20+
1821
# python
1922
.venv
2023
.cache

.luaurc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
"libs": "src/libs",
88
"kit": "src/kit",
99
// lute
10-
"lute": "~/.lute/typedefs/0.1.0/lute",
11-
"lint": "~/.lute/typedefs/0.1.0/lint",
12-
"std": "~/.lute/typedefs/0.1.0/std",
10+
"lute": ".lute/typedefs/lute",
11+
"lint": ".lute/typedefs/lint",
12+
"std": ".lute/typedefs/std",
1313
"batteries": ".lute/batteries",
1414
"scripts": ".lute",
1515
"config": ".config"

.lute/batteries/pp.luau

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
type ExistingOptions = {
2+
rawStrings: boolean?,
3+
}
4+
5+
local isPrimitiveType = { string = true, number = true, boolean = true }
6+
7+
local typeSortOrder: { [string]: number } = {
8+
["boolean"] = 1,
9+
["number"] = 2,
10+
["string"] = 3,
11+
["function"] = 4,
12+
["vector"] = 5,
13+
["buffer"] = 6,
14+
["thread"] = 7,
15+
["table"] = 8,
16+
["userdata"] = 9,
17+
["nil"] = 10,
18+
}
19+
20+
local function isPrimitiveArray(array: { [unknown]: unknown }): boolean
21+
local max, len = 0, #array
22+
23+
for key, value in array do
24+
if type(key) ~= "number" then
25+
return false
26+
elseif key <= 0 then
27+
return false
28+
-- userdatas arent primitives
29+
elseif not isPrimitiveType[type(value)] then
30+
return false
31+
end
32+
33+
max = math.max(key, max)
34+
end
35+
36+
return len == max
37+
end
38+
39+
local function getFormattedAdress(t: {}): string
40+
return `table<({t})>`
41+
end
42+
43+
local function formatValue(value: unknown, options: ExistingOptions?): string
44+
if type(value) == "table" then
45+
return getFormattedAdress(value) -- simple representation for table values
46+
elseif type(value) ~= "string" then
47+
return tostring(value)
48+
end
49+
50+
if options and options.rawStrings then
51+
return `"{value}"`
52+
end
53+
return string.format("%q", value)
54+
end
55+
56+
local function formatKey(key: unknown, seq: boolean): string
57+
if seq then
58+
return ""
59+
end
60+
61+
if type(key) == "table" then
62+
return `[{getFormattedAdress(key)}] = ` -- TODO: handling for table keys
63+
end
64+
if type(key) ~= "string" then
65+
return `[{tostring(key)}] =`
66+
end
67+
68+
-- key is a simple identifier
69+
if string.match(key, "^[%a_][%w_]-$") == key then
70+
return `{key} = `
71+
end
72+
73+
return `[{string.format("%q", key)}] = `
74+
end
75+
76+
local function isEmpty(t: { [unknown]: unknown }): boolean
77+
for _ in t do
78+
return false
79+
end
80+
return true
81+
end
82+
83+
-- FIXME(luau): mark `dataTable` indexer as read-only
84+
local function traverseTable(
85+
dataTable: { [unknown]: unknown },
86+
seen: { [unknown]: boolean },
87+
indent: number,
88+
options: ExistingOptions?
89+
): string
90+
local output = ""
91+
local indentStr = string.rep(" ", indent)
92+
93+
-- FIXME(Luau): We shouldn't need this annotation.
94+
local keys: { unknown } = {}
95+
96+
-- Collect all keys, not just primitives
97+
for key in dataTable do
98+
table.insert(keys, key)
99+
end
100+
101+
table.sort(keys, function(a, b): boolean
102+
local typeofTableA, typeofTableB = typeof(dataTable[a]), typeof(dataTable[b])
103+
104+
if typeofTableA ~= typeofTableB then
105+
return typeSortOrder[typeofTableA] < typeSortOrder[typeofTableB]
106+
end
107+
108+
if type(a) == "number" and type(b) == "number" then
109+
return a < b
110+
end
111+
112+
return tostring(a) < tostring(b)
113+
end)
114+
115+
local inSequence = false
116+
local previousKey = 0
117+
118+
for _, key in keys do
119+
if type(key) == "number" and key > 0 and key - 1 == previousKey then
120+
previousKey = key
121+
inSequence = true
122+
else
123+
inSequence = false
124+
end
125+
126+
local value = dataTable[key]
127+
128+
if type(value) ~= "table" then
129+
output = `{output}{indentStr}{formatKey(key, inSequence)}{formatValue(value, options)},\n`
130+
continue
131+
end
132+
133+
-- prevents self-referential tables from looping infinitely
134+
if seen[value] then
135+
output = `{output}{indentStr}{formatKey(key, inSequence)}[Circular Reference <({value})>],\n`
136+
continue
137+
else
138+
seen[value] = true
139+
end
140+
141+
if isEmpty(value :: { [unknown]: unknown }) then
142+
output = string.format("%s%s%s{},\n", output, indentStr, formatKey(key, inSequence))
143+
continue
144+
end
145+
146+
if isPrimitiveArray(value :: { [unknown]: unknown }) then -- collapse primitive arrays
147+
local outputConcatTbl = table.create(#value) :: { string }
148+
149+
for valueIndex, valueInArray in value :: { unknown } do
150+
outputConcatTbl[valueIndex] = formatValue(valueInArray)
151+
end
152+
153+
output = string.format(
154+
"%s%s%s{%*},\n",
155+
output,
156+
indentStr,
157+
formatKey(key, inSequence),
158+
table.concat(outputConcatTbl, ", ")
159+
)
160+
continue
161+
end
162+
163+
output = string.format(
164+
"%s%s%s{\n%s%s},\n",
165+
output,
166+
indentStr,
167+
formatKey(key, inSequence),
168+
traverseTable(value :: any, seen, indent + 1, options),
169+
indentStr
170+
)
171+
172+
seen[value] = nil
173+
end
174+
175+
return output
176+
end
177+
178+
return function(data: unknown, options: ExistingOptions?): string
179+
options = options or {} :: ExistingOptions
180+
181+
-- if it's not a primitive, we'll pretty print it as a value
182+
if type(data) ~= "table" then
183+
return formatValue(data, options)
184+
end
185+
186+
return `\{\n{traverseTable(data :: { [unknown]: unknown }, { [data] = true }, 1, options)}\}`
187+
end

0 commit comments

Comments
 (0)