size: 3 KiB

1#include <stdio.h>
2#include <string.h>
3#include <lua.h>
4#include <lauxlib.h>
5#include <lualib.h>
6#include <djot.h>
7
8#include "djot_combined.inc"
9/* unsigned char djot_combined_lua[] */
10
11void djot_report_error(lua_State *L) {
12 if(!L) {
13 fprintf(stderr, "lua_State is NULL\n");
14 } else {
15 fprintf(stderr, "error: %s\n", lua_tostring(L, -1));
16 }
17}
18
19const char *djot_get_error(lua_State *L) {
20 if(!L) {
21 return "lua_State is NULL\n";
22 } else {
23 return lua_tostring(L, -1);
24 }
25}
26
27lua_State *djot_open() {
28 lua_State *L = luaL_newstate(); /* create Lua state */
29 if (L == NULL) {
30 return NULL;
31 }
32 luaL_openlibs(L); /* opens Lua libraries */
33
34 if (luaL_dostring(L, (const char*)djot_combined_lua) != LUA_OK) {
35 djot_report_error(L);
36 return NULL;
37 }
38
39 lua_setglobal(L, "djot");
40
41 return L;
42}
43
44void djot_close(lua_State *L) {
45 lua_close(L);
46}
47
48/* Parse input (optionally including source positions) and add
49 * a global 'doc' with the parsed AST. The
50 * subordinate functions djot_render_html, djot_render_ast,
51 * djot_render_matches, djot_apply_filter can then be used to manipulate
52 * or render the content. Returns 1 on success, 0 on error. */
53int djot_parse(lua_State *L, char *input, bool sourcepos) {
54 lua_getglobal(L, "djot");
55 lua_getfield(L, -1, "parse");
56 lua_pushstring(L, input);
57 lua_pushboolean(L, sourcepos);
58 if (lua_pcall(L, 2, 1, 0) != LUA_OK) {
59 return 0;
60 }
61 lua_setglobal(L, "doc");
62 return 1;
63}
64
65/* Render the document in the global 'doc' as HTML, returning a string,
66 * or NULL on error. */
67char *djot_render_html(lua_State *L) {
68 lua_getglobal(L, "djot");
69 lua_getfield(L, -1, "render_html");
70 lua_getglobal(L, "doc");
71 if (lua_pcall(L, 1, 1, 0) != LUA_OK) {
72 return NULL;
73 }
74 return (char *)lua_tostring(L, -1);
75}
76
77/* Render the AST of the document in the global 'doc' as JSON.
78 * NULL is returned on error. */
79char *djot_render_ast_json(lua_State *L) {
80 lua_getglobal(L, "djot");
81 lua_getfield(L, -1, "render_ast_json");
82 lua_getglobal(L, "doc");
83 if (lua_pcall(L, 1, 1, 0) != LUA_OK) {
84 return NULL;
85 }
86 return (char *)lua_tostring(L, -1);
87}
88
89/* Render the AST of the document in the global 'doc' as JSON.
90 * NULL is returned on error. */
91char *djot_render_ast_pretty(lua_State *L) {
92 lua_getglobal(L, "djot");
93 lua_getfield(L, -1, "render_ast_pretty");
94 lua_getglobal(L, "doc");
95 if (lua_pcall(L, 1, 1, 0) != LUA_OK) {
96 return NULL;
97 }
98 return (char *)lua_tostring(L, -1);
99}
100
101/* Load a filter from a string and apply it to the AST in global 'doc'.
102 * Return 1 on success, 0 on error. */
103int djot_apply_filter(lua_State *L, char *filter) {
104 lua_getglobal(L, "djot");
105 lua_getfield(L, -1, "filter");
106 lua_getfield(L, -1, "load_filter");
107 lua_pushstring(L, filter);
108 if (lua_pcall(L, 1, 1, 0) != LUA_OK) {
109 return 0;
110 }
111 // Now we should have the loaded filter on top of stack, or nil and an error
112 if lua_isnil(L, -2) {
113 return 0;
114 }
115 // If we're here, top of stack should be the compiled filter
116 lua_getglobal(L, "djot");
117 lua_getfield(L, -1, "filter");
118 lua_getfield(L, -1, "apply_filter");
119 lua_getglobal(L, "doc");
120 lua_pushvalue(L, -5); /* push the compiled filter to top of stack */
121 if (lua_pcall(L, 2, 1, 0) != LUA_OK) {
122 return 0;
123 }
124 return 1;
125}
126
127/* Parse input and render the events as a JSON array.
128 * NULL is returned on error. */
129char *djot_parse_and_render_events(lua_State *L, char *input) {
130 lua_getglobal(L, "djot");
131 lua_getfield(L, -1, "parse_and_render_events");
132 lua_pushstring(L, input);
133 if (lua_pcall(L, 1, 1, 0) != LUA_OK) {
134 return NULL;
135 }
136 return (char *)lua_tostring(L, -1);
137}
138