mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
plugins/console: Fixed tab completion after linenoise update.
* Can now cycle through candidates by repeatedly pushing Tab. * Also cleaned up Lua thread context object a little, and made it possible to pass any Lua object as a status value.
This commit is contained in:
parent
3f99355acc
commit
6dea565343
@ -43,8 +43,11 @@ function console.startplugin()
|
||||
local ln = require('linenoise')
|
||||
ln.setcompletion(
|
||||
function(c, str)
|
||||
status = str
|
||||
yield()
|
||||
ln.addcompletion(c, str)
|
||||
for k, v in pairs(status) do
|
||||
ln.addcompletion(c, v)
|
||||
end
|
||||
end)
|
||||
local ret = ln.linenoise('$PROMPT')
|
||||
if ret == nil then
|
||||
@ -191,11 +194,8 @@ function console.startplugin()
|
||||
return curstring, strs, expr:match("([%.:%w%(%)%[%]_]-)([:%.%[%(])" .. word .. "$")
|
||||
end
|
||||
|
||||
local function get_completions(line, endpos)
|
||||
local function get_completions(line)
|
||||
matches = {}
|
||||
local endstr = line:sub(endpos + 1, -1)
|
||||
line = line:sub(1, endpos)
|
||||
endstr = endstr or ""
|
||||
local start, word = line:match("^(.*[ \t\n\"\\'><=;:%+%-%*/%%^~#{}%(%)%[%].,])(.-)$")
|
||||
if not start then
|
||||
start = ""
|
||||
@ -206,16 +206,18 @@ function console.startplugin()
|
||||
|
||||
local str, strs, expr, sep = simplify_expression(line, word)
|
||||
contextual_list(expr, sep, str, word, strs)
|
||||
if #matches > 1 then
|
||||
print("\n")
|
||||
for k, v in pairs(matches) do
|
||||
print(v)
|
||||
end
|
||||
return "\x01" .. "-1"
|
||||
if #matches == 0 then
|
||||
return { line }
|
||||
elseif #matches == 1 then
|
||||
return start .. matches[1] .. endstr .. "\x01" .. (#start + #matches[1])
|
||||
return { start .. matches[1] }
|
||||
end
|
||||
return "\x01" .. "-1"
|
||||
print("")
|
||||
result = { }
|
||||
for k, v in pairs(matches) do
|
||||
print(v)
|
||||
table.insert(result, start .. v)
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
emu.register_start(function()
|
||||
@ -249,7 +251,7 @@ function console.startplugin()
|
||||
-- ln.refresh() FIXME: how to replicate this now that the API has been removed?
|
||||
end
|
||||
if conth.yield then
|
||||
conth:continue(get_completions(conth.result:match("([^\x01]*)\x01(.*)")))
|
||||
conth:continue(get_completions(conth.result))
|
||||
return
|
||||
elseif conth.busy then
|
||||
return
|
||||
|
@ -31,7 +31,9 @@
|
||||
#include "corestr.h"
|
||||
#include "notifier.h"
|
||||
|
||||
#include <condition_variable>
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
|
||||
@ -58,6 +60,91 @@ struct lua_engine::devenum
|
||||
|
||||
namespace {
|
||||
|
||||
struct thread_context
|
||||
{
|
||||
private:
|
||||
sol::object m_result;
|
||||
std::mutex m_guard;
|
||||
std::condition_variable m_sync;
|
||||
|
||||
public:
|
||||
bool m_busy = false;
|
||||
bool m_yield = false;
|
||||
|
||||
bool start(char const *scr)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_guard);
|
||||
if (m_busy)
|
||||
return false;
|
||||
|
||||
std::string script(scr);
|
||||
std::thread th(
|
||||
[this, script = std::string(scr)] ()
|
||||
{
|
||||
sol::state thstate;
|
||||
thstate.open_libraries();
|
||||
thstate["package"]["preload"]["zlib"] = &luaopen_zlib;
|
||||
thstate["package"]["preload"]["lfs"] = &luaopen_lfs;
|
||||
thstate["package"]["preload"]["linenoise"] = &luaopen_linenoise;
|
||||
sol::load_result res = thstate.load(script);
|
||||
if (res.valid())
|
||||
{
|
||||
sol::protected_function func = res.get<sol::protected_function>();
|
||||
thstate.set_function(
|
||||
"yield",
|
||||
[this, &thstate]()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_guard);
|
||||
m_result = thstate["status"];
|
||||
m_yield = true;
|
||||
m_sync.wait(lock);
|
||||
m_yield = false;
|
||||
thstate["status"] = m_result;
|
||||
});
|
||||
auto ret = func();
|
||||
if (ret.valid())
|
||||
{
|
||||
m_result = ret.get<sol::object>();
|
||||
}
|
||||
else
|
||||
{
|
||||
sol::error err = ret;
|
||||
osd_printf_error("[LUA ERROR] in thread: %s\n", err.what());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sol::error err = res;
|
||||
osd_printf_error("[LUA ERROR] when loading script for thread: %s\n", err.what());
|
||||
}
|
||||
m_busy = false; // FIXME: shouldn't do this when not holding the lock
|
||||
});
|
||||
m_busy = true;
|
||||
m_yield = false;
|
||||
th.detach();
|
||||
return true;
|
||||
}
|
||||
|
||||
void resume(sol::object val)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_guard);
|
||||
if (m_yield)
|
||||
{
|
||||
m_result = val;
|
||||
m_sync.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
sol::object result()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_guard);
|
||||
if (m_busy && !m_yield)
|
||||
return sol::lua_nil;
|
||||
else
|
||||
return m_result;
|
||||
}
|
||||
};
|
||||
|
||||
struct image_interface_formats
|
||||
{
|
||||
image_interface_formats(device_image_interface &i) : image(i) { }
|
||||
@ -883,70 +970,12 @@ void lua_engine::initialize()
|
||||
* thread.yield - check if thread is yielded
|
||||
*/
|
||||
|
||||
auto thread_type = emu.new_usertype<context>("thread", sol::call_constructor, sol::constructors<sol::types<>>());
|
||||
thread_type.set("start", [](context &ctx, const char *scr) {
|
||||
std::string script(scr);
|
||||
if (ctx.busy)
|
||||
return false;
|
||||
std::thread th([&ctx, script]() {
|
||||
sol::state thstate;
|
||||
thstate.open_libraries();
|
||||
thstate["package"]["preload"]["zlib"] = &luaopen_zlib;
|
||||
thstate["package"]["preload"]["lfs"] = &luaopen_lfs;
|
||||
thstate["package"]["preload"]["linenoise"] = &luaopen_linenoise;
|
||||
sol::load_result res = thstate.load(script);
|
||||
if(res.valid())
|
||||
{
|
||||
sol::protected_function func = res.get<sol::protected_function>();
|
||||
thstate["yield"] = [&ctx, &thstate]() {
|
||||
std::mutex m;
|
||||
std::unique_lock<std::mutex> lock(m);
|
||||
ctx.result = thstate["status"];
|
||||
ctx.yield = true;
|
||||
ctx.sync.wait(lock);
|
||||
ctx.yield = false;
|
||||
thstate["status"] = ctx.result;
|
||||
};
|
||||
auto ret = func();
|
||||
if (ret.valid())
|
||||
{
|
||||
const char *tmp = ret.get<const char *>();
|
||||
if (tmp != nullptr)
|
||||
ctx.result = tmp;
|
||||
else
|
||||
osd_printf_error("[LUA ERROR] in thread: return value must be string\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
sol::error err = ret;
|
||||
osd_printf_error("[LUA ERROR] in thread: %s\n", err.what());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sol::error err = res;
|
||||
osd_printf_error("[LUA ERROR] when loading script for thread: %s\n", err.what());
|
||||
}
|
||||
ctx.busy = false;
|
||||
});
|
||||
ctx.busy = true;
|
||||
ctx.yield = false;
|
||||
th.detach();
|
||||
return true;
|
||||
});
|
||||
thread_type.set("continue", [](context &ctx, const char *val) {
|
||||
if (!ctx.yield)
|
||||
return;
|
||||
ctx.result = val;
|
||||
ctx.sync.notify_all();
|
||||
});
|
||||
thread_type.set("result", sol::property([](context &ctx) -> std::string {
|
||||
if (ctx.busy && !ctx.yield)
|
||||
return "";
|
||||
return ctx.result;
|
||||
}));
|
||||
thread_type.set("busy", sol::readonly(&context::busy));
|
||||
thread_type.set("yield", sol::readonly(&context::yield));
|
||||
auto thread_type = emu.new_usertype<thread_context>("thread", sol::call_constructor, sol::constructors<sol::types<>>());
|
||||
thread_type.set_function("start", &thread_context::start);
|
||||
thread_type.set_function("continue", &thread_context::resume);
|
||||
thread_type["result"] = sol::property(&thread_context::result);
|
||||
thread_type["busy"] = sol::readonly(&thread_context::m_busy);
|
||||
thread_type["yield"] = sol::readonly(&thread_context::m_yield);
|
||||
|
||||
|
||||
/* save_item library
|
||||
|
@ -12,7 +12,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
@ -161,15 +160,6 @@ private:
|
||||
unsigned int stride;
|
||||
};
|
||||
|
||||
struct context
|
||||
{
|
||||
context() { busy = false; yield = false; }
|
||||
std::string result;
|
||||
std::condition_variable sync;
|
||||
bool busy;
|
||||
bool yield;
|
||||
};
|
||||
|
||||
// internal state
|
||||
lua_State *m_lua_state;
|
||||
std::unique_ptr<sol::state_view> m_sol_state;
|
||||
|
Loading…
Reference in New Issue
Block a user