Add base support for Lua object overcommit
[lsnes.git] / src / lua / ibind.cpp
blobedf78cc0dbbf4dba99fe70329390c526e8761490
1 #include "lua/internal.hpp"
2 #include "core/keymapper.hpp"
3 #include "core/command.hpp"
4 #include <vector>
6 class lua_inverse_bind
8 public:
9 lua_inverse_bind(lua::state& L, const std::string& name, const std::string& cmd);
10 static size_t overcommit(const std::string& name, const std::string& cmd) { return 0; }
11 std::string print()
13 return ikey.getname();
15 static int create(lua::state& L, lua::parameters& P);
16 private:
17 keyboard::invbind ikey;
20 class lua_command_binding : public command::base
22 public:
23 lua_command_binding(lua::state& _L, const std::string& cmd, int idx)
24 : command::base(lsnes_cmd, cmd), L(_L)
26 L.pushlightuserdata(this);
27 L.pushvalue(idx);
28 L.rawset(LUA_REGISTRYINDEX);
30 void invoke(const std::string& arguments) throw(std::bad_alloc, std::runtime_error)
32 L.pushlightuserdata(this);
33 L.rawget(LUA_REGISTRYINDEX);
34 L.pushstring(arguments.c_str());
35 int r = L.pcall(1, 0, 0);
36 std::string err;
37 if(r == LUA_ERRRUN)
38 err = L.get_string(-1, "Lua command callback");
39 else if(r == LUA_ERRMEM)
40 err = "Out of memory";
41 else if(r == LUA_ERRERR)
42 err = "Double fault";
43 else
44 err = "Unknown error";
45 if(r) {
46 messages << "Error running lua command hook: " << err << std::endl;
49 private:
50 lua::state& L;
53 class lua_command_bind
55 public:
56 lua_command_bind(lua::state& L, const std::string& cmd, int idx1, int idx2);
57 static size_t overcommit(const std::string& cmd, int idx1, int idx2) { return 0; }
58 ~lua_command_bind();
59 std::string print()
61 if(b)
62 return a->get_name() + "," + b->get_name();
63 else
64 return a->get_name();
66 static int create(lua::state& L, lua::parameters& P);
67 private:
68 lua_command_binding* a;
69 lua_command_binding* b;
72 lua_inverse_bind::lua_inverse_bind(lua::state& L, const std::string& name, const std::string& cmd)
73 : ikey(lsnes_mapper, cmd, "Lua‣" + name)
77 lua_command_bind::lua_command_bind(lua::state& L, const std::string& cmd, int idx1, int idx2)
79 if(L.type(idx2) == LUA_TFUNCTION) {
80 a = new lua_command_binding(L, "+" + cmd, idx1);
81 b = new lua_command_binding(L, "-" + cmd, idx2);
82 } else {
83 a = new lua_command_binding(L, cmd, idx1);
84 b = NULL;
88 lua_command_bind::~lua_command_bind()
90 delete a;
91 delete b;
94 namespace
96 int list_bindings(lua::state& L, lua::parameters& P)
98 std::string target;
100 P(P.optional(target, ""));
102 L.newtable();
103 for(auto key : lsnes_mapper.get_bindings()) {
104 std::string _key = key;
105 std::string cmd = lsnes_mapper.get(key);
106 if(target != "" && cmd != target)
107 continue;
108 L.pushlstring(_key.c_str(), _key.length());
109 L.pushlstring(cmd.c_str(), cmd.length());
110 L.rawset(-3);
112 for(auto key : lsnes_mapper.get_controller_keys()) {
113 for(unsigned i = 0;; i++) {
114 std::string _key = key->get_string(i);
115 if(_key == "")
116 break;
117 std::string cmd = key->get_command();
118 _key = "|/" + _key;
119 if(target != "" && cmd != target)
120 continue;
121 L.pushlstring(_key.c_str(), _key.length());
122 L.pushlstring(cmd.c_str(), cmd.length());
123 L.rawset(-3);
126 return 1;
129 int get_alias(lua::state& L, lua::parameters& P)
131 std::string name;
133 P(name);
135 std::string a = lsnes_cmd.get_alias_for(name);
136 if(a != "")
137 L.pushlstring(a);
138 else
139 L.pushnil();
140 return 1;
143 int set_alias(lua::state& L, lua::parameters& P)
145 std::string name, value;
147 P(name, P.optional(value, ""));
149 lsnes_cmd.set_alias_for(name, value);
150 refresh_alias_binds();
151 return 0;
154 lua::functions alias_fns(lua_func_misc, "", {
155 {"list_bindings", list_bindings},
156 {"get_alias", get_alias},
157 {"set_alias", set_alias},
160 lua::_class<lua_inverse_bind> class_inverse_bind(lua_class_bind, "INVERSEBIND", {
161 {"new", lua_inverse_bind::create},
162 }, {}, &lua_inverse_bind::print);
163 lua::_class<lua_command_bind> class_command_bind(lua_class_bind, "COMMANDBIND", {
164 {"new", lua_command_bind::create},
165 }, {}, &lua_command_bind::print);
168 int lua_inverse_bind::create(lua::state& L, lua::parameters& P)
170 std::string name, command;
172 P(name, command);
174 lua::_class<lua_inverse_bind>::create(L, name, command);
175 return 1;
178 int lua_command_bind::create(lua::state& L, lua::parameters& P)
180 std::string name;
181 int lfn1 = 0, lfn2 = 0;
183 P(name, P.function(lfn1));
184 if(P.is_function() || P.is_novalue())
185 lfn2 = P.skip();
186 else
187 P.expected("function or nil");
188 lua::_class<lua_command_bind>::create(L.get_master(), name, lfn1, lfn2);
189 return 1;