Skip to content

Commit 9c68716

Browse files
committed
Initial implementation of SQUISH.LUA
1 parent 80d1acf commit 9c68716

File tree

1 file changed

+150
-0
lines changed

1 file changed

+150
-0
lines changed

util/SQUISH.LUA

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
#!/usr/bin/env lua
2+
3+
local function Squish(fileName)
4+
local f, e = io.open(fileName, "r")
5+
if not f then
6+
print(e)
7+
return
8+
end
9+
local function tokenizeFile(file)
10+
local data, tokens, pos = file:read("all"), {}, 1
11+
12+
if data:sub(1, 2) == "#!" then
13+
local lineEnd = data:find("\n", 1) or #data + 1
14+
table.insert(tokens, {type = "shebang", value = data:sub(1, lineEnd - 1)})
15+
pos = lineEnd
16+
end
17+
18+
while pos <= #data do
19+
local c = data:sub(pos, pos)
20+
21+
-- Handle comments
22+
if c == "-" and data:sub(pos, pos + 1) == "--" then
23+
local commentStart = pos
24+
-- Check for multi-line comment
25+
if data:sub(pos + 2, pos + 3) == "[[" then
26+
local commentEnd = data:find("]]", pos + 4, true)
27+
if commentEnd then
28+
table.insert(tokens, {type = "comment", value = data:sub(commentStart, commentEnd + 1)})
29+
pos = commentEnd + 2
30+
else
31+
-- Unclosed comment, treat as single line
32+
local lineEnd = data:find("\n", pos) or #data + 1
33+
table.insert(tokens, {type = "comment", value = data:sub(commentStart, lineEnd - 1)})
34+
pos = lineEnd
35+
end
36+
-- Standard single-line comment
37+
else
38+
local lineEnd = data:find("\n", pos) or #data + 1
39+
table.insert(tokens, {type = "comment", value = data:sub(commentStart, lineEnd - 1)})
40+
pos = lineEnd
41+
end
42+
43+
-- Handle strings with double quotes
44+
elseif c == '"' then
45+
local stringStart = pos
46+
pos = pos + 1
47+
while pos <= #data do
48+
if data:sub(pos, pos) == '"' and data:sub(pos - 1, pos - 1) ~= "\\" then
49+
break
50+
elseif data:sub(pos, pos) == "\\" and pos < #data then
51+
pos = pos + 2 -- Skip escaped character
52+
else
53+
pos = pos + 1
54+
end
55+
end
56+
if pos <= #data then
57+
table.insert(tokens, {type = "string", value = data:sub(stringStart, pos)})
58+
pos = pos + 1
59+
else
60+
-- Unclosed string, treat as code (this is an error in Lua)
61+
table.insert(tokens, {type = "code", value = data:sub(stringStart, pos - 1)})
62+
end
63+
64+
-- Handle strings with single quotes
65+
elseif c == "'" then
66+
local stringStart = pos
67+
pos = pos + 1
68+
while pos <= #data do
69+
if data:sub(pos, pos) == "'" and data:sub(pos - 1, pos - 1) ~= "\\" then
70+
break
71+
elseif data:sub(pos, pos) == "\\" and pos < #data then
72+
pos = pos + 2 -- Skip escaped character
73+
else
74+
pos = pos + 1
75+
end
76+
end
77+
if pos <= #data then
78+
table.insert(tokens, {type = "string", value = data:sub(stringStart, pos)})
79+
pos = pos + 1
80+
else
81+
-- Unclosed string, treat as code (this is an error in Lua)
82+
table.insert(tokens, {type = "code", value = data:sub(stringStart, pos - 1)})
83+
end
84+
85+
-- Handle long bracket strings
86+
elseif c == "[" and data:sub(pos, pos + 1):match("%[=*%[") then
87+
local stringStart = pos
88+
local openBracket = data:match("%[=*%[", pos)
89+
local closeBracket = openBracket:gsub("%[", "]")
90+
local stringEnd = data:find(closeBracket, pos + #openBracket, true)
91+
92+
if stringEnd then
93+
table.insert(tokens, {type = "string", value = data:sub(stringStart, stringEnd + #closeBracket - 1)})
94+
pos = stringEnd + #closeBracket
95+
else
96+
-- Unclosed long bracket, treat as code (this is an error in Lua)
97+
table.insert(tokens, {type = "code", value = data:sub(stringStart, pos)})
98+
pos = pos + 1
99+
end
100+
101+
-- Handle normal code
102+
else
103+
local codeStart = pos
104+
while pos <= #data do
105+
local next_char = data:sub(pos, pos)
106+
if next_char == "-" and data:sub(pos, pos + 1) == "--" or
107+
next_char == '"' or next_char == "'" or
108+
(next_char == "[" and data:sub(pos, pos + 1):match("%[=*%[")) then
109+
break
110+
end
111+
pos = pos + 1
112+
end
113+
114+
if codeStart < pos then
115+
table.insert(tokens, {type = "code", value = data:sub(codeStart, pos - 1)})
116+
end
117+
end
118+
end
119+
return tokens
120+
end
121+
122+
local function removeWhiteSpace(tokens)
123+
for _, token in ipairs(tokens) do
124+
if token.type == "code" then
125+
token.value = token.value:gsub("%s+", " ") -- Replace multiple spaces with a single space
126+
token.value = token.value:gsub("%s*([%(%){},;=%+%-%*/%^])%s*", "%1") -- Remove spaces around operators and punctuation
127+
token.value = token.value:gsub("^%s+", "") -- Remove leading whitespace
128+
token.value = token.value:gsub("%s+$", "") -- Remove trailing whitespace
129+
end
130+
end
131+
end
132+
133+
local tokens = tokenizeFile(f)
134+
135+
-- Get the size of the script before any squishing
136+
local beforeSize = f:seek()
137+
f:close()
138+
removeWhiteSpace(tokens)
139+
140+
-- Include the shebang on its own line if there is one
141+
local data = #tokens > 0 and tokens[1].type == "shebang" and table.remove(tokens, 1).value .. '\n' or ""
142+
143+
-- Concatenate data together
144+
for _, token in ipairs(tokens) do
145+
if token.type ~= "comment" then data = data .. token.value end
146+
end
147+
print(data)
148+
end
149+
150+
for _,v in ipairs(arg) do Squish(v) end

0 commit comments

Comments
 (0)