diff options
author | Björn Linse <bjorn.linse@gmail.com> | 2019-06-15 15:59:45 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-15 15:59:45 +0200 |
commit | 2f1a653a845680efab1a27f6411e36e8cd2f3696 (patch) | |
tree | fa562d5f83dbeb611d91cdf780bc1ce1e75a4408 /src | |
parent | 93f8c2793cf5020d6fca00b6f10e4a158578034f (diff) | |
parent | 64cdf9f78a9bfd4d08a9d9bf2df48a4b2f296190 (diff) | |
download | rneovim-2f1a653a845680efab1a27f6411e36e8cd2f3696.tar.gz rneovim-2f1a653a845680efab1a27f6411e36e8cd2f3696.tar.bz2 rneovim-2f1a653a845680efab1a27f6411e36e8cd2f3696.zip |
Merge pull request #10231 from bfredl/bufcb_end
api/lua: add on_detach to nvim_buf_attach
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/api/buffer.c | 21 | ||||
-rw-r--r-- | src/nvim/buffer_defs.h | 3 | ||||
-rw-r--r-- | src/nvim/buffer_updates.c | 23 | ||||
-rw-r--r-- | src/nvim/lua/executor.c | 11 |
4 files changed, 48 insertions, 10 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 81b3851c53..b0b65545ab 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -12,6 +12,7 @@ #include "nvim/api/buffer.h" #include "nvim/api/private/helpers.h" #include "nvim/api/private/defs.h" +#include "nvim/lua/executor.h" #include "nvim/vim.h" #include "nvim/buffer.h" #include "nvim/charset.h" @@ -137,24 +138,38 @@ Boolean nvim_buf_attach(uint64_t channel_id, if (is_lua && strequal("on_lines", k.data)) { if (v->type != kObjectTypeLuaRef) { api_set_error(err, kErrorTypeValidation, "callback is not a function"); - return false; + goto error; } cb.on_lines = v->data.luaref; v->data.integer = LUA_NOREF; } else if (is_lua && strequal("on_changedtick", k.data)) { if (v->type != kObjectTypeLuaRef) { api_set_error(err, kErrorTypeValidation, "callback is not a function"); - return false; + goto error; } cb.on_changedtick = v->data.luaref; v->data.integer = LUA_NOREF; + } else if (is_lua && strequal("on_detach", k.data)) { + if (v->type != kObjectTypeLuaRef) { + api_set_error(err, kErrorTypeValidation, "callback is not a function"); + goto error; + } + cb.on_detach = v->data.luaref; + v->data.integer = LUA_NOREF; } else { api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); - return false; + goto error; } } return buf_updates_register(buf, channel_id, cb, send_buffer); + +error: + // TODO(bfredl): ASAN build should check that the ref table is empty? + executor_free_luaref(cb.on_lines); + executor_free_luaref(cb.on_changedtick); + executor_free_luaref(cb.on_detach); + return false; } /// Deactivates buffer-update events on the channel. diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 117a9183a4..69cefe2247 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -456,8 +456,9 @@ typedef TV_DICTITEM_STRUCT(sizeof("changedtick")) ChangedtickDictItem; typedef struct { LuaRef on_lines; LuaRef on_changedtick; + LuaRef on_detach; } BufUpdateCallbacks; -#define BUF_UPDATE_CALLBACKS_INIT { LUA_NOREF, LUA_NOREF } +#define BUF_UPDATE_CALLBACKS_INIT { LUA_NOREF, LUA_NOREF, LUA_NOREF } #define BUF_HAS_QF_ENTRY 1 #define BUF_HAS_LL_ENTRY 2 diff --git a/src/nvim/buffer_updates.c b/src/nvim/buffer_updates.c index 2515e3f8aa..21efda9fd9 100644 --- a/src/nvim/buffer_updates.c +++ b/src/nvim/buffer_updates.c @@ -143,7 +143,21 @@ void buf_updates_unregister_all(buf_T *buf) } for (size_t i = 0; i < kv_size(buf->update_callbacks); i++) { - free_update_callbacks(kv_A(buf->update_callbacks, i)); + BufUpdateCallbacks cb = kv_A(buf->update_callbacks, i); + if (cb.on_detach != LUA_NOREF) { + Array args = ARRAY_DICT_INIT; + Object items[1]; + args.size = 1; + args.items = items; + + // the first argument is always the buffer handle + args.items[0] = BUFFER_OBJ(buf->handle); + + textlock++; + executor_exec_lua_cb(cb.on_detach, "detach", args, false); + textlock--; + } + free_update_callbacks(cb); } kv_destroy(buf->update_callbacks); kv_init(buf->update_callbacks); @@ -237,13 +251,14 @@ void buf_updates_send_changes(buf_T *buf, args.items[4] = INTEGER_OBJ(firstline - 1 + num_added); textlock++; - Object res = executor_exec_lua_cb(cb.on_lines, "lines", args); + Object res = executor_exec_lua_cb(cb.on_lines, "lines", args, true); textlock--; if (res.type == kObjectTypeBoolean && res.data.boolean == true) { free_update_callbacks(cb); keep = false; } + api_free_object(res); } if (keep) { kv_A(buf->update_callbacks, j++) = kv_A(buf->update_callbacks, i); @@ -276,13 +291,15 @@ void buf_updates_changedtick(buf_T *buf) args.items[1] = INTEGER_OBJ(buf_get_changedtick(buf)); textlock++; - Object res = executor_exec_lua_cb(cb.on_changedtick, "changedtick", args); + Object res = executor_exec_lua_cb(cb.on_changedtick, "changedtick", + args, true); textlock--; if (res.type == kObjectTypeBoolean && res.data.boolean == true) { free_update_callbacks(cb); keep = false; } + api_free_object(res); } if (keep) { kv_A(buf->update_callbacks, j++) = kv_A(buf->update_callbacks, i); diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 8cb282356a..ae872c1540 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -520,7 +520,8 @@ Object executor_exec_lua_api(const String str, const Array args, Error *err) return nlua_pop_Object(lstate, false, err); } -Object executor_exec_lua_cb(LuaRef ref, const char *name, Array args) +Object executor_exec_lua_cb(LuaRef ref, const char *name, Array args, + bool retval) { lua_State *const lstate = nlua_enter(); nlua_pushref(lstate, ref); @@ -529,7 +530,7 @@ Object executor_exec_lua_cb(LuaRef ref, const char *name, Array args) nlua_push_Object(lstate, args.items[i]); } - if (lua_pcall(lstate, (int)args.size+1, 1, 0)) { + if (lua_pcall(lstate, (int)args.size+1, retval ? 1 : 0, 0)) { // TODO(bfredl): callbacks:s might not always be msg-safe, for instance // lua callbacks for redraw events. Later on let the caller deal with the // error instead. @@ -538,7 +539,11 @@ Object executor_exec_lua_cb(LuaRef ref, const char *name, Array args) } Error err = ERROR_INIT; - return nlua_pop_Object(lstate, false, &err); + if (retval) { + return nlua_pop_Object(lstate, false, &err); + } else { + return NIL; + } } /// Run lua string |