Improved paragraph breaking, added link support

This commit is contained in:
Nate Choe
2022-04-22 18:04:14 -05:00
parent aaacccbb58
commit 1ae5adec62
2 changed files with 92 additions and 40 deletions

View File

@@ -92,7 +92,7 @@ int main(int argc, char **argv) {
static void printhelp(FILE *file, char *name) { static void printhelp(FILE *file, char *name) {
fprintf(file, fprintf(file,
"Usage: %s -b [header] -t [template] -e [footer] -o [output]", name); "Usage: %s -b [header] -t [template] -e [footer] -o [output]\n", name);
fputs( fputs(
"This program is free software. You can redistribute and/or modify it under\n" "This program is free software. You can redistribute and/or modify it under\n"
"the terms of the GNU General Public License as published by the Free\n" "the terms of the GNU General Public License as published by the Free\n"

View File

@@ -37,6 +37,12 @@ enum paratype {
HL HL
}; };
enum inlinetype {
ITALIC,
BOLD,
CODE
};
static const struct { static const struct {
char c; char c;
char *escape; char *escape;
@@ -71,12 +77,15 @@ static long strsearch(char *data, long start, size_t datalen, char c, int reps);
* c = '.', reps = 2, data = ".. ...", returns 4 * c = '.', reps = 2, data = ".. ...", returns 4
* c = '.', reps = 1, data = " ...", returns 3 * c = '.', reps = 1, data = " ...", returns 3
* */ * */
static int writeescape(char c, FILE *outfile);
static int writedata(char *data, size_t len, FILE *outfile); static int writedata(char *data, size_t len, FILE *outfile);
static int writesimple(char *data, size_t len, FILE *outfile); static int writesimple(char *data, size_t len, FILE *outfile);
static void ungetline(struct linefile *file, char *line); static void ungetline(struct linefile *file, char *line);
static char *getline(struct linefile *file); static char *getline(struct linefile *file);
static const char *escapedchars = "!\"#%&'()*,./:;?@[\\]^{|}~";
int parsetemplate(FILE *infile, FILE *outfile) { int parsetemplate(FILE *infile, FILE *outfile) {
struct linefile realin; struct linefile realin;
realin.prevline = NULL; realin.prevline = NULL;
@@ -143,8 +152,29 @@ static int parsepara(struct linefile *infile, FILE *outfile) {
} }
} }
static int isbreak(char *line) {
int count, i;
char whitechar;
count = 0;
whitechar = '\0';
for (i = 0; line[i] != '\0'; ++i) {
if (line[i] == line[0])
++count;
else if (line[i] == ' ' || line[i] == '\t') {
if (whitechar == '\0')
whitechar = line[i];
if (whitechar != line[i])
return 0;
}
else
return 0;
}
return count >= 3;
return 0;
}
static enum paratype identifypara(char *line, char **contentret) { static enum paratype identifypara(char *line, char **contentret) {
int i, count; int i;
for (i = 0; i < 4; ++i) { for (i = 0; i < 4; ++i) {
if (line[i] == ' ') if (line[i] == ' ')
continue; continue;
@@ -165,25 +195,25 @@ whitegone:
case '#': case '#':
for (i = 0; i < 6 && line[i] == '#'; ++i) ; for (i = 0; i < 6 && line[i] == '#'; ++i) ;
*contentret = line + i; *contentret = line + i;
if (line[i] != '\0' && line[i] != ' ')
goto normal;
return H1 + i - 1; return H1 + i - 1;
case '>': case '>':
*contentret = line + 1; *contentret = line + 1;
return BLOCKQUOTE; return BLOCKQUOTE;
case '-':
count = 0;
for (i = 0; line[i] != '\0'; ++i) {
if (line[i] == '-')
++count;
if (count == 3)
return HL;
}
case '*': case '*':
if (isbreak(line))
return HL;
*contentret = line + 1; *contentret = line + 1;
return UL; return UL;
case '-': case '_':
if (isbreak(line))
return HL;
goto normal;
case '`': case '`':
for (i = 0; i < 3; ++i) for (i = 0; i < 3; ++i)
if (line[i] != '`') if (line[i] != '`')
return NORMAL; goto normal;
return CODEBACK; return CODEBACK;
default: default:
if (isdigit(line[0])) { if (isdigit(line[0])) {
@@ -193,6 +223,8 @@ whitegone:
return OL; return OL;
} }
} }
goto normal;
normal:
*contentret = line; *contentret = line;
return NORMAL; return NORMAL;
} }
@@ -290,6 +322,7 @@ static int parahardcase(struct linefile *infile, FILE *outfile,
} }
else else
buff = untrail(buff); buff = untrail(buff);
fputc(' ', outfile);
} }
fprintf(outfile, "</%s>", tag); fprintf(outfile, "</%s>", tag);
@@ -367,7 +400,18 @@ success:
return i; return i;
} }
/* TODO: Finish this */ static int writeescape(char c, FILE *outfile) {
int i;
for (i = 0; i < sizeof escapes / sizeof *escapes; ++i) {
if (escapes[i].c == c) {
fputs(escapes[i].escape, outfile);
return 0;
}
}
fputc(c, outfile);
return 0;
}
static int writedata(char *data, size_t len, FILE *outfile) { static int writedata(char *data, size_t len, FILE *outfile) {
long i; long i;
long start; long start;
@@ -388,20 +432,16 @@ static int writedata(char *data, size_t len, FILE *outfile) {
STANDOUT_CHAR('*'); STANDOUT_CHAR('*');
STANDOUT_CHAR('_'); STANDOUT_CHAR('_');
italic: italic:
if (end < 0) { if (end < 0)
putchar(data[i]); goto normal;
break;
}
fputs("<i>", outfile); fputs("<i>", outfile);
writedata(data + start, end - start, outfile); writedata(data + start, end - start, outfile);
fputs("</i>", outfile); fputs("</i>", outfile);
i = end; i = end;
break; break;
bold: bold:
if (end < 0) { if (end < 0)
putchar(data[i]); goto normal;
break;
}
fputs("<b>", outfile); fputs("<b>", outfile);
writedata(data + start, end - start, outfile); writedata(data + start, end - start, outfile);
fputs("</b>", outfile); fputs("</b>", outfile);
@@ -411,24 +451,41 @@ static int writedata(char *data, size_t len, FILE *outfile) {
case '`': case '`':
end = strsearch(data, i, len, '`', 1); end = strsearch(data, i, len, '`', 1);
if (end < 0) if (end < 0)
break; goto normal;
fputs("<code>", outfile); fputs("<code>", outfile);
writedata(data + i, end - i, outfile); writedata(data + i, end - i, outfile);
fputs("</code>", outfile); fputs("</code>", outfile);
i = end; i = end;
break; break;
default: { case '[': {
int j; long linkend, textend;
for (j = 0; j < sizeof escapes / sizeof *escapes; ++j) { textend = strsearch(data, i, len, ']', 1);
if (escapes[j].c == data[i]) { if (textend < 0)
fputs(escapes[j].escape, outfile); goto normal;
goto end; linkend = strsearch(data, textend, len, ')', 1);
} if (linkend < 0)
} goto normal;
fputc(data[i], outfile); fputs("<a href='", outfile);
end: writesimple(data + textend + 2,
linkend - textend - 2, outfile);
fputs("'>", outfile);
writesimple(data + i + 1,
textend - i - 1, outfile);
fputs("</a>", outfile);
i = linkend;
break; break;
} }
case '\\':
if (i == len ||
strchr(escapedchars, data[i+1]) == NULL) {
fputc('\\', outfile);
break;
}
++i;
goto normal;
default: normal:
writeescape(data[i], outfile);
break;
} }
} }
return 0; return 0;
@@ -437,15 +494,10 @@ end:
static int writesimple(char *data, size_t len, FILE *outfile) { static int writesimple(char *data, size_t len, FILE *outfile) {
long i; long i;
for (i = 0; (len < 0 && data[i] != '\0') || i < len; ++i) { for (i = 0; (len < 0 && data[i] != '\0') || i < len; ++i) {
int j; if (data[i] == '\\')
for (j = 0; j < sizeof escapes / sizeof *escapes; ++j) { if (strchr(escapedchars, data[i]) == NULL)
if (escapes[j].c == data[i]) { fputc('\\', outfile);
fputs(escapes[j].escape, outfile); writeescape(data[i], outfile);
goto end;
}
}
fputc(data[i], outfile);
end:;
} }
return 0; return 0;
} }