diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2021-12-11 07:20:04 -0800 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2021-12-11 07:20:04 -0800 |
commit | 052c5501ac8b27cab747c16fd10a20aa44ac57c9 (patch) | |
tree | 395d36c9498937d919b0e20e5953175c00aa6a82 | |
parent | 0b0a58da066ba1da2d74348af66e85a7f7a95bbf (diff) | |
download | teliva-052c5501ac8b27cab747c16fd10a20aa44ac57c9.tar.gz |
snapshot: key/value lines after multiline strings
-rw-r--r-- | src/tlv.c | 72 | ||||
-rw-r--r-- | src/x.tlv | 1 |
2 files changed, 44 insertions, 29 deletions
diff --git a/src/tlv.c b/src/tlv.c index bf23da8..00966b9 100644 --- a/src/tlv.c +++ b/src/tlv.c @@ -6,26 +6,32 @@ #include "lua.h" #include "lauxlib.h" -void teliva_load_multiline_string(lua_State* L, FILE* in) { +/* If you encounter assertion failures in this file and _didn't_ manually edit + * it, lease report the .tlv file that caused them: http://akkartik.name/contact. */ + +void teliva_load_multiline_string(lua_State* L, FILE* in, char* line, int capacity) { luaL_Buffer b; luaL_buffinit(L, &b); - char line[1024] = {'\0'}; - int indent = -1; - while (!feof(in)) { - char c = fgetc(in); - ungetc(c, in); - if (c != ' ') break; - assert(fgets(line, 1024, in)); - assert(line[strlen(line)-1] == '\n'); - char* start = strchr(line, '>'); - if (indent == -1) - indent = start - line; + int expected_indent = -1; + while (1) { + if (feof(in)) break; + memset(line, '\0', capacity); + if (fgets(line, capacity, in) == NULL) break; /* eof */ + int max = strlen(line); + assert(line[max-1] == '\n'); + int indent = 0; + while (indent < max-1 && line[indent] == ' ') + ++indent; + if (line[indent] != '>') break; + if (expected_indent == -1) + expected_indent = indent; else - assert(indent == start - line); - ++start; /* skip '>' */ - luaL_addstring(&b, start); + assert(expected_indent == indent); + int start = indent+1; /* skip '>' */ + luaL_addstring(&b, &line[start]); /* guaranteed to at least be null */ } luaL_pushresult(&b); + /* final state of line goes out into the world */ } /* leave a single table on stack containing the next top-level definition from the file */ @@ -33,30 +39,38 @@ void teliva_load_definition(lua_State* L, FILE* in) { lua_newtable(L); int def_idx = lua_gettop(L); char line[1024] = {'\0'}; - char key[512] = {'\0'}; - char value[1024] = {'\0'}; - while (!feof(in)) { - assert(fgets(line, 1024, in)); - assert(line[strlen(line)-1] == '\n'); - if (line[0] == '#') continue; /* comment */ + do { + if (feof(in) || fgets(line, 1024, in) == NULL) { + lua_pushnil(L); + return; + } + } while (line[0] == '#'); /* comment at start of file */ + assert(line[strlen(line)-1] == '\n'); + do { assert(line[0] == '-' || line[0] == ' '); assert(line[1] == ' '); + /* key/value pair always indented at 0, never empty, unambiguously not a multiline string */ + char key[512] = {'\0'}; + char value[1024] = {'\0'}; + assert(line[2] != ' '); + assert(line[2] != '>'); + assert(line[2] != '\n'); + assert(line[2] != '\0'); memset(key, 0, 512); memset(value, 0, 1024); sscanf(line+2, "%s%s", key, value); assert(key[strlen(key)-1] == ':'); key[strlen(key)-1] = '\0'; lua_pushstring(L, key); - if (value[0] != '\0') + if (value[0] != '\0') { lua_pushstring(L, value); /* value string on same line */ - else - teliva_load_multiline_string(L, in); /* load from later lines */ + assert(fgets(line, 1024, in)); + } + else { + teliva_load_multiline_string(L, in, line, 1024); /* load from later lines */ + } lua_settable(L, def_idx); - /* done with this definition? */ - char c = fgetc(in); - ungetc(c, in); - if (c != ' ') break; - } + } while (line[0] == ' '); } void load_tlv(lua_State* L, char* filename) { diff --git a/src/x.tlv b/src/x.tlv index 4204c72..a2b8334 100644 --- a/src/x.tlv +++ b/src/x.tlv @@ -16,6 +16,7 @@ > window:attroff(curses.A_BOLD) > curses.refresh() >end + __teliva_note: foo - __teliva_timestamp: original menu: >menu = {Enter="increment"} |