Skip to content

Commit c637c6e

Browse files
committed
Added params.onInsert() which can be used to change what @insert inserts. Command line: Added an "insert" message.
1 parent b995ad3 commit c637c6e

File tree

3 files changed

+82
-28
lines changed

3 files changed

+82
-28
lines changed

misc/runTests.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,8 @@ doTest("Output values of different types", function()
196196
assert(not luaOut)
197197
end)
198198

199-
-- @Incomplete: Add tests for @insert etc.
199+
-- @Incomplete: Add tests for @insert and the other pp keywords.
200+
-- @Incomplete: Add test for params.onInsert().
200201

201202

202203

preprocess-cl.lua

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ exec lua "$0" "$@"
8686
inputPaths: Array of file paths to process. Paths can be added or removed freely.
8787
outputPaths: If the --outputpaths option is present this is an array of output paths for the respective path in inputPaths, otherwise it's nil.
8888
89+
"insert"
90+
Sent for each @insert statement. The handler is expected to return a Lua string.
91+
Arguments:
92+
path: The file being processed.
93+
name: The name of the resource to be inserted (could be a file path or anything).
94+
8995
"beforemeta"
9096
Sent before a file's metaprogram runs.
9197
Arguments:
@@ -289,6 +295,21 @@ pp.metaEnvironment.dataFromCommandLine = customData -- May be nil.
289295
-- Load message handler.
290296
local messageHandler = nil
291297

298+
local function hasMessageHandler(message)
299+
if not messageHandler then
300+
return false
301+
302+
elseif type(messageHandler) == "function" then
303+
return true
304+
305+
elseif type(messageHandler) == "table" then
306+
return messageHandler[message] ~= nil
307+
308+
else
309+
assert(false)
310+
end
311+
end
312+
292313
local function sendMessage(message, ...)
293314
if not messageHandler then
294315
return
@@ -330,7 +351,7 @@ if messageHandlerPath ~= "" then
330351
end
331352
end
332353
else
333-
errorline(messageHandlerPath..": File did not return a function or table.")
354+
errorline(messageHandlerPath..": File did not return a table or a function.")
334355
end
335356
end
336357

@@ -396,6 +417,23 @@ for i, pathIn in ipairs(pathsIn) do
396417
debug = isDebug,
397418
addLineNumbers = addLineNumbers,
398419

420+
onInsert = (hasMessageHandler("insert") or nil) and function(name)
421+
local lua = sendMessage("insert", pathIn, name)
422+
423+
-- onInsert() is expected to return a Lua string and so is the message handler.
424+
-- However, if the handler is a single catch-all function we allow the message
425+
-- to not be handled and we fall back to the default behavior of treating 'name'
426+
-- as a path to a file to be inserted. If we didn't allow this then it would be
427+
-- required for the "insert" message to be handled. I think it's better if the
428+
-- user can choose whether to handle a message or not!
429+
--
430+
if lua == nil and type(messageHandler) == "function" then
431+
return assert(pp.getFileContents(name))
432+
end
433+
434+
return lua
435+
end,
436+
399437
onBeforeMeta = messageHandler and function()
400438
sendMessage("beforemeta", pathIn)
401439
end,

preprocess.lua

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,6 @@ local isToken
210210
local loadLuaString, loadLuaFile
211211
local outputLineNumber, maybeOutputLineNumber
212212
local pack, unpack
213-
local parseStringlike
214213
local printf, printTokens, printTraceback
215214
local pushErrorHandler, pushErrorHandlerIfOverridingDefault, popErrorHandler
216215
local serialize, toLua
@@ -325,7 +324,7 @@ function errorAtToken(fileBuffers, tok, pos, agent, s, ...)
325324
errorInFile(fileBuffers[tok.file], tok.file, pos or tok.position, agent, s, ...)
326325
end
327326

328-
function parseStringlike(s, ptr)
327+
local function parseStringlike(s, ptr)
329328
local reprStart = ptr
330329
local reprEnd
331330

@@ -372,14 +371,14 @@ function parseStringlike(s, ptr)
372371
return tok, ptr
373372
end
374373

