Cleanup lua code by introducing lua::functions
[lsnes.git] / src / lua / ibind.cpp
blob026e47465739e7fb126e71a1443179a25f6b1ee6
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 std::string print()
12 return ikey.getname();
14 static int create(lua::state& L, lua::parameters& P);
15 private:
16 keyboard::invbind ikey;
19 class lua_command_binding : public command::base
21 public:
22 lua_command_binding(lua::state& _L, const std::string& cmd, int idx)
23 : command::base(lsnes_cmd, cmd), L(_L)
25 L.pushlightuserdata(this);
26 L.pushvalue(idx);
27 L.rawset(LUA_REGISTRYINDEX);
29 void invoke(const std::string& arguments) throw(std::bad_alloc, std::runtime_error)
31 L.pushlightuserdata(this);
32 L.rawget(LUA_REGISTRYINDEX);
33 L.pushstring(arguments.c_str());
34 int r = L.pcall(1, 0, 0);
35 std::string err;
36 if(r == LUA_ERRRUN)
37 err = L.get_string(-1, "Lua command callback");
38 else if(r == LUA_ERRMEM)
39 err = "Out of memory";
40 else if(r == LUA_ERRERR)
41 err = "Double fault";
42 else
43 err = "Unknown error";
44 if(r) {
45 messages << "Error running lua command hook: " << err << std::endl;
48 private:
49 lua::state& L;
52 class lua_command_bind
54 public:
55 lua_command_bind(lua::state& L, const std::string& cmd, int idx1, int idx2);
56 ~lua_command_bind();
57 std::string print()
59 if(b)
60 return a->get_name() + "," + b->get_name();
61 else
62 return a->get_name();
64 static int create(lua::state& L, lua::parameters& P);
65 private:
66 lua_command_binding* a;
67 lua_command_binding* b;
70 lua_inverse_bind::lua_inverse_bind(lua::state& L, const std::string& name, const std::string& cmd)
71 : ikey(lsnes_mapper, cmd, "Lua‣" + name)
75 lua_command_bind::lua_command_bind(lua::state& L, const std::string& cmd, int idx1, int idx2)
77 if(L.type(idx2) == LUA_TFUNCTION) {
78 a = new lua_command_binding(L, "+" + cmd, idx1);
79 b = new lua_command_binding(L, "-" + cmd, idx2);
80 } else {
81 a = new lua_command_binding(L, cmd, idx1);
82 b = NULL;
86 lua_command_bind::~lua_command_bind()
88 delete a;
89 delete b;
92 namespace
94 int list_bindings(lua::state& L, lua::parameters& P)
96 std::string target;
98 P(P.optional(target, ""));
100 L.newtable();
101 for(auto key : lsnes_mapper.get_bindings()) {
102 std::string _key = key;
103 std::string cmd = lsnes_mapper.get(key);
104 if(target != "" && cmd != target)
105 continue;
106 L.pushlstring(_key.c_str(), _key.length());
107 L.pushlstring(cmd.c_str(), cmd.length());
108 L.rawset(-3);
110 for(auto key : lsnes_mapper.get_controller_keys()) {
111 for(unsigned i = 0;; i++) {
112 std::string _key = key->get_string(i);
113 if(_key == "")
114 break;
115 std::string cmd = key->get_command();
116 _key = "|/" + _key;
117 if(target != "" && cmd != target)
118 continue;
119 L.pushlstring(_key.c_str(), _key.length());
120 L.pushlstring(cmd.c_str(), cmd.length());
121 L.rawset(-3);
124 return 1;
127 int get_alias(lua::state& L, lua::parameters& P)
129 std::string name;
131 P(name);
133 std::string a = lsnes_cmd.get_alias_for(name);
134 if(a != "")
135 L.pushlstring(a);
136 else
137 L.pushnil();
138 return 1;
141 int set_alias(lua::state& L, lua::parameters& P)
143 std::string name, value;
145 P(name, P.optional(value, ""));
147 lsnes_cmd.set_alias_for(name, value);
148 refresh_alias_binds();
149 return 0;
152 lua::functions alias_fns(lua_func_misc, "", {
153 {"list_bindings", list_bindings},
154 {"get_alias", get_alias},
155 {"set_alias", set_alias},
158 lua::_class<lua_inverse_bind> class_inverse_bind(lua_class_bind, "INVERSEBIND", {
159 {"new", lua_inverse_bind::create},
160 }, {}, &lua_inverse_bind::print);
161 lua::_class<lua_command_bind> class_command_bind(lua_class_bind, "COMMANDBIND", {
162 {"new", lua_command_bind::create},
163 }, {}, &lua_command_bind::print);
166 int lua_inverse_bind::create(lua::state& L, lua::parameters& P)
168 std::string name, command;
170 P(name, command);
172 lua_inverse_bind* b = lua::_class<lua_inverse_bind>::create(L, name, command);
173 return 1;
176 int lua_command_bind::create(lua::state& L, lua::parameters& P)
178 std::string name;
179 int lfn1 = 0, lfn2 = 0;
181 P(name, P.function(lfn1));
182 if(P.is_function() || P.is_novalue())
183 lfn2 = P.skip();
184 else
185 P.expected("function or nil");
186 lua_command_bind* b = lua::_class<lua_command_bind>::create(L.get_master(), name, lfn1, lfn2);
187 return 1;