-- license:BSD-3-Clause -- copyright-holders:Carl local exports = {} exports.name = "console" exports.version = "0.0.1" exports.description = "Console plugin" exports.license = "The BSD 3-Clause License" exports.author = { name = "Carl" } local console = exports function console.startplugin() local conth = emu.thread() local started = false local ln = require("linenoise") local preload = false print(" _/ _/ _/_/ _/ _/ _/_/_/_/"); print(" _/_/ _/_/ _/ _/ _/_/ _/_/ _/ "); print(" _/ _/ _/ _/_/_/_/ _/ _/ _/ _/_/_/ "); print(" _/ _/ _/ _/ _/ _/ _/ "); print("_/ _/ _/ _/ _/ _/ _/_/_/_/ \n"); print(emu.app_name() .. " " .. emu.app_version(), "\nCopyright (C) Nicola Salmoria and the MAME team\n"); print(_VERSION, "\nCopyright (C) Lua.org, PUC-Rio\n"); -- linenoise isn't thread safe but that means history can handled here -- that also means that bad things will happen if anything outside lua tries to use it -- especially the completion callback ln.historysetmaxlen(10) local scr = "local ln = require('linenoise')\n" scr = scr .. "ln.setcompletion(function(c, str) status = str\n" scr = scr .. " yield()\n" -- coroutines can't yield in the middle of a callback so this is a real thread scr = scr .. " status:gsub('[^,]*', function(s) if s ~= '' then ln.addcompletion(c, s) end end)\n" scr = scr .. "end)\n" scr = scr .. "return ln.linenoise('\x1b[1;36m[MAME]\x1b[0m> ')" local function get_completions(str) local comps = "," local table = str:match("([(]?[%w.:()]-)[:.][%w_]*$") local rest, last = str:match("(.-[:.]?)([%w_]*)$") local err if table == "" or not table then table = "_G" end err, tablef = pcall(load("return " .. table)) if (not err) or (not tablef) then return comps end if type(tablef) == 'table' then for k, v in pairs(tablef) do if k:match("^" .. last) then comps = comps .. "," .. rest .. k end end end if type(tablef) == "userdata" then local tablef = getmetatable(tablef) for k, v in pairs(tablef) do if k:match("^" .. last) then comps = comps .. "," .. rest .. k end end end return comps end emu.register_periodic(function() if conth.yield then conth:continue(get_completions(conth.result)) return elseif conth.busy then return elseif started then local cmd = conth.result preload = false local func, err = load(cmd) if not func then if err:match("") then print("incomplete command") ln.preload(cmd) preload = true else print("error: ", err) end else local status status, err = pcall(func) if not status then print("error: ", err) end end if not preload then ln.historyadd(cmd) end end conth:start(scr) started = true end) end return exports