From c926397ed679597a94b9537d4dcb72fbe921c014 Mon Sep 17 00:00:00 2001 From: LDA Date: Sun, 4 Aug 2024 20:27:42 +0200 Subject: [PATCH] [ADD/WIP] Start making Ayadocs Docs!!! --- .gitignore | 3 + DATES.TXT | 5 + Makefile | 19 ++- XEPS-TBD.TXT | 5 +- etc/ayadoc/style.css | 46 ++++++ tools/aya.c | 339 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 414 insertions(+), 3 deletions(-) create mode 100644 DATES.TXT create mode 100644 etc/ayadoc/style.css create mode 100644 tools/aya.c diff --git a/.gitignore b/.gitignore index 2ac11a3..ff7606f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ data/* tools/out tools/out/* + +ayaya/* +ayaya diff --git a/DATES.TXT b/DATES.TXT new file mode 100644 index 0000000..256475a --- /dev/null +++ b/DATES.TXT @@ -0,0 +1,5 @@ +Some dates for Parsee-related events. They mostly serve as LDA's TODOs with +a strict deadline: + - ~September 2024: + Get Parsee into the _Phantasmagoria of Bug View_ stage (essentially + v0.0.1 for a public testing) once I can afford `yama`. diff --git a/Makefile b/Makefile index c62dfdb..06ee118 100644 --- a/Makefile +++ b/Makefile @@ -17,21 +17,38 @@ CYTO_LIB=/usr/local/lib # Where's Cytoplasm's library is SOURCE=src OBJECT=build +AYAS=ayaya +ETC=etc INCLUDES=src/include CC=cc CFLAGS=-I$(SOURCE) -I$(INCLUDES) -I$(CYTO_INC) -DNAME="\"$(NAME)\"" -DVERSION="\"$(VERSION)\"" -DREPOSITORY=\"$(REPOSITORY)\" -g -ggdb -Wall -Werror LDFLAGS=-L $(CYTO_LIB) -lCytoplasm -g -ggdb +AFLAGS=-C "$(ETC)/ayadoc/style.css" BINARY=parsee # ============================ Compilation ================================= SRC_FILES:=$(shell find $(SOURCE) -name '*.c') OBJ_FILES:=${subst $(SOURCE)/,$(OBJECT)/,$(patsubst %.c, %.o, $(SRC_FILES))} +CPP_FILES:=$(shell find $(INCLUDES) -name '*.h') +AYA_FILES:=${subst $(INCLUDES)/,$(AYAS)/,$(patsubst %.h, %.html, $(CPP_FILES))} + +all: binary utils + binary: $(OBJ_FILES) $(CC) $(LDFLAGS) $(OBJ_FILES) -o $(BINARY) clean: - rm -rf $(OBJECT) $(BINARY) + rm -rf $(OBJECT) $(BINARY) $(AYAS) $(OBJECT)/%.o: $(SOURCE)/%.c @mkdir -p $(shell dirname "$@") $(CC) -c $(CFLAGS) $< -o $@ + +utils: + (cd tools && make) + +ayadoc: utils $(AYA_FILES) + +$(AYAS)/%.html: $(INCLUDES)/%.h + @mkdir -p $(shell dirname "$@") + tools/out/aya $(AFLAGS) -i $< -o $@ diff --git a/XEPS-TBD.TXT b/XEPS-TBD.TXT index da535ab..f887385 100644 --- a/XEPS-TBD.TXT +++ b/XEPS-TBD.TXT @@ -48,8 +48,9 @@ THESE I WANT TO SEND THEM A NICE, BRIGHT GIFT: Not XEPs, but ideas that _needs_ to be added: - - "GIVE THE PUPPETS APPROPRIATE PLS/ROLES" - Hydro/t4d - "also it [Bifrost] doesn't respect voice either" + ~ "GIVE THE PUPPETS APPROPRIATE PLS/ROLES" - Hydro/t4d + - "also it [Bifrost] doesn't respect voice either" -> Send a form on moderated + MUCs (which is standard, so its not too bad!) - Standalone/Static Parsee, ideally as small as it can be(if not as APE). - https://www.youtube.com/watch?v=InL414iDZmY diff --git a/etc/ayadoc/style.css b/etc/ayadoc/style.css new file mode 100644 index 0000000..cc7595e --- /dev/null +++ b/etc/ayadoc/style.css @@ -0,0 +1,46 @@ +/* CSS style for Parsee Ayadocs */ +/* ---------- BASIC STYLING ----------*/ +html +{ + background-color: #222; + color: #eee; + font-family: sans-serif; +} + +blockquote +{ + border-left: 2px solid #ccc; + margin: 1.5em 10px; +} +blockquote p +{ + display: inline-block; +} + +a:visited +{ + color: #bedead; +} +a:link +{ + color: #fad; +} + + +/* ---------- AYADOC-SPECIFIC STYLING ----------*/ +.aya-return +{ + color: #fe8019; +} +.aya-arg +{ + text-decoration: underline; +} +.aya-name +{ + color: #689d6a; +} +.rets-none +{ + text-decoration: underline; +} diff --git a/tools/aya.c b/tools/aya.c new file mode 100644 index 0000000..0863ce5 --- /dev/null +++ b/tools/aya.c @@ -0,0 +1,339 @@ +/* aya.c - Generates a documentation page for a Parsee function + * ============================================================ + * Not hdoc because I hate hdoc!!!!!!111!!!!!!1!!!!11111!!! + * TODO: Aya is currently incomplete. Sorry, not sorry. + * + * Under CC0, as its a rather useful example of a KappaChat tool. + * See LICENSE for more information about Parsee's licensing. */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +typedef struct AyadocComment { + /* TODO: Descriptions are a bit more advanced than a raw string. + * Only because you have to deal with the {value} format. */ + char *description; + + /* Some notes are more advanced (see Returns, Modifies, See-Also, ...) */ + HashMap *notes; +} AyadocComment; + +static void +FreeAyadoc(AyadocComment *comment) +{ + char *key, *value; + if (!comment) + { + return; + } + + Free(comment->description); + while (HashMapIterate(comment->notes, &key, (void **) &value)) + { + Free(value); + } + HashMapFree(comment->notes); + + Free(comment); +} +static AyadocComment * +ParseAyadoc(char *raw) +{ + AyadocComment *ret; + char *start, *line_break; + bool end_of_text = false; + bool parsing_notes = false; + if (!raw) + { + return NULL; + } + ret = Malloc(sizeof(*ret)); + ret->notes = HashMapCreate(); + ret->description = NULL; + + start = raw; + while (!end_of_text) + { + char *line_content = NULL, *temporary = NULL; + char *index_ptr; + if (!(line_break = strchr(start, '\n'))) + { + end_of_text = true; + + /* Points to the EOF. I am using strchr because we need to + * defer the {end_of_text}. */ + line_break = start + strlen(start); + } + + if (start >= line_break) + { + break; + } + + if (!strncmp(start, " *", 2) || !strncmp(start, "*", 1)) + { + start += 1 + (*start == ' '); + while (start && isspace(*start)) + { + start++; + } + } + + for (index_ptr = start; index_ptr < line_break; index_ptr++) + { + char char_buffer[2] = { *index_ptr, '\0' }; + + temporary = line_content; + line_content = StrConcat(2, line_content, char_buffer); + Free(temporary); + } + + if (!line_content) + { + break; + } + + if (!strncmp(line_content, "---", 3)) + { + parsing_notes = true; + + goto line_end; + } + + if (parsing_notes) + { + char *del = strchr(line_content, ':'); + char *val = del + 1; + if (del && strlen(del) >= 1) + { + while (*val && isspace(*val)) + { + val++; + } + } + if (del) + { + *del = '\0'; + } + HashMapSet(ret->notes, line_content, StrDuplicate(val)); + goto line_end; + } + + temporary = ret->description; + ret->description = StrConcat(3, ret->description, line_content, "\n"); + Free(temporary); +line_end: + Free(line_content); + start = line_break + 1; + } + + return ret; +} + +static void +GenerateReturns(Stream *out, AyadocComment *ayadoc, HeaderDeclaration decl, char *val) +{ + if (StrEquals(val, "NOTHING")) + { + StreamPrintf(out, " nothing."); + return; + } + + StreamPrintf(out, ": "); + + /* TODO: Split all arguments by the '|', and handle them automatically + * (with live-alongs, special capped params, ... */ + StreamPrintf(out, " %s", val); +} +static void +GenerateHTML(Stream *out, AyadocComment *ayadoc, HeaderDeclaration decl) +{ + if (!out || !ayadoc) + { + return; + } + + StreamPrintf(out, "
", decl.name); + { + StreamPrintf(out, "

%s


", decl.name); + + StreamPrintf(out, "

Signature

"); + StreamPrintf(out, "
", decl.name); + { + char *attr, *value; + StreamPrintf(out, ""); + { + StreamPrintf(out, ""); + StreamPrintf(out, "%s", decl.returnType); + StreamPrintf(out, "
"); + } + { + size_t i, args = ArraySize(decl.args); + StreamPrintf(out, ""); + StreamPrintf(out, "%s", decl.name); + StreamPrintf(out, ""); + StreamPrintf(out, "("); + + for (i = 0; i < args; i++) + { + char *arg = ArrayGet(decl.args, i); + + StreamPrintf(out, ""); + StreamPrintf(out, "%s", arg); + StreamPrintf(out, ""); + + if (i != args - 1) + { + StreamPrintf(out, ", "); + } + } + StreamPrintf(out, ");"); + } + StreamPrintf(out, "
"); + + StreamPrintf(out, "

Description

"); + /* TODO: Pretty-print {}s by resolving from context. + * We don't make the input HTML-safe, aside from newlines as + * BR tags. */ + StreamPrintf( + out, + "

%s

", + ayadoc->description ? + ayadoc->description : + "" + "(no description given)" + "" + ); + + /* Extra fields */ + while (HashMapIterate(ayadoc->notes, &attr, (void **) &value)) + { + if (StrEquals(attr, "Returns")) + { + /* TODO: Be a little more advanced. */ + StreamPrintf(out, "
", decl.name); + StreamPrintf(out, "Returns"); + GenerateReturns(out, ayadoc, decl, value); + StreamPrintf(out, "
"); + StreamFlush(out); + continue; + } + } + + } + StreamPrintf(out, "
"); + } + StreamPrintf(out, "
"); + StreamFlush(out); +} + +int +Main(Array *args, HashMap *env) +{ + ArgParseState state; + int flag; + + char *header = NULL, *xhtml = NULL, *css = NULL; + Stream *input, *output; + + ArgParseStateInit(&state); + while ((flag = ArgParse(&state, args, "i:o:C:")) != -1) + { + switch (flag) + { + case 'i': + header = state.optArg; + break; + case 'o': + xhtml = state.optArg; + break; + case 'C': + css = state.optArg; + break; + } + } + + if (!header || !xhtml) + { + Log(LOG_ERR, + "Usage: %s -i [C header file] -o [Generated Aya HTML]", + ArrayGet(args, 0) + ); + return EXIT_FAILURE; + } + input = StreamOpen(header, "r"); + output = StreamOpen(xhtml, "w"); + + StreamPrintf(output, ""); + StreamPrintf(output, ""); + + StreamPrintf(output, ""); + if (css) + { + Stream *css_stream = StreamOpen(css, "r"); + StreamPrintf(output, ""); + StreamClose(css_stream); + } + StreamPrintf(output, ""); + + StreamPrintf(output, ""); + /* TODO */ + { + AyadocComment *comm = NULL; + HeaderExpr expression = { 0 }; + while (true) + { + HeaderDeclaration decl; + + HeaderParse(input, &expression); + if (expression.type == HP_EOF) + { + break; + } + + switch (expression.type) + { + case HP_COMMENT: + if (strncmp(expression.data.text, "*", 1)) + { + break; + } + if (comm) + { + FreeAyadoc(comm); + } + comm = ParseAyadoc(expression.data.text); + break; + case HP_DECLARATION: + if (!comm) + { + break; + } + decl = expression.data.declaration; + GenerateHTML(output, comm, decl); + FreeAyadoc(comm); + comm = NULL; + default: + break; + } + } + } + StreamPrintf(output, ""); + + StreamPrintf(output, ""); + + StreamClose(output); + StreamClose(input); + return EXIT_SUCCESS; +}