forked from qt-creator/qt-creator
Lua: Replace lua repl script
Change-Id: Iea236081b9cfecd29d7c5c2290570010c9a83276 Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
@@ -24,6 +24,7 @@
|
|||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QListView>
|
#include <QListView>
|
||||||
|
#include <QPainter>
|
||||||
#include <QStringListModel>
|
#include <QStringListModel>
|
||||||
#include <QStyledItemDelegate>
|
#include <QStyledItemDelegate>
|
||||||
|
|
||||||
@@ -78,7 +79,7 @@ public:
|
|||||||
{
|
{
|
||||||
auto label = new QLabel(parent);
|
auto label = new QLabel(parent);
|
||||||
const QString text = index.data().toString();
|
const QString text = index.data().toString();
|
||||||
label->setText(text);
|
label->setText(text.startsWith("__ERROR__") ? text.mid(9) : text);
|
||||||
label->setFont(option.font);
|
label->setFont(option.font);
|
||||||
label->setTextInteractionFlags(
|
label->setTextInteractionFlags(
|
||||||
Qt::TextInteractionFlag::TextSelectableByMouse
|
Qt::TextInteractionFlag::TextSelectableByMouse
|
||||||
@@ -87,6 +88,29 @@ public:
|
|||||||
label->setSelection(0, text.size());
|
label->setSelection(0, text.size());
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index)
|
||||||
|
const override
|
||||||
|
{
|
||||||
|
QStyleOptionViewItem opt = option;
|
||||||
|
initStyleOption(&opt, index);
|
||||||
|
|
||||||
|
bool isError = opt.text.startsWith("__ERROR__");
|
||||||
|
|
||||||
|
if (isError)
|
||||||
|
opt.text = opt.text.mid(9);
|
||||||
|
|
||||||
|
if (opt.state & QStyle::State_Selected) {
|
||||||
|
painter->fillRect(opt.rect, opt.palette.highlight());
|
||||||
|
painter->setPen(opt.palette.highlightedText().color());
|
||||||
|
} else if (isError) {
|
||||||
|
painter->setPen(creatorColor(Theme::Token_Notification_Danger));
|
||||||
|
} else {
|
||||||
|
painter->setPen(opt.palette.text().color());
|
||||||
|
}
|
||||||
|
|
||||||
|
painter->drawText(opt.rect, opt.displayAlignment, opt.text);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class LuaReplView : public QListView
|
class LuaReplView : public QListView
|
||||||
@@ -135,6 +159,7 @@ public:
|
|||||||
m_model.setStringList(m_model.stringList() << msgs);
|
m_model.setStringList(m_model.stringList() << msgs);
|
||||||
scrollToBottom();
|
scrollToBottom();
|
||||||
};
|
};
|
||||||
|
lua["LuaCopyright"] = LUA_COPYRIGHT;
|
||||||
|
|
||||||
sol::table async = lua.script("return require('async')", "_ilua_").get<sol::table>();
|
sol::table async = lua.script("return require('async')", "_ilua_").get<sol::table>();
|
||||||
sol::function wrap = async["wrap"];
|
sol::function wrap = async["wrap"];
|
||||||
|
@@ -1,359 +1,61 @@
|
|||||||
-- ilua.lua
|
|
||||||
-- A more friendly Lua interactive prompt
|
|
||||||
-- doesn't need '='
|
|
||||||
-- will try to print out tables recursively, subject to the pretty_print_limit value.
|
|
||||||
-- Steve Donovan, 2007
|
|
||||||
--
|
|
||||||
local pretty_print_limit = 20
|
|
||||||
local max_depth = 7
|
|
||||||
local table_clever = true
|
|
||||||
local prompt = '> '
|
|
||||||
local verbose = false
|
|
||||||
local strict = true
|
|
||||||
-- suppress strict warnings
|
|
||||||
_ = true
|
|
||||||
|
|
||||||
-- imported global functions
|
|
||||||
local sub = string.sub
|
|
||||||
local match = string.match
|
|
||||||
local find = string.find
|
|
||||||
local push = table.insert
|
|
||||||
local pop = table.remove
|
|
||||||
local append = table.insert
|
|
||||||
local concat = table.concat
|
|
||||||
local floor = math.floor
|
|
||||||
local write = io.write
|
|
||||||
local read = io.read
|
|
||||||
|
|
||||||
local collisions = {}
|
|
||||||
local G_LIB = {}
|
|
||||||
local declared = {}
|
|
||||||
local line_handler_fn, global_handler_fn
|
|
||||||
local print_handlers = {}
|
|
||||||
|
|
||||||
ilua = {}
|
|
||||||
local num_prec
|
|
||||||
local num_all
|
|
||||||
|
|
||||||
local jstack = {}
|
|
||||||
|
|
||||||
local function oprint(...)
|
|
||||||
print(...)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function join(tbl, delim, limit, depth)
|
|
||||||
if not limit then limit = pretty_print_limit end
|
|
||||||
if not depth then depth = max_depth end
|
|
||||||
local n = #tbl
|
|
||||||
local res = ''
|
|
||||||
local k = 0
|
|
||||||
-- very important to avoid disgracing ourselves with circular referencs...
|
|
||||||
if #jstack > depth then
|
|
||||||
return "..."
|
|
||||||
end
|
|
||||||
for i, t in ipairs(jstack) do
|
|
||||||
if tbl == t then
|
|
||||||
return "<self>"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
push(jstack, tbl)
|
|
||||||
-- this is a hack to work out if a table is 'list-like' or 'map-like'
|
|
||||||
-- you can switch it off with ilua.table_options {clever = false}
|
|
||||||
local is_list
|
|
||||||
if table_clever then
|
|
||||||
local index1 = n > 0 and tbl[1]
|
|
||||||
local index2 = n > 1 and tbl[2]
|
|
||||||
is_list = index1 and index2
|
|
||||||
end
|
|
||||||
if is_list then
|
|
||||||
for i, v in ipairs(tbl) do
|
|
||||||
res = res .. delim .. val2str(v)
|
|
||||||
k = k + 1
|
|
||||||
if k > limit then
|
|
||||||
res = res .. " ... "
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
for key, v in pairs(tbl) do
|
|
||||||
if type(key) == 'number' then
|
|
||||||
key = '[' .. tostring(key) .. ']'
|
|
||||||
else
|
|
||||||
key = tostring(key)
|
|
||||||
end
|
|
||||||
res = res .. delim .. key .. '=' .. val2str(v)
|
|
||||||
k = k + 1
|
|
||||||
if k > limit then
|
|
||||||
res = res .. " ... "
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
pop(jstack)
|
|
||||||
return sub(res, 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function val2str(val)
|
|
||||||
local tp = type(val)
|
|
||||||
if print_handlers[tp] then
|
|
||||||
local s = print_handlers[tp](val)
|
|
||||||
return s or '?'
|
|
||||||
end
|
|
||||||
if tp == 'function' then
|
|
||||||
return tostring(val)
|
|
||||||
elseif tp == 'table' then
|
|
||||||
if val.__tostring then
|
|
||||||
return tostring(val)
|
|
||||||
else
|
|
||||||
return '{' .. join(val, ',') .. '}'
|
|
||||||
end
|
|
||||||
elseif tp == 'string' then
|
|
||||||
return "'" .. val .. "'"
|
|
||||||
elseif tp == 'number' then
|
|
||||||
-- we try only to apply floating-point precision for numbers deemed to be floating-point,
|
|
||||||
-- unless the 3rd arg to precision() is true.
|
|
||||||
if num_prec and (num_all or floor(val) ~= val) then
|
|
||||||
return num_prec:format(val)
|
|
||||||
else
|
|
||||||
return tostring(val)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
return tostring(val)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function _pretty_print(...)
|
|
||||||
local arg <const> = table.pack(...)
|
|
||||||
for i, val in ipairs(arg) do
|
|
||||||
oprint(val2str(val))
|
|
||||||
end
|
|
||||||
_G['_'] = arg[1]
|
|
||||||
end
|
|
||||||
|
|
||||||
function compile(line)
|
|
||||||
if verbose then oprint(line) end
|
|
||||||
local f, err = load(line, 'local')
|
|
||||||
return err, f
|
|
||||||
end
|
|
||||||
|
|
||||||
function evaluate(chunk)
|
|
||||||
local ok, res = pcall(chunk)
|
|
||||||
if not ok then
|
|
||||||
return res
|
|
||||||
end
|
|
||||||
return nil -- meaning, fine!
|
|
||||||
end
|
|
||||||
|
|
||||||
function eval_lua(line)
|
|
||||||
-- is the line handler interested?
|
|
||||||
if line_handler_fn then
|
|
||||||
line = line_handler_fn(line)
|
|
||||||
-- returning nil here means that the handler doesn't want
|
|
||||||
-- Lua to see the string
|
|
||||||
if not line then return end
|
|
||||||
end
|
|
||||||
-- is it an expression?
|
|
||||||
local err, chunk = compile('_pretty_print(' .. line .. ')')
|
|
||||||
if err then
|
|
||||||
-- otherwise, a statement?
|
|
||||||
err, chunk = compile(line)
|
|
||||||
end
|
|
||||||
-- if compiled ok, then evaluate the chunk
|
|
||||||
if not err then
|
|
||||||
err = evaluate(chunk)
|
|
||||||
end
|
|
||||||
-- if there was any error, print it out
|
|
||||||
if err then
|
|
||||||
oprint(err)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function quit(code, msg)
|
|
||||||
io.stderr:write(msg, '\n')
|
|
||||||
os.exit(code)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- functions available in scripts
|
|
||||||
function ilua.precision(len, prec, all)
|
|
||||||
if not len then
|
|
||||||
num_prec = nil
|
|
||||||
else
|
|
||||||
num_prec = '%' .. len .. '.' .. prec .. 'f'
|
|
||||||
end
|
|
||||||
num_all = all
|
|
||||||
end
|
|
||||||
|
|
||||||
function ilua.table_options(t)
|
|
||||||
if t.limit then pretty_print_limit = t.limit end
|
|
||||||
if t.depth then max_depth = t.depth end
|
|
||||||
if t.clever ~= nil then table_clever = t.clever end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- inject @tbl into the global namespace
|
|
||||||
function ilua.import(tbl, dont_complain, lib)
|
|
||||||
lib = lib or '<unknown>'
|
|
||||||
if type(tbl) == 'table' then
|
|
||||||
for k, v in pairs(tbl) do
|
|
||||||
local key = rawget(_G, k)
|
|
||||||
-- NB to keep track of collisions!
|
|
||||||
if key and k ~= '_M' and k ~= '_NAME' and k ~= '_PACKAGE' and k ~= '_VERSION' then
|
|
||||||
append(collisions, { k, lib, G_LIB[k] })
|
|
||||||
end
|
|
||||||
_G[k] = v
|
|
||||||
G_LIB[k] = lib
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not dont_complain and #collisions > 0 then
|
|
||||||
for i, coll in ipairs(collisions) do
|
|
||||||
local name, lib, oldlib = coll[1], coll[2], coll[3]
|
|
||||||
write('warning: ', lib, '.', name, ' overwrites ')
|
|
||||||
if oldlib then
|
|
||||||
write(oldlib, '.', name, '\n')
|
|
||||||
else
|
|
||||||
write('global ', name, '\n')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function ilua.print_handler(name, handler)
|
|
||||||
print_handlers[name] = handler
|
|
||||||
end
|
|
||||||
|
|
||||||
function ilua.line_handler(handler)
|
|
||||||
line_handler_fn = handler
|
|
||||||
end
|
|
||||||
|
|
||||||
function ilua.global_handler(handler)
|
|
||||||
global_handler_fn = handler
|
|
||||||
end
|
|
||||||
|
|
||||||
function ilua.print_variables()
|
|
||||||
for name, v in pairs(declared) do
|
|
||||||
print(name, type(_G[name]))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--
|
|
||||||
-- strict.lua
|
|
||||||
-- checks uses of undeclared global variables
|
|
||||||
-- All global variables must be 'declared' through a regular assignment
|
|
||||||
-- (even assigning nil will do) in a main chunk before being used
|
|
||||||
-- anywhere.
|
|
||||||
--
|
|
||||||
local function set_strict()
|
|
||||||
local mt = getmetatable(_G)
|
|
||||||
if mt == nil then
|
|
||||||
mt = {}
|
|
||||||
setmetatable(_G, mt)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function what()
|
|
||||||
local d = debug.getinfo(3, "S")
|
|
||||||
return d and d.what or "C"
|
|
||||||
end
|
|
||||||
|
|
||||||
mt.__newindex = function(t, n, v)
|
|
||||||
declared[n] = true
|
|
||||||
rawset(t, n, v)
|
|
||||||
end
|
|
||||||
|
|
||||||
mt.__index = function(t, n)
|
|
||||||
if not declared[n] and what() ~= "C" then
|
|
||||||
local lookup = global_handler_fn and global_handler_fn(n)
|
|
||||||
if not lookup then
|
|
||||||
error("variable '" .. n .. "' is not declared", 2)
|
|
||||||
else
|
|
||||||
return lookup
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return rawget(t, n)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Initial operations which may not succeed!
|
|
||||||
-- try to bring in any ilua configuration file; don't complain if this is unsuccessful
|
|
||||||
pcall(function()
|
|
||||||
require 'ilua-defs'
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- process command-line parameters
|
|
||||||
if arg then
|
|
||||||
local i = 1
|
|
||||||
|
|
||||||
local function parm_value(opt, parm, def)
|
|
||||||
local val = parm:sub(3)
|
|
||||||
if #val == 0 then
|
|
||||||
i = i + 1
|
|
||||||
if i > #arg then
|
|
||||||
if not def then
|
|
||||||
quit(-1, "expecting parameter for option '-" .. opt .. "'")
|
|
||||||
else
|
|
||||||
return def
|
|
||||||
end
|
|
||||||
end
|
|
||||||
val = arg[i]
|
|
||||||
end
|
|
||||||
return val
|
|
||||||
end
|
|
||||||
|
|
||||||
while i <= #arg do
|
|
||||||
local v = arg[i]
|
|
||||||
local opt = v:sub(1, 1)
|
|
||||||
if opt == '-' then
|
|
||||||
opt = v:sub(2, 2)
|
|
||||||
if opt == 'h' then
|
|
||||||
quit(0, "ilua (-l lib) (-L lib) (lua files)")
|
|
||||||
elseif opt == 'l' then
|
|
||||||
require(parm_value(opt, v))
|
|
||||||
elseif opt == 'L' then
|
|
||||||
local lib = parm_value(opt, v)
|
|
||||||
local tbl = require(lib)
|
|
||||||
-- we cannot always trust require to return the table!
|
|
||||||
if type(tbl) ~= 'table' then
|
|
||||||
tbl = _G[lib]
|
|
||||||
end
|
|
||||||
ilua.import(tbl, true, lib)
|
|
||||||
elseif opt == 't' or opt == 'T' then
|
|
||||||
local file
|
|
||||||
if opt == 'T' then
|
|
||||||
file = 'ilua_' .. os.date('%y_%m_%d_%H_%M') .. '.log'
|
|
||||||
else
|
|
||||||
file = parm_value(opt, v, "ilua.log")
|
|
||||||
end
|
|
||||||
print('saving transcript "' .. file .. '"')
|
|
||||||
elseif opt == 's' then
|
|
||||||
strict = false
|
|
||||||
elseif opt == 'v' then
|
|
||||||
verbose = true
|
|
||||||
end
|
|
||||||
else -- a plain file to be executed immediately
|
|
||||||
dofile(v)
|
|
||||||
end
|
|
||||||
i = i + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
print 'ILUA: Lua 5.4.6 Copyright (C) 1994-2007 Lua.org, PUC-Rio'
|
|
||||||
|
|
||||||
-- any import complaints?
|
|
||||||
ilua.import()
|
|
||||||
|
|
||||||
-- enable 'not declared' error
|
|
||||||
if strict then
|
|
||||||
set_strict()
|
|
||||||
end
|
|
||||||
|
|
||||||
local a = require('async')
|
local a = require('async')
|
||||||
|
local inspect = require('inspect')
|
||||||
|
|
||||||
a.sync(function()
|
local prompt = '> '
|
||||||
local line = a.wait(readline(prompt))
|
|
||||||
|
|
||||||
while line do
|
local function errHandler(err)
|
||||||
---if line == 'quit' then break end
|
return debug.traceback(err, 2)
|
||||||
eval_lua(line)
|
|
||||||
---saveline(line)
|
|
||||||
line = a.wait(readline(prompt))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---Returns the number of arguments and a table with the arguments
|
||||||
|
---We need this because select('#', ...) is the only way to figure out the number of arguments
|
||||||
|
---because #table will not count nil values
|
||||||
|
---@return integer nArguments The number of arguments provided to wrap(...)
|
||||||
|
---@return table arguments The arguments packed a table
|
||||||
|
local function wrap(...) return select('#', ...), { ... } end
|
||||||
|
|
||||||
|
local function eval(code)
|
||||||
|
if #code == 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
--We load the code once as is, and once by adding a return statement in front of it
|
||||||
|
local asFunc, errFunc = load(code)
|
||||||
|
local asReturn = load('return ' .. code)
|
||||||
|
--If the code with return statement did not compile we will use the code without it
|
||||||
|
if not asReturn then
|
||||||
|
--If the code without the return did not compile either we print an error
|
||||||
|
if not asFunc then
|
||||||
|
print("__ERROR__" .. errFunc)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
asReturn = asFunc
|
||||||
|
end
|
||||||
|
|
||||||
|
--We call the compiled code in protected mode, which will capture and errors thrown by it.
|
||||||
|
local numberOfReturnValues, result = wrap(xpcall(asReturn, errHandler))
|
||||||
|
|
||||||
|
--result[1] contains true or false depending on whether the function ran successfully
|
||||||
|
if not result[1] then
|
||||||
|
print("__ERROR__" .. result[2])
|
||||||
|
--numberOfReturnValues is the real number of values returned from xpcall
|
||||||
|
elseif numberOfReturnValues > 1 then
|
||||||
|
--We concatenate all the return values into a single string
|
||||||
|
local str = ""
|
||||||
|
--Skip the first value which is the boolean from xpcall
|
||||||
|
for i = 2, numberOfReturnValues do
|
||||||
|
str = str .. inspect(result[i]) .. '\t'
|
||||||
|
end
|
||||||
|
print(str)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
print(LuaCopyright)
|
||||||
|
|
||||||
|
--Main Loop
|
||||||
|
a.sync(function()
|
||||||
|
repeat
|
||||||
|
local input = a.wait(readline(prompt))
|
||||||
|
eval(input)
|
||||||
|
until false
|
||||||
end)()
|
end)()
|
||||||
|
Reference in New Issue
Block a user