1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
-- 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')
ln.setcompletion(function(c, str)
status = str
yield()
status:gsub('[^,]*', function(s) if s ~= '' then ln.addcompletion(c, s) end end)
end)
return ln.linenoise('\x1b[1;36m[MAME]\x1b[0m> ')
]]
local function find_unmatch(str, openpar, pair)
local done = false
if not str:match(openpar) then
return str
end
local tmp = str:gsub(pair, "")
if not tmp:match(openpar) then
return str
end
repeat
str = str:gsub(".-" .. openpar .. "(.*)", function (s)
tmp = s:gsub(pair, "")
if not tmp:match(openpar) then
done = true
end
return s
end)
until done or str == ""
return str
end
local function get_completions(str)
local comps = ","
local rest, dot, last = str:match("(.-)([.:]?)([^.:]*)$")
str = find_unmatch(str, "%(", "%b()")
str = find_unmatch(str, "%[", "%b[]")
local table = str:match("([%w_%.:%(%)%[%]]-)[:.][%w_]*$")
local err
if rest == "" or not table then
if dot == "" then
table = "_G"
else
return comps
end
end
err, tablef = pcall(load("return " .. table))
if (not err) or (not tablef) then
return comps
end
rest = rest .. dot
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("<eof>") 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
|