cgmnlm

colorful gemini line mode browser
git clone https://git.clttr.info/cgmnlm.git
Log (Feed) | Files | Refs (Tags) | README | LICENSE

commit 5799323f4c92181a3446a729366b230456e93c81
parent 59d43726bb18a1e240a7188b3dd33af5876a126e
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sun, 20 Sep 2020 22:28:45 -0400

Implement preformatted text

Diffstat:
Minclude/gmni.h | 11++++++-----
Msrc/gmnlm.c | 11+++++++++--
Msrc/parser.c | 31++++++++++++++++++++++++-------
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);