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:
Mvis-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);