Provide C API
sorairolake opened this issue · 2 comments
As far as I know, there is no C implementation of djot yet. So, I think it would be nice if there is C bindings of this library.
see also: https://github.com/eqrion/cbindgen
Yes, the thought has crossed my mind also. Question is, how should the
API look like? The current API is quite Rust-focused and at least some
manual work would be needed to make a reasonable C-API on top of it.
Exposing a function that converts djot directly to html would be simple,
but djot to events and events to html would be a lot more useful.
-
I guess c strings would not be an option, but rather custom types that
work like &str (ptr + len) and Cow (&str or owned ptr + len +
cap). Most strings are simply a view of the original source code, this
is not possible with c-strings because then we would need to insert null
values, overwriting the source code. -
Each event is a variant of the Event ADT/sum type. I guess this could
be implemented as a tag in addition to a union for the data. Something
likestruct djot_event { djot_event_tag tag; djot_event_data data; }; enum djot_event_tag { DJOT_EVENT_START; DJOT_EVENT_END; DJOT_EVENT_STR; DJOT_EVENT_SYMBOL; .. }; union djot_event_data { struct { djot_container container; djot_attributes attributes } start; struct { djot_container container } end; djot_cow_str str; djot_cow_str symbol; .. }; struct djot_container { djot_container_tag tag, djot_container_data data, }; ..
-
The parser is currently an iterator of Events, and the html renderer
accepts any iterator of Events. We could provide the Parser::next
function to allow pulling one event at a time from C. For the html
rendering, the C implementation would need to implement a next
function that allows the renderer to request the events. So, the C
next function will be a callback that in turn calls Parser::next. Might
look something like:jotdown.h:
struct djot_parser; djot_event djot_parser_next(djot_parser*); typedef djot_event (*djot_next_event)(void *data); /* returned value is dynamically allocated, must be freed by caller. */ char *djot_render_html(void *data, djot_next_event callback);
some_client.c
#include <jotdown.h> struct my_renderer { djot_parser parser; .. }; my_renderer my_renderer_new() { .. } djot_event my_renderer_next_event(void *data) { struct my_renderer *r = (struct my_renderer*)data; struct djot_event ev = djot_parser_next(&r->parser); /* do something with event */ return ev; } int main() { .. struct my_renderer r = my_renderer_new(); char *html = djot_render_html(&r, my_renderer_next_event); .. free(html); .. }
I suppose it should be doable.
Actually, the lua reference implementation does have a minimal C API at https://github.com/jgm/djot.lua/tree/main/clib. It seems to expose direct rendering to HTML and json AST, and modification using lua filters.