From 8a7c1e9bdfcdfb0591f177b37f87a6f589895b65 Mon Sep 17 00:00:00 2001 From: Nate Choe Date: Sat, 23 Apr 2022 02:10:22 -0500 Subject: [PATCH] Added code blocks --- src/include/mdutil.h | 7 ++++++- src/io.c | 4 ++-- src/main.c | 29 ++++++++++++++++++++++++----- src/mdutil.c | 23 ++++++++++++++++------- src/template.c | 25 ++++++++++++++++++++++--- 5 files changed, 70 insertions(+), 18 deletions(-) diff --git a/src/include/mdutil.h b/src/include/mdutil.h index 9c4b768..7a93827 100644 --- a/src/include/mdutil.h +++ b/src/include/mdutil.h @@ -23,6 +23,7 @@ enum linetype { EMPTY, PLAIN, SPACECODE, + FENCECODE, HR, SETEXT1, /* === */ @@ -33,10 +34,14 @@ enum linetype { enum nodetype { PARAGRAPH, CODE, + /* Used for code that starts with spaces */ + CODEBLOCK, + /* Used for triple backtick code */ NONE }; -enum linetype identifyline(char *line); +enum linetype identifyline(char *line, enum nodetype prev); +/* prev is almost never used, but sometimes it is. */ char *realcontent(char *line, enum linetype type); #endif diff --git a/src/io.c b/src/io.c index f5f394e..e229393 100644 --- a/src/io.c +++ b/src/io.c @@ -39,11 +39,11 @@ char *getline(struct linefile *file) { return ret; } if (c == '\t') { - while (len % 4 != 0) { + do { ret = append(ret, ' ', &len, &alloc); if (ret == NULL) return NULL; - } + } while (len % 4 != 0); } else { ret = append(ret, c, &len, &alloc); diff --git a/src/main.c b/src/main.c index dde1bd2..f1a5620 100644 --- a/src/main.c +++ b/src/main.c @@ -29,6 +29,7 @@ int main(int argc, char **argv) { char *header, *template, *footer, *out; FILE *outfile; int c; + const char *filefailmsg = "Failed to open file %s\n"; header = template = footer = out = NULL; @@ -63,22 +64,40 @@ int main(int argc, char **argv) { if (header != NULL) { FILE *headerfile; headerfile = fopen(header, "r"); - if (copyhtml(headerfile, outfile)) { - fputs("Failed to copy header\n", stderr); + if (headerfile != NULL) { + if (copyhtml(headerfile, outfile)) { + fputs(filefailmsg, stderr); + return 1; + } + } + else { + fprintf(stderr, filefailmsg, header); return 1; } } if (template != NULL) { FILE *templatefile; templatefile = fopen(template, "r"); - if (parsetemplate(templatefile, outfile)) + if (templatefile != NULL) { + if (parsetemplate(templatefile, outfile)) + return 1; + } + else { + fprintf(stderr, filefailmsg, template); return 1; + } } if (footer != NULL) { FILE *footerfile; footerfile = fopen(footer, "r"); - if (copyhtml(footerfile, outfile)) { - fputs("Failed to copy footer\n", stderr); + if (footerfile != NULL) { + if (copyhtml(footerfile, outfile)) { + fputs("Failed to copy footer\n", stderr); + return 1; + } + } + else { + fprintf(stderr, filefailmsg, footer); return 1; } } diff --git a/src/mdutil.c b/src/mdutil.c index e6bd7f5..3e27666 100644 --- a/src/mdutil.c +++ b/src/mdutil.c @@ -24,14 +24,16 @@ static char *truncate(char *str); -enum linetype identifyline(char *line) { +enum linetype identifyline(char *line, enum nodetype prev) { int i; - for (i = 0; i < 4; ++i) { - if (!isspace(line[i])) - goto notcode; + if (prev != PARAGRAPH) { + for (i = 0; i < 4; ++i) { + if (!isspace(line[i])) + goto notspacecode; + } + return SPACECODE; } - return SPACECODE; -notcode: +notspacecode: line = truncate(line); if (line[0] == '\0') return EMPTY; @@ -63,6 +65,13 @@ notcode: /* There has to be at least 3 delimiter characters */ } nothr: + for (i = 0; i < 3; ++i) { + if (line[i] != '`') + goto notfencedcode; + } + return FENCECODE; +notfencedcode: + return PLAIN; } /* TODO: Finish this */ @@ -75,7 +84,7 @@ static char *truncate(char *str) { char *realcontent(char *line, enum linetype type) { switch (type) { - case EMPTY: case HR: case SETEXT1: case SETEXT2: + case EMPTY: case HR: case SETEXT1: case SETEXT2: case FENCECODE: return NULL; case PLAIN: return line; diff --git a/src/template.c b/src/template.c index 575d67b..d18f047 100644 --- a/src/template.c +++ b/src/template.c @@ -28,6 +28,8 @@ struct parsestate { enum nodetype type; struct string *para; + int isfirst; + /* Used to insert
tags. Currently onlu used for FENCECODE. */ }; static int parseline(char *line, struct parsestate *currstate, FILE *out); @@ -63,8 +65,20 @@ int parsetemplate(FILE *infile, FILE *outfile) { static int parseline(char *line, struct parsestate *currstate, FILE *out) { enum linetype type; - type = identifyline(line); - fflush(stdout); + type = identifyline(line, currstate->type); + + if (currstate->type == CODEBLOCK) { + if (type == FENCECODE) { + currstate->type = NONE; + fputs("", out); + return 0; + } + if (!currstate->isfirst) + fputs("
", out); + fputs(line, out); + currstate->isfirst = 0; + return 0; + } switch (type) { case EMPTY: @@ -120,6 +134,11 @@ static int parseline(char *line, struct parsestate *currstate, FILE *out) { * paragraph and only write after obtaining the whole thing * as to not include the wrong tags. * */ + case FENCECODE: + fputs("", out); + currstate->type = CODEBLOCK; + currstate->isfirst = 1; + break; case SPACECODE: if (currstate->type != CODE) { endpara(currstate, out); @@ -142,7 +161,7 @@ static int endpara(struct parsestate *state, FILE *out) { fputs("

", out); resetstring(state->para); return 0; - case CODE: + case CODE: case CODEBLOCK: fputs("
", out); return 0; case NONE: