commit a7dfc248ff4d88d5f7f63df0e61c63b29623216f
parent bc4a6634b54d62d5a460f22a4e81564358f74794
Author: hhvn <dev@hhvn.uk>
Date: Sun, 16 Jan 2022 19:10:43 +0000
zygo.c zygo.h config.h: navigation
Diffstat:
M | config.h | | | 1 | + |
M | zygo.c | | | 106 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ |
M | zygo.h | | | 8 | +++++++- |
3 files changed, 106 insertions(+), 9 deletions(-)
diff --git a/config.h b/config.h
@@ -5,6 +5,7 @@ static short uri_pair[2] = {0, 7};
static short cmd_pair[2] = {7, 0};
static short arg_pair[2] = {-1, 0};
static short err_pair[2] = {160, 0};
+static short eid_pair[2] = {4, -1};
static int stimeout = 5;
diff --git a/zygo.c b/zygo.c
@@ -26,6 +26,7 @@
#include <locale.h>
#include <signal.h>
#include <unistd.h>
+#include <ctype.h>
#include <stdio.h>
#include "zygo.h"
#include "config.h"
@@ -41,7 +42,9 @@ int config[] = {
struct {
int scroll;
- int wantinput;
+ int wantinput; /* 0 - no
+ * 1 - yes (with cmd)
+ * 2 - yes (id) */
wint_t input[BUFLEN];
char cmd;
char *arg;
@@ -318,24 +321,31 @@ list_free(List **l) {
void
list_append(List **l, Elem *e) {
+ Elem *elem;
+
zygo_assert(l);
if (!(*l)) {
(*l) = emalloc(sizeof(List));
(*l)->len = 0;
+ (*l)->lastid = 0;
(*l)->elems = NULL;
}
+ elem = elem_dup(e);
+ if (elem->type != 'i')
+ elem->id = ++(*l)->lastid;
+
if (!(*l)->elems) {
(*l)->len = 1;
(*l)->elems = emalloc(sizeof(Elem *) * (*l)->len);
- *(*l)->elems = elem_dup(e);
+ *(*l)->elems = elem;
return;
}
(*l)->len++;
(*l)->elems = erealloc((*l)->elems, sizeof(Elem *) * (*l)->len);
- *((*l)->elems + (*l)->len - 1) = elem_dup(e);
+ *((*l)->elems + (*l)->len - 1) = elem;
}
Elem *
@@ -345,6 +355,18 @@ list_get(List **l, size_t elem) {
return *((*l)->elems + elem);
}
+Elem *
+list_idget(List **l, size_t id) {
+ int i;
+
+ if (!l || !(*l) || (*l)->len == 0 || id >= (*l)->len)
+ return NULL;
+ for (i = 0; i < (*l)->len; i++)
+ if ((*((*l)->elems + i))->id == id)
+ return *((*l)->elems + i);
+ return NULL;
+}
+
size_t
list_len(List **l) {
if (!l || !(*l))
@@ -352,6 +374,9 @@ list_len(List **l) {
return (*l)->len;
}
+/*
+ * Misc functions
+ */
int
readline(char *buf, size_t count) {
size_t i = 0;
@@ -417,6 +442,18 @@ go(Elem *e) {
return 0;
}
+int
+digits(int i) {
+ int ret = 0;
+
+ do {
+ ret++;
+ i /= 10;
+ } while (i != 0);
+
+ return ret;
+}
+
/*
* UI functions
*/
@@ -436,7 +473,7 @@ error(char *format, ...) {
addstr(" ");
refresh();
candraw = 0;
- alarm(5);
+ alarm(stimeout);
}
Scheme *
@@ -452,6 +489,12 @@ int
draw_line(Elem *e, int maxlines) {
int lc, cc;
+ attron(COLOR_PAIR(PAIR_EID));
+ if (e->type != 'i')
+ printw("% 3d ", e->id);
+ else
+ printw(" ");
+ attroff(A_COLOR);
printw("%s | ", getscheme(e->type)->name);
attron(COLOR_PAIR(getscheme(e->type)->pair));
printw("%s\n", e->desc);
@@ -493,8 +536,10 @@ draw_bar(void) {
printw(" ");
if (ui.wantinput) {
curs_set(1);
- attron(COLOR_PAIR(PAIR_CMD));
- printw("%c", ui.cmd);
+ if (ui.wantinput == 1) {
+ attron(COLOR_PAIR(PAIR_CMD));
+ printw("%c", ui.cmd);
+ }
attron(COLOR_PAIR(PAIR_ARG));
printw("%s", ui.arg);
} else curs_set(0);
@@ -539,7 +584,7 @@ run(void) {
if (c == KEY_RESIZE) {
draw_page();
draw_bar();
- } else if (ui.wantinput) {
+ } else if (ui.wantinput == 1) {
if (c == 27 /* escape */) {
ui.wantinput = 0;
} else if (c == '\n') {
@@ -565,6 +610,29 @@ run(void) {
syncinput();
}
draw_bar();
+ } else if (ui.wantinput == 2) {
+ if (c == 27 /* escape */) {
+ ui.wantinput = 0;
+ } else if (c == '\n' || il + 1 >= digits(page->lastid)) {
+ if (c != '\n') {
+ ui.input[il++] = c;
+ ui.input[il] = '\0';
+ syncinput();
+ }
+ goto gonum;
+ } else if (c == KEY_BACKSPACE || c == 127) {
+ if (il == 0) {
+ ui.wantinput = 0;
+ } else {
+ ui.input[--il] = '\0';
+ syncinput();
+ }
+ } else if (isdigit((int)c)) {
+ ui.input[il++] = c;
+ ui.input[il] = '\0';
+ syncinput();
+ }
+ draw_bar();
} else {
switch (c) {
case KEY_DOWN:
@@ -598,10 +666,20 @@ run(void) {
case 'q':
endwin();
exit(EXIT_SUCCESS);
+ /* link numbers */
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
- /* TODO: numbered link handling */
+ ui.wantinput = 2;
+ ui.input[0] = c;
+ ui.input[1] = '\0';
+ syncinput();
+ il = 1;
+ if (digits(page->lastid) == 1)
+ goto gonum;
+ draw_bar();
break;
+ /* commands without arg */
+ /* commands with arg */
case ':':
ui.cmd = (char)c;
ui.wantinput = 1;
@@ -619,6 +697,17 @@ run(void) {
break;
}
}
+
+ continue;
+
+gonum:
+ if (atoi(ui.arg) >= page->lastid || atoi(ui.arg) < 1)
+ error("no such link: %d", atoi(ui.arg));
+ else
+ go(list_idget(&page, atoi(ui.arg)));
+ ui.wantinput = 0;
+ draw_page();
+ draw_bar();
}
}
@@ -667,6 +756,7 @@ main(int argc, char *argv[]) {
init_pair(PAIR_CMD, cmd_pair[0], cmd_pair[1]);
init_pair(PAIR_ARG, arg_pair[0], arg_pair[1]);
init_pair(PAIR_ERR, err_pair[0], err_pair[1]);
+ init_pair(PAIR_EID, eid_pair[0], eid_pair[1]);
for (i = 0; scheme[i].type; i++) {
scheme[i].pair = i + PAIR_SCHEME;
init_pair(scheme[i].pair, scheme[i].fg, -1);
diff --git a/zygo.h b/zygo.h
@@ -28,12 +28,16 @@ struct Elem {
char *selector;
char *server;
char *port;
+ size_t id; /* only set when:
+ * - type != 'i'
+ * - in a list */
};
typedef struct List List;
struct List {
struct Elem **elems;
size_t len;
+ size_t lastid;
};
typedef struct Scheme Scheme;
@@ -54,7 +58,8 @@ enum {
PAIR_CMD = 3,
PAIR_ARG = 4,
PAIR_ERR = 5,
- PAIR_SCHEME = 6,
+ PAIR_EID = 6,
+ PAIR_SCHEME = 7,
};
extern List *history;
@@ -80,6 +85,7 @@ char *elemtouri(Elem *e);
void list_free(List **l);
void list_append(List **l, Elem *e);
Elem *list_get(List **l, size_t elem);
+Elem *list_idget(List **l, size_t id);
size_t list_len(List **l);