aboutsummaryrefslogtreecommitdiff
path: root/vis-lua.c
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2016-12-19 10:28:16 +0100
committerMarc André Tanner <mat@brain-dump.org>2016-12-19 12:05:03 +0100
commit4905f678318d6a95b30a56b0551a356593dbd00c (patch)
tree78d1b37cac1c79d017007989dad091f55dae4ded /vis-lua.c
parentc73845177bad1fe27df105a06aac5f71f94b5ebd (diff)
downloadvis-4905f678318d6a95b30a56b0551a356593dbd00c.tar.gz
vis-4905f678318d6a95b30a56b0551a356593dbd00c.tar.xz
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 (limited to 'vis-lua.c')
-rw-r--r--vis-lua.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/vis-lua.c b/vis-lua.c
index da875e2..bb97a33 100644
--- 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);