[luatex] REPL
Robert Krug
destiny6 at mac.com
Mon Jan 11 23:32:49 CET 2021
Greetings
Here is a simple REPL for use with LuaTeX. I started with work by Rob Hoelz <rob at hoelz.ro> and cut out all the bells and whistles. To use it, save this to a lua file and load it. The REPL can be started by invoking repl(). I find this very handy to explore what is going on with LuaTeX.
Robert
P.S. I use this within Emacs. I assume it will work anywhere with a terminal type interface.
==========
-- Copyright (c) 2011-2015 Rob Hoelz <rob at hoelz.ro>
--
-- Further hacked by others.
--
-- Permission is hereby granted, free of charge, to any person
-- obtaining a copy of this software and associated documentation
-- files (the "Software"), to deal in the Software without
-- restriction, including without limitation the rights to use, copy,
-- modify, merge, publish, distribute, sublicense, and/or sell copies
-- of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be
-- included in all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-- SOFTWARE.
-- @class repl
--- This module implements the core functionality of a REPL.
repl = {VERSION = 0.9 }
repl_buffer = ''
local error = error
local function gather_results(success, ...)
local n = select('#', ...)
return success, { n = n, ... }
end
--- Uses the compilation error to determine whether or not further input
--- is pending after the last line. That is, is this a fraction of a
--- statement.
--- Rather crude, but this seems to work.
local function detectcontinue(err)
return string.match(err, "'<eof>'$") or string.match(err, "<eof>$")
end
local function compilechunk(chunk)
-- If this is an expression, rather than a statement, we should
-- get a function, in f, to return the value of that expression.
local f, err = load('return ' .. chunk, 'REPL')
-- for statements (or fractions thereof).
if not f then
f, err = load(chunk, 'REPL')
end
return f, err
end
-- @param results The results to display. The results are a table,
-- with the integer keys containing the results, and the 'n' key
-- containing the highest integer key.
local function displayresults(results)
if results.n == 0 then return end
print(table.unpack(results, 1, results.n))
end
local function displayerror(err)
print(err)
end
--- Evaluates a line of input, and displays return value(s).
local function handleline(line)
local chunk = repl_buffer .. line
local f, err = compilechunk(chunk)
if f then
-- We have a (presumed) function. Try to call it, and display the
-- results, or error.
repl_buffer = ''
local success, results = gather_results(xpcall(f, function(...) return debug.traceback(...) end))
if success then
displayresults(results)
else
displayerror(results[1])
end
else
-- Is this a (presumed) fraction of a statement, or an error?
if detectcontinue(err) then
-- Presumably, a fraction of a statement.
repl_buffer = chunk .. '\n'
return 2
else
-- An error. Clear the buffer, so this does not keep happening.
repl_buffer = ''
displayerror(err)
end
end
return 1
end
local function prompt(level)
local prompt
if level == 1 then prompt=">" else prompt=">>" end
io.write(prompt)
end
--- Run a REPL loop in a synchronous fashion.
function repl()
print()
prompt(1)
for line in io.stdin:lines() do
local level = handleline(line)
prompt(level)
end
end
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://tug.org/pipermail/luatex/attachments/20210111/8c4c25a7/attachment.html>
More information about the luatex
mailing list.