1018 g_free (word); |
1022 g_free (word); |
1019 return 0; |
1023 return 0; |
1020 } |
1024 } |
1021 |
1025 |
1022 /// main.command |
1026 /// main.command |
1023 /// Associates or breaks association between mcabber command name and lua function. |
1027 /// Associates mcabber command name and lua function. |
1024 /// To unregister command omit function argument. |
1028 /// As a completion you can also specify a string name (see completion type) instead of table, for non-builtin, you can just pass integer id. |
1025 /// If you specify a third argument, table (even empty), function will return completion group id or nothing. |
|
1026 /// You can also specify a string name (see completion type) instead of table, for non-builtin, you can just pass integer id. |
|
1027 /// Note, that for now there are no way to unregister completion group, so, resources can be exausted easily. |
1029 /// Note, that for now there are no way to unregister completion group, so, resources can be exausted easily. |
1028 /// Also note, that it ignores keys in a completion table. |
1030 /// Also note, that it ignores keys in a completion table. |
1029 /// A: string (command name), command function (optional), boolean (parse args flag, optional), table (completions, optional)/completion type (or integer comletion group id, optional) |
1031 /// A: string (command name), command function, boolean (parse args flag, optional), table (completions, optional)/completion type (or integer comletion group id, optional) |
1030 /// R: completion type (integer completion group id or string for builtin types, optional) |
1032 /// R: userdata (command object) |
1031 static int lua_main_command (lua_State *L) |
1033 static int lua_main_command (lua_State *L) |
1032 { |
1034 { |
1033 const char *name = luaL_checkstring (L, 1); // XXX: to_utf8? looks like no :/ |
1035 const char *name = luaL_checkstring (L, 1); // XXX: to_utf8? looks like no :/ |
1034 lua_command_callback_t *cb; |
1036 lua_command_t *cb; |
1035 int top = lua_gettop (L); |
1037 int top = lua_gettop (L); |
1036 if (top > 1 && !(top == 2 && lua_isnil (L, 2))) { // Register |
1038 guint cid = 0; |
1037 guint cid = 0; |
1039 int parse = 0; |
1038 int parse = 0; |
1040 luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected"); |
1039 luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected"); |
1041 |
1040 |
1042 if (top > 2) { // parse flag provided |
1041 if (top > 2) { // parse flag provided |
1043 parse = lua_toboolean (L, 3); |
1042 parse = lua_toboolean (L, 3); |
1044 |
1043 |
1045 if (top > 3) { // Completions provided |
1044 if (top > 3) { // Completions provided |
1046 if (lua_type (L, 4) == LUA_TTABLE) { |
1045 if (lua_type (L, 4) == LUA_TTABLE) { |
1047 cid = compl_new_category (); |
1046 cid = compl_new_category (); |
1048 if (cid) { |
1047 if (cid) { |
1049 lua_added_categories = g_slist_prepend (lua_added_categories, (gpointer) cid); |
1048 lua_added_categories = g_slist_prepend (lua_added_categories, (gpointer) cid); |
1050 lua_pushnil (L); |
1049 lua_pushnil (L); |
1051 while (lua_next (L, 4)) { |
1050 while (lua_next (L, 4)) { |
1052 char *word = to_utf8 (luaL_checkstring (L, -1)); |
1051 char *word = to_utf8 (luaL_checkstring (L, -1)); |
1053 compl_add_category_word (cid, word); |
1052 compl_add_category_word (cid, word); |
1054 lua_pop (L, 1); |
1053 lua_pop (L, 1); |
1055 g_free (word); |
1054 g_free (word); |
|
1055 } |
|
1056 } |
1056 } |
1057 } else |
1057 } |
1058 cid = luaL_checkenum (L, 4, lua_completion_type); |
1058 } else |
1059 } |
1059 cid = luaL_checkenum (L, 4, lua_completion_type); |
1060 } |
1060 } |
1061 |
1061 } |
1062 cb = luaL_malloc (L, sizeof (lua_command_callback_t)); |
1062 |
1063 lua_pushvalue (L, 2); |
1063 cb = lua_newuserdata (L, sizeof (lua_command_t)); |
1064 cb->reference = luaL_ref (L, LUA_REGISTRYINDEX); |
1064 luaL_getmetatable (L, "mcabber.command"); |
1065 cb->parse_args = parse; |
1065 lua_setmetatable (L, -2); |
1066 cb->L = L; |
1066 lua_pushvalue (L, 2); |
1067 cmd_add (name, "", cid, 0, (void (*) (char *p)) lua_main_command_handler, cb); |
1067 cb -> cbref = luaL_ref (L, LUA_REGISTRYINDEX); |
1068 |
1068 lua_pushvalue (L, -1); |
1069 lua_added_commands = g_slist_prepend (lua_added_commands, g_strdup (name)); |
1069 cb -> selfref = luaL_ref (L, LUA_REGISTRYINDEX); |
1070 |
1070 cb -> parse_args = parse; |
1071 if (cid) { |
1071 cb -> L = L; |
1072 luaL_pushenum (L, cid, lua_completion_type); |
1072 #ifdef HAVE_CMD_ID |
1073 return 1; |
1073 cb -> cmid = cmd_add (name, "", cid, 0, (void (*) (char *p)) lua_main_command_handler, cb); |
1074 } |
1074 #else |
1075 } else { // Unregister |
1075 lua_pushvalue (L, 1); |
1076 GSList *el = g_slist_find_custom (lua_added_commands, name, (GCompareFunc) g_strcmp0); |
1076 cb -> nameref = luaL_ref (L, LUA_REGISTRYINDEX); |
1077 |
1077 cmd_add (name, "", cid, 0, (void (*) (char *p)) lua_main_command_handler, cb); |
1078 cb = cmd_del (name); |
1078 #endif |
1079 if (cb) { |
1079 |
1080 luaL_unref (cb->L, LUA_REGISTRYINDEX, cb->reference); |
1080 return 1; |
1081 luaL_free (cb->L, cb); |
1081 } |
1082 } |
1082 |
1083 |
1083 static void lua_mcabber_unregister_command (lua_State *L, lua_command_t *cb) |
1084 if (el) { |
1084 { |
1085 g_free (el->data); |
1085 #ifdef HAVE_CMD_ID |
1086 lua_added_commands = g_slist_delete_link (lua_added_commands, el); |
1086 if (cb -> cmid) |
1087 } |
1087 cmd_del (cb -> cmid); |
|
1088 #else |
|
1089 const char *name; |
|
1090 |
|
1091 if (cb -> nameref == LUA_NOREF) |
|
1092 return; |
|
1093 |
|
1094 lua_rawgeti (L, LUA_REGISTRYINDEX, cb -> nameref); |
|
1095 name = lua_tostring (L, -1); |
|
1096 cmd_del (name); |
|
1097 lua_pop (L, 1); |
|
1098 #endif |
|
1099 } |
|
1100 |
|
1101 /// command:del |
|
1102 /// Unregisters given command from mcabber. Object will be destroyed later. |
|
1103 static int lua_mcabber_command_del (lua_State *L) |
|
1104 { |
|
1105 lua_command_t *cb = luaL_checkudata (L, 1, "mcabber.command"); |
|
1106 luaL_argcheck (L, cb != NULL, 1, "mcabber command object expected"); |
|
1107 lua_mcabber_unregister_command (L, cb); |
|
1108 if (cb -> selfref != LUA_NOREF) { |
|
1109 luaL_unref (L, LUA_REGISTRYINDEX, cb -> selfref); |
|
1110 cb -> selfref = LUA_NOREF; |
1088 } |
1111 } |
1089 return 0; |
1112 return 0; |
|
1113 } |
|
1114 |
|
1115 static int lua_mcabber_command_gc (lua_State *L) |
|
1116 { |
|
1117 lua_command_t *cb = luaL_checkudata (L, 1, "mcabber.command"); |
|
1118 luaL_argcheck (L, cb != NULL, 1, "mcabber command object expected"); |
|
1119 lua_mcabber_unregister_command (L, cb); |
|
1120 #ifndef HAVE_CMD_ID |
|
1121 if (cb -> nameref != LUA_NOREF) |
|
1122 luaL_unref (L, LUA_REGISTRYINDEX, cb -> nameref); |
|
1123 #endif |
|
1124 if (cb -> cbref != LUA_NOREF) |
|
1125 luaL_unref (L, LUA_REGISTRYINDEX, cb -> cbref); |
|
1126 return 0; |
|
1127 } |
|
1128 |
|
1129 static const luaL_Reg lua_mcabber_command_reg_m[] = { |
|
1130 { "del", lua_mcabber_command_del }, |
|
1131 { "__gc", lua_mcabber_command_gc }, |
|
1132 { NULL, NULL }, |
|
1133 }; |
|
1134 |
|
1135 static void lua_command_init (lua_State *L) |
|
1136 { |
|
1137 luaL_newmetatable (L, "mcabber.command"); |
|
1138 lua_pushvalue (L, -1); |
|
1139 lua_setfield (L, -2, "__index"); |
|
1140 luaL_register (L, NULL, lua_mcabber_command_reg_m); |
|
1141 lua_pop (L, 1); |
1090 } |
1142 } |
1091 |
1143 |
1092 // TIMER |
1144 // TIMER |
1093 |
1145 |
1094 typedef struct { |
1146 typedef struct { |