diff --git a/Makefile b/Makefile
index 69a241a8825a6a7aa979eb2ae95a26faaf3a0532..3d4df602cd7f7ab4f5a45b47dee0d47729f0739c 100644
--- a/Makefile
+++ b/Makefile
@@ -8,6 +8,10 @@ gmni: $(gmni_objects)
@printf 'CCLD\t$@\n'
@$(CC) $(LDFLAGS) $(LIBS) -o $@ $(gmni_objects)
+gmnlm: $(gmnlm_objects)
doc/gmni.1: doc/gmni.scd
.SUFFIXES: .c .o .scd .1
diff --git a/config.sh b/config.sh
index b93815ada4a25ec508e7a86cc79b9e9be3eba428..52931ab241c3177285b56258bf9b67ac4b63a7ea 100644
--- a/config.sh
+++ b/config.sh
@@ -134,6 +134,7 @@
all: ${all}
EOF
gmni >>"$outdir"/config.mk
echo done
touch $outdir/cppcache
diff --git a/configure b/configure
index aca6e8a1eaa9a6271f03eb8863640d0d93cdf435..151bdae8c12d9ad07d3a5240d7c554f4c62664c8 100755
--- a/configure
+++ b/configure
@@ -7,10 +7,18 @@ genrules gmni \
src/client.c \
src/escape.c \
src/gmni.c \
src/url.c
+}
+gmnlm() {
src/client.c \
src/escape.c \
src/gmnlm.c \
src/parser.c \
src/url.c
}
-all="gmni"
+all="gmni gmnlm"
run_configure
diff --git a/src/gmni.c b/src/gmni.c
index 75c6c5afb6e7f1f286d314d93f2b44ef8414afb3..dc0c5c7f61679369fe4fadafd0508147868cc3c3 100644
--- a/src/gmni.c
+++ b/src/gmni.c
@@ -15,7 +15,7 @@ #include <unistd.h>
#include "gmni.h"
static void
-usage(char *argv_0)
+usage(const char *argv_0)
{
fprintf(stderr,
"usage: %s [-46lLiIN] [-E cert] [-d input] [-D path] gemini://...\n",
diff --git a/src/gmnlm.c b/src/gmnlm.c
new file mode 100644
index 0000000000000000000000000000000000000000..bc3f647d42372678b4180f539df8637d0ba69a12
--- /dev/null
+++ b/src/gmnlm.c
@@ -0,0 +1,215 @@
+#include <assert.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <unistd.h>
+#include "gmni.h"
+#include "url.h"
+struct link {
+};
+static void
+usage(const char *argv_0)
+{
+}
+static bool
+set_url(struct Curl_URL *url, char *new_url)
+{
fprintf(stderr, "Error: invalid URL\n");
return false;
+}
+static char *
+trim_ws(char *in)
+{
in[i] = 0;
+}
+static void
+display_gemini(FILE *tty, struct gemini_response *resp,
struct link **next, bool pagination)
+{
switch (tok.token) {
case GEMINI_TEXT:
// TODO: word wrap
col += fprintf(tty, " %s\n", trim_ws(tok.text));
break;
case GEMINI_LINK:
(void)next; // TODO: Record links
col += fprintf(tty, "[%d] %s\n", nlinks++, trim_ws(
tok.link.text ? tok.link.text : tok.link.url));
break;
case GEMINI_PREFORMATTED:
continue; // TODO
case GEMINI_HEADING:
for (int n = tok.heading.level; n; --n) {
col += fprintf(tty, "#");
}
col += fprintf(tty, " %s\n", trim_ws(tok.heading.title));
break;
case GEMINI_LIST_ITEM:
// TODO: Option to disable Unicode
col += fprintf(tty, " • %s\n", trim_ws(tok.list_item));
break;
case GEMINI_QUOTE:
// TODO: Option to disable Unicode
col += fprintf(tty, " | %s\n", trim_ws(tok.quote_text));
break;
}
while (col >= ws.ws_col) {
col -= ws.ws_col;
++row;
}
++row;
col = 0;
if (pagination && row >= ws.ws_row - 1) {
fprintf(tty, "[Enter for more, or q to stop] ");
size_t n = 0;
char *l = NULL;
if (getline(&l, &n, tty) == -1) {
return;
}
if (strcmp(l, "q\n") == 0) {
return;
}
free(l);
row = col = 0;
}
+}
+int
+main(int argc, char *argv[])
+{
switch (c) {
case 'P':
pagination = false;
break;
case 'h':
usage(argv[0]);
return 0;
default:
fprintf(stderr, "fatal: unknown flag %c\n", c);
return 1;
}
set_url(url, argv[optind]);
have_url = true;
usage(argv[0]);
return 1;
.ssl_ctx = SSL_CTX_new(TLS_method()),
assert(have_url); // TODO
struct link *links;
static char prompt[4096];
char *plain_url;
CURLUcode uc = curl_url_get(url, CURLUPART_URL, &plain_url, 0);
assert(uc == CURLUE_OK); // Invariant
snprintf(prompt, sizeof(prompt), "\n\t%s\n"
"\tWhere to? [n]: follow Nth link; [o <url>]: open URL; [q]: quit\n"
"=> ", plain_url);
enum gemini_result res = gemini_request(plain_url, &opts, &resp);
if (res != GEMINI_OK) {
fprintf(stderr, "Error: %s\n", gemini_strerr(res, &resp));
assert(0); // TODO: Prompt
}
switch (gemini_response_class(resp.status)) {
case GEMINI_STATUS_CLASS_INPUT:
assert(0); // TODO
case GEMINI_STATUS_CLASS_REDIRECT:
assert(0); // TODO
case GEMINI_STATUS_CLASS_CLIENT_CERTIFICATE_REQUIRED:
assert(0); // TODO
case GEMINI_STATUS_CLASS_TEMPORARY_FAILURE:
case GEMINI_STATUS_CLASS_PERMANENT_FAILURE:
fprintf(stderr, "Server returned %s %d %s\n",
resp.status / 10 == 4 ?
"TEMPORARY FAILURE" : "PERMANENT FALIURE",
resp.status, resp.meta);
break;
case GEMINI_STATUS_CLASS_SUCCESS:
display_gemini(tty, &resp, &links, pagination);
break;
}
gemini_response_finish(&resp);
fprintf(tty, "%s", prompt);
size_t l = 0;
char *in = NULL;
ssize_t n = getline(&in, &l, tty);
if (n == -1 && feof(tty)) {
break;
}
if (strcmp(in, "q\n") == 0) {
run = false;
}
free(in);
+}
text/gemini
This content has been proxied by September (ba2dc).