vis
a vi-like editor based on Plan 9's structural regular expressions
git clone https://9o.is/git/vis.git
commit 9f0dc592ee9b7d361c4bd7b19134e2696cff16d9 parent 0e5684e431843acc781930eda9d2c5e1adcfd5ff Author: Marc André Tanner <mat@brain-dump.org> Date: Mon, 19 Dec 2016 10:28:16 +0100 vis-lua: implement file.marks[] array We need to retrieve a pointer to the File struct but can not store it directly in the Lua uservalue because the address is already used for the regular file object (of type vis.file). For now we use file->marks as an address and then use offsetof to retrieve the start of the struct. Diffstat:
| M | vis-lua.c | | | 65 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 65 insertions(+), 0 deletions(-)
diff --git a/vis-lua.c b/vis-lua.c @@ -11,6 +11,7 @@ * @license ISC * @release RELEASE */ +#include <stddef.h> #include <stdarg.h> #include <stdio.h> #include <string.h> @@ -416,6 +417,11 @@ static void *obj_ref_check(lua_State *L, int idx, const char *type) { return obj; } +static void *obj_ref_check_containerof(lua_State *L, int idx, const char *type, size_t offset) { + void *obj = obj_ref_check(L, idx, type); + return obj ? ((char*)obj-offset) : obj; +} + static void *obj_lightref_new(lua_State *L, void *addr, const char *type) { if (!addr) return NULL; @@ -1425,6 +1431,10 @@ static const struct luaL_Reg window_cursor_funcs[] = { * File state. * @tfield bool modified whether the file contains unsaved changes */ +/*** + * File marks. + * @field marks array to access the marks of this file by single letter name + */ static int file_index(lua_State *L) { File *file = obj_ref_check(L, 1, "vis.file"); if (!file) { @@ -1473,6 +1483,11 @@ static int file_index(lua_State *L) { lua_pushboolean(L, text_modified(file->text)); return 1; } + + if (strcmp(key, "marks") == 0) { + obj_ref_new(L, file->marks, "vis.file.marks"); + return 1; + } } return index_common(L); @@ -1751,6 +1766,53 @@ static const struct luaL_Reg file_lines_funcs[] = { { NULL, NULL }, }; +static int file_marks_index(lua_State *L) { + File *file = obj_ref_check_containerof(L, 1, "vis.file.marks", offsetof(File, marks)); + if (!file) + goto err; + const char *symbol = luaL_checkstring(L, 2); + if (!symbol || strlen(symbol) != 1) + goto err; + enum VisMark mark = vis_mark_from(NULL /* XXX */, symbol[0]); + if (mark == VIS_MARK_INVALID) + goto err; + size_t pos = text_mark_get(file->text, file->marks[mark]); + if (pos == EPOS) + goto err; + lua_pushunsigned(L, pos); + return 1; +err: + lua_pushnil(L); + return 1; +} + +static int file_marks_newindex(lua_State *L) { + File *file = obj_ref_check_containerof(L, 1, "vis.file.marks", offsetof(File, marks)); + if (!file) + return 0; + const char *symbol = luaL_checkstring(L, 2); + if (!symbol || strlen(symbol) != 1) + return 0; + enum VisMark mark = vis_mark_from(NULL /* XXX */, symbol[0]); + size_t pos = luaL_checkunsigned(L, 3); + if (mark < LENGTH(file->marks)) + file->marks[mark] = text_mark_set(file->text, pos); + return 0; +} + +static int file_marks_len(lua_State *L) { + File *file = obj_ref_check_containerof(L, 1, "vis.file.marks", offsetof(File, marks)); + lua_pushunsigned(L, file ? LENGTH(file->marks) : 0); + return 1; +} + +static const struct luaL_Reg file_marks_funcs[] = { + { "__index", file_marks_index }, + { "__newindex", file_marks_newindex }, + { "__len", file_marks_len }, + { NULL, NULL }, +}; + /*** * The user interface. * @@ -2034,6 +2096,8 @@ void vis_lua_init(Vis *vis) { } obj_type_new(L, "vis.file.mark"); + obj_type_new(L, "vis.file.marks"); + luaL_setfuncs(L, file_marks_funcs, 0); obj_type_new(L, "vis.window.cursor"); luaL_setfuncs(L, window_cursor_funcs, 0); @@ -2209,6 +2273,7 @@ void vis_lua_file_close(Vis *vis, File *file) { obj_ref_new(L, file, "vis.file"); pcall(vis, L, 1, 0); } + obj_ref_free(L, file->marks); obj_ref_free(L, file->text); obj_ref_free(L, file); lua_pop(L, 1);