375-
local NUM_HEX_FRAC_EXP = ("^( 0x ([%dA-Fa-f]*) %.([%dA-Fa-f]+) [Pp]([-+]?[%dA-Fa-f]+) )"):gsub(" +", "")
376-
local NUM_HEX_FRAC = ("^( 0x ([%dA-Fa-f]*) %.([%dA-Fa-f]+) )"):gsub(" +", "")
377-
local NUM_HEX_EXP = ("^( 0x ([%dA-Fa-f]+) [Pp]([-+]?[%dA-Fa-f]+) )"):gsub(" +", "")
378-
local NUM_HEX = ("^( 0x [%dA-Fa-f]+ )"):gsub(" +", "")
379-
local NUM_DEC_FRAC_EXP = ("^( %d* %.%d+ [Ee][-+]?%d+ )"):gsub(" +", "")
380-
local NUM_DEC_FRAC = ("^( %d* %.%d+ )"):gsub(" +", "")
381-
local NUM_DEC_EXP = ("^( %d+ [Ee][-+]?%d+ )"):gsub(" +", "")
382-
local NUM_DEC = ("^( %d+ )"):gsub(" +", "")
374+
local NUM_HEX_FRAC_EXP = ("^( 0[Xx] ([%dA-Fa-f]*) %.([%dA-Fa-f]+) [Pp]([-+]?[%dA-Fa-f]+) )"):gsub(" +", "")
375+
local NUM_HEX_FRAC = ("^( 0[Xx] ([%dA-Fa-f]*) %.([%dA-Fa-f]+) )"):gsub(" +", "")
376+
local NUM_HEX_EXP = ("^( 0[Xx] ([%dA-Fa-f]+) [Pp]([-+]?[%dA-Fa-f]+) )"):gsub(" +", "")
377+
local NUM_HEX = ("^( 0[Xx] [%dA-Fa-f]+ )"):gsub(" +", "")
378+
local NUM_DEC_FRAC_EXP = ("^( %d* %.%d+ [Ee][-+]?%d+ )"):gsub(" +", "")
379+
local NUM_DEC_FRAC = ("^( %d* %.%d+ )"):gsub(" +", "")
380+
local NUM_DEC_EXP = ("^( %d+ [Ee][-+]?%d+ )"):gsub(" +", "")
381+
local NUM_DEC = ("^( %d+ )"):gsub(" +", "")
383382

384383
-- tokens = tokenize( lua, filePath, allowBacktickStrings [, allowPreprocessorTokens=false ] )
385384
function tokenize(s, path, allowBacktickStrings, allowMetaTokens)
@@ -584,7 +583,6 @@ function tokenize(s, path, allowBacktickStrings, allowMetaTokens)
584583
tok = {type="whitespace", representation=whitespace, value=whitespace}
585584

586585
-- Punctuation etc.
587-
-- "//", ">>", "<<",
588586
elseif s:find("^%.%.%.", ptr) then
589587
local repr = s:sub(ptr, ptr+2)
590588
tok = {type="punctuation", representation=repr, value=repr}
@@ -1425,7 +1423,7 @@ local function _processFileOrString(params, isFile)
14251423
luaUnprocessed = params.code
14261424
end
14271425

1428-
local fileBuffers = {[pathIn]=luaUnprocessed}
1426+
local fileBuffers = {[pathIn]=luaUnprocessed} -- Doesn't have to be the contents of files if params.onInsert() is defined.
14291427

14301428
local specialFirstLine, rest = luaUnprocessed:match"^(#[^\r\n]*\r?\n?)(.*)$"
14311429
if specialFirstLine then
@@ -1443,7 +1441,7 @@ local function _processFileOrString(params, isFile)
14431441
local lineCountCode = getLineCountWithCode(tokensRaw)
14441442
local tokenCount = 0 -- Set later.
14451443
local hasPreprocessorCode = false -- Set later.
1446-
local insertedPaths = {}
1444+
local insertedNames = {}
14471445

14481446
-- Do preprocessor keyword stuff.
14491447
local tokenStack = {}
@@ -1479,19 +1477,34 @@ local function _processFileOrString(params, isFile)
14791477
tokenStack[i] = nil
14801478
end
14811479

1482-
local toInsertPath = tokNext.value
1483-
local toInsertLua = fileBuffers[toInsertPath]
1480+
local toInsertName = tokNext.value
1481+
local toInsertLua = fileBuffers[toInsertName]
14841482

