Simplify command::* memory management
[lsnes.git] / src / lua / ibind.cpp
blob1d490827f46180eec4386d02e0ea25310a9dcc70
1 #include "lua/internal.hpp"
2 #include "core/instance.hpp"
3 #include "core/keymapper.hpp"
4 #include "core/command.hpp"
5 #include <vector>
7 class lua_inverse_bind
9 public:
10 lua_inverse_bind(lua::state& L, const std::string& name, const std::string& cmd);
11 static size_t overcommit(const std::string& name, const std::string& cmd) { return 0; }
12 std::string print()
14 return ikey.getname();
16 static int create(lua::state& L, lua::parameters& P);
17 private:
18 keyboard::invbind ikey;
21 class lua_command_binding : public command::base
23 public:
24 lua_command_binding(lua::state& _L, const std::string& cmd, int idx)
25 : command::base(CORE().command, cmd, false), L(_L)
27 L.pushlightuserdata(this);
28 L.pushvalue(idx);
29 L.rawset(LUA_REGISTRYINDEX);
31 void invoke(const std::string& arguments) throw(std::bad_alloc, std::runtime_error)
33 L.pushlightuserdata(this);
34 L.rawget(LUA_REGISTRYINDEX);
35 L.pushstring(arguments.c_str());
36 int r = L.pcall(1, 0, 0);
37 std::string err;
38 if(r == LUA_ERRRUN)
39 err = L.get_string(-1, "Lua command callback");
40 else if(r == LUA_ERRMEM)
41 err = "Out of memory";
42 else if(r == LUA_ERRERR)
43 err = "Double fault";
44 else
45 err = "Unknown error";
46 if(r) {
47 messages << "Error running lua command hook: " << err << std::endl;
50 private:
51 lua::state& L;
54 class lua_command_bind
56 public:
57 lua_command_bind(lua::state& L, const std::string& cmd, int idx1, int idx2);
58 static size_t overcommit(const std::string& cmd, int idx1, int idx2) { return 0; }
59 ~lua_command_bind();
60 std::string print()
62 if(b)
63 return a->get_name() + "," + b->get_name();
64 else
65 return a->get_name();
67 static int create(lua::state& L, lua::parameters& P);
68 private:
69 lua_command_binding* a;
70 lua_command_binding* b;
73 lua_inverse_bind::lua_inverse_bind(lua::state& L, const std::string& name, const std::string& cmd)
74 : ikey(CORE().mapper, cmd, "Lua‣" + name)
78 lua_command_bind::lua_command_bind(lua::state& L, const std::string& cmd, int idx1, int idx2)
80 if(L.type(idx2) == LUA_TFUNCTION) {
81 a = new lua_command_binding(L, "+" + cmd, idx1);
82 b = new lua_command_binding(L, "-" + cmd, idx2);
83 } else {
84 a = new lua_command_binding(L, cmd, idx1);
85 b = NULL;
89 lua_command_bind::~lua_command_bind()
91 delete a;
92 delete b;
95 namespace
97 int list_bindings(lua::state& L, lua::parameters& P)
99 std::string target;
101 P(P.optional(target, ""));
103 L.newtable();
104 for(auto key : CORE().mapper.get_bindings()) {
105 std::string _key = key;
106 std::string cmd = CORE().mapper.get(key);
107 if(target != "" && cmd != target)
108 continue;
109 L.pushlstring(_key.c_str(), _key.length());
110 L.pushlstring(cmd.c_str(), cmd.length());
111 L.rawset(-3);
113 for(auto key : CORE().mapper.get_controller_keys()) {
114 for(unsigned i = 0;; i++) {
115 std::string _key = key->get_string(i);
116 if(_key == "")
117 break;
118 std::string cmd = key->get_command();
119 _key = "|/" + _key;
120 if(target != "" && cmd != target)
121 continue;
122 L.pushlstring(_key.c_str(), _key.length());
123 L.pushlstring(cmd.c_str(), cmd.length());
124 L.rawset(-3);
127 return 1;
130 int get_alias(lua::state& L, lua::parameters& P)
132 std::string name;
134 P(name);
136 std::string a = CORE().command.get_alias_for(name);
137 if(a != "")
138 L.pushlstring(a);
139 else
140 L.pushnil();
141 return 1;
144 int set_alias(lua::state& L, lua::parameters& P)
146 std::string name, value;
148 P(name, P.optional(value, ""));
150 CORE().command.set_alias_for(name, value);
151 refresh_alias_binds();
152 return 0;
155 lua::functions alias_fns(lua_func_misc, "", {
156 {"list_bindings", list_bindings},
157 {"get_alias", get_alias},
158 {"set_alias", set_alias},
161 lua::_class<lua_inverse_bind> class_inverse_bind(lua_class_bind, "INVERSEBIND", {
162 {"new", lua_inverse_bind::create},
163 }, {}, &lua_inverse_bind::print);
164 lua::_class<lua_command_bind> class_command_bind(lua_class_bind, "COMMANDBIND", {
165 {"new", lua_command_bind::create},
166 }, {}, &lua_command_bind::print);
169 int lua_inverse_bind::create(lua::state& L, lua::parameters& P)
171 std::string name, command;
173 P(name, command);
175 lua::_class<lua_inverse_bind>::create(L, name, command);
176 return 1;
179 int lua_command_bind::create(lua::state& L, lua::parameters& P)
181 std::string name;
182 int lfn1 = 0, lfn2 = 0;
184 P(name, P.function(lfn1));
185 if(P.is_function() || P.is_novalue())
186 lfn2 = P.skip();
187 else
188 P.expected("function or nil");
189 lua::_class<lua_command_bind>::create(L.get_master(), name, lfn1, lfn2);
190 return 1;