Improved paragraph breaking, added link support
This commit is contained in:
@@ -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"
|
||||||
|
|||||||
130
src/template.c
130
src/template.c
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user