14851483
if not toInsertLua then
1486-
local err
1487-
toInsertLua, err = getFileContents(toInsertPath)
1488-
1489-
if not toInsertLua then
1490-
errorAtToken(fileBuffers, tokNext, tokNext.position+1, "Parser", "Could not read file: %s", err)
1484+
if params.onInsert then
1485+
toInsertLua = params.onInsert(toInsertName)
1486+
1487+
if type(toInsertLua) ~= "string" then
1488+
errorAtToken(
1489+
fileBuffers, tokNext, tokNext.position+1,
1490+
nil, "Expected a string from params.onInsert(). (Got %s)", type(toInsertLua)
1491+
)
1492+
end
1493+
1494+
else
1495+
local err
1496+
toInsertLua, err = getFileContents(toInsertName)
1497+
1498+
if not toInsertLua then
1499+
errorAtToken(
1500+
fileBuffers, tokNext, tokNext.position+1,
1501+
"Parser", "Could not read file: %s", tostring(err)
1502+
)
1503+
end
14911504
end
14921505

1493-
fileBuffers[toInsertPath] = toInsertLua
1494-
table.insert(insertedPaths, toInsertPath)
1506+
fileBuffers[toInsertName] = toInsertLua
1507+
table.insert(insertedNames, toInsertName)
14951508

14961509
else
14971510
insertCount = insertCount+1 -- Note: We don't count insertions of newly encountered files.
@@ -1501,12 +1514,12 @@ local function _processFileOrString(params, isFile)
15011514
fileBuffers, tokNext, tokNext.position+1, "Parser",
15021515
"Too many duplicate inserts. We may be stuck in a recursive loop."
15031516
.." (Unique files inserted so far: %s)",
1504-
table.concat(insertedPaths, ", ")
1517+
table.concat(insertedNames, ", ")
15051518
)
15061519
end
15071520
end
15081521

1509-
local toInsertTokens = tokenize(toInsertLua, toInsertPath, params.backtickStrings, true)
1522+
local toInsertTokens = tokenize(toInsertLua, toInsertName, params.backtickStrings, true)
15101523
for i = #toInsertTokens, 1, -1 do
15111524
table.insert(tokenStack, toInsertTokens[i])
15121525
end
@@ -1972,7 +1985,7 @@ local function _processFileOrString(params, isFile)
19721985
linesOfCode = lineCountCode,
19731986
tokenCount = tokenCount,
19741987
hasPreprocessorCode = hasPreprocessorCode,
1975-
insertedFiles = insertedPaths,
1988+
insertedFiles = insertedNames,
19761989
}
19771990

19781991
if params.onDone then params.onDone(info) end
@@ -2080,8 +2093,9 @@ local lib = {
20802093
--
20812094
-- backtickStrings = boolean -- [Optional] Enable the backtick (`) to be used as string literal delimiters. Backtick strings don't interpret any escape sequences and can't contain backticks.
20822095
--
2083-
-- onAfterMeta = function( luaString ) -- [Optional] Here you can modify and return the Lua code before it's written to 'pathOut'.
2096+
-- onInsert = function( name ) -- [Optional] Called for each @insert statement. It's expected to return a Lua string. By default 'name' is a path to a file to be inserted.
20842097
-- onBeforeMeta = function( ) -- [Optional] Called before the metaprogram runs.
2098+
-- onAfterMeta = function( luaString ) -- [Optional] Here you can modify and return the Lua code before it's written to 'pathOut'.
20852099
-- onError = function( error ) -- [Optional] You can use this to get traceback information. 'error' is the same value as what is returned from processFile().
20862100
--
20872101
processFile = processFile,
@@ -2101,6 +2115,7 @@ local lib = {
21012115
--
21022116
-- backtickStrings = boolean -- [Optional] Enable the backtick (`) to be used as string literal delimiters. Backtick strings don't interpret any escape sequences and can't contain backticks.
21032117
--
2118+
-- onInsert = function( name ) -- [Optional] Called for each @insert statement. It's expected to return a Lua string. By default 'name' is a path to a file to be inserted.
21042119
-- onBeforeMeta = function( ) -- [Optional] Called before the metaprogram runs.
21052120
-- onError = function( error ) -- [Optional] You can use this to get traceback information. 'error' is the same value as the second returned value from processString().
21062121
--

0 commit comments

Comments
 (0)