commit 5799323f4c92181a3446a729366b230456e93c81
parent 59d43726bb18a1e240a7188b3dd33af5876a126e
Author: Drew DeVault <sir@cmpwn.com>
Date: Sun, 20 Sep 2020 22:28:45 -0400
Implement preformatted text
Diffstat:
3 files changed, 39 insertions(+), 14 deletions(-)
diff --git a/include/gmni.h b/include/gmni.h
@@ -2,6 +2,7 @@
#define GEMINI_CLIENT_H
#include <netdb.h>
#include <openssl/ssl.h>
+#include <stdbool.h>
#include <sys/socket.h>
enum gemini_result {
@@ -106,7 +107,9 @@ enum gemini_status_class gemini_response_class(enum gemini_status status);
enum gemini_tok {
GEMINI_TEXT,
GEMINI_LINK,
- GEMINI_PREFORMATTED,
+ GEMINI_PREFORMATTED_BEGIN,
+ GEMINI_PREFORMATTED_END,
+ GEMINI_PREFORMATTED_TEXT,
GEMINI_HEADING,
GEMINI_LIST_ITEM,
GEMINI_QUOTE,
@@ -124,10 +127,7 @@ struct gemini_token {
char *url; // May be NULL
} link;
- struct {
- char *text;
- char *alt_text; // May be NULL
- } preformatted;
+ char *preformatted;
struct {
char *title;
@@ -144,6 +144,7 @@ struct gemini_parser {
char *buf;
size_t bufsz;
size_t bufln;
+ bool preformatted;
};
// Initializes a text/gemini parser which reads from the specified BIO.
diff --git a/src/gmnlm.c b/src/gmnlm.c
@@ -278,8 +278,15 @@ repeat:
col += fprintf(out, " ");
}
break;
- case GEMINI_PREFORMATTED:
- continue; // TODO
+ case GEMINI_PREFORMATTED_BEGIN:
+ case GEMINI_PREFORMATTED_END:
+ continue; // Not used
+ case GEMINI_PREFORMATTED_TEXT:
+ col += fprintf(out, "` ");
+ if (text == NULL) {
+ text = tok.text;
+ }
+ break;
case GEMINI_HEADING:
if (text == NULL) {
for (int n = tok.heading.level; n; --n) {
diff --git a/src/parser.c b/src/parser.c
@@ -1,6 +1,7 @@
#include <assert.h>
#include <ctype.h>
#include <openssl/bio.h>
+#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
@@ -15,6 +16,7 @@ gemini_parser_init(struct gemini_parser *p, BIO *f)
p->buf = malloc(p->bufsz + 1);
p->buf[0] = 0;
BIO_up_ref(p->f);
+ p->preformatted = false;
}
void
@@ -57,7 +59,15 @@ gemini_parser_next(struct gemini_parser *p, struct gemini_token *tok)
*end = 0;
}
- if (strncmp(p->buf, "=>", 2) == 0) {
+ if (p->preformatted) {
+ if (strncmp(p->buf, "```", 3) == 0) {
+ tok->token = GEMINI_PREFORMATTED_END;
+ p->preformatted = false;
+ } else {
+ tok->token = GEMINI_PREFORMATTED_TEXT;
+ tok->preformatted = strdup(p->buf);
+ }
+ } else if (strncmp(p->buf, "=>", 2) == 0) {
tok->token = GEMINI_LINK;
int i = 2;
while (p->buf[i] && isspace(p->buf[i])) ++i;
@@ -76,9 +86,11 @@ gemini_parser_next(struct gemini_parser *p, struct gemini_token *tok)
tok->link.url = strdup(tok->link.url);
} else if (strncmp(p->buf, "```", 3) == 0) {
- tok->token = GEMINI_PREFORMATTED; // TODO
- tok->preformatted.text = strdup("<text>");
- tok->preformatted.alt_text = strdup("<alt-text>");
+ tok->token = GEMINI_PREFORMATTED_BEGIN;
+ if (p->buf[3]) {
+ tok->preformatted = strdup(&p->buf[3]);
+ }
+ p->preformatted = true;
} else if (p->buf[0] == '#') {
tok->token = GEMINI_HEADING;
int level = 1;
@@ -125,9 +137,14 @@ gemini_token_finish(struct gemini_token *tok)
free(tok->link.text);
free(tok->link.url);
break;
- case GEMINI_PREFORMATTED:
- free(tok->preformatted.text);
- free(tok->preformatted.alt_text);
+ case GEMINI_PREFORMATTED_BEGIN:
+ free(tok->preformatted);
+ break;
+ case GEMINI_PREFORMATTED_TEXT:
+ free(tok->preformatted);
+ break;
+ case GEMINI_PREFORMATTED_END:
+ // Nothing to free
break;
case GEMINI_HEADING:
free(tok->heading.title);