Commit Diff


commit - 6d413abf961327c226d341c8bafe5c9a6e6ef88c
commit + 67c8ed7f496533b30422532ac86a57b02265b1ab
blob - 6c5fc4fc2692a025d295b8ea8836e249e48290c1
blob + ad9d7c241a992e0548e4aa80c463f112d0aec7c5
--- Makefile.am
+++ Makefile.am
@@ -4,6 +4,7 @@ telescope_SOURCES =	compat.h	\
 			compat/*.[ch]	\
 			gemini.c	\
 			gemtext.c	\
+			keymap.c	\
 			mime.c		\
 			pages.c		\
 			parser.c	\
blob - /dev/null
blob + 95334c2303461185e1133845affdba1ca63de1c1 (mode 644)
--- /dev/null
+++ keymap.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2021 Omar Polo <op@omarpolo.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "telescope.h"
+
+#include <ctype.h>
+#include <curses.h>
+#include <stdlib.h>
+
+#define CTRL(n)	((n)&0x1F)
+
+struct keytable {
+	char	*p;
+	int	 k;
+} keytable[] = {
+	{ "<up>",	KEY_UP },
+	{ "<down>",	KEY_DOWN },
+	{ "<left>",	KEY_LEFT },
+	{ "<right>",	KEY_RIGHT },
+	{ "<prior>",	KEY_PPAGE },
+	{ "<next>",	KEY_NPAGE },
+	{ "<home>",	KEY_HOME },
+	{ "<end>",	KEY_END },
+	/* ... */
+	{ "del",	KEY_BACKSPACE },
+	{ "esc",	27 },
+	{ "space",	' ' },
+	{ "spc",	' ' },
+	{ "enter",	CTRL('m') },
+	{ "ret",	CTRL('m' )},
+	{ "tab",	CTRL('i') },
+	/* ... */
+	{ NULL, 0 },
+};
+
+int
+kbd(const char *key)
+{
+	struct keytable *t;
+
+	for (t = keytable; t->p != NULL; ++t) {
+		if (has_prefix(key, t->p))
+			return t->k;
+	}
+
+        return *key;
+}
+
+const char *
+unkbd(int k)
+{
+	struct keytable *t;
+
+	for (t = keytable; t->p != NULL; ++t) {
+		if (k == t->k)
+			return t->p;
+	}
+
+	return NULL;
+}
+
+int
+kmap_define_key(struct kmap *map, const char *key, void (*fn)(struct tab*))
+{
+	int ctrl, meta, k;
+	struct keymap	*entry;
+
+again:
+	if ((ctrl = has_prefix(key, "C-")))
+		key += 2;
+	if ((meta = has_prefix(key, "M-")))
+		key += 2;
+	if (*key == '\0')
+                return 0;
+	k = kbd(key);
+
+	if (ctrl)
+		k = CTRL(k);
+
+	/* skip key & spaces */
+	while (*key != '\0' && !isspace(*key))
+		++key;
+	while (*key != '\0' && isspace(*key))
+		++key;
+
+	TAILQ_FOREACH(entry, &map->m, keymaps) {
+		if (entry->meta == meta && entry->key == k) {
+			if (*key == '\0') {
+				entry->fn = fn;
+				return 1;
+			}
+			map = &entry->map;
+			goto again;
+		}
+	}
+
+	if ((entry = calloc(1, sizeof(*entry))) == NULL)
+		return 0;
+
+	entry->meta = meta;
+	entry->key = k;
+	TAILQ_INIT(&entry->map.m);
+
+	if (TAILQ_EMPTY(&map->m))
+		TAILQ_INSERT_HEAD(&map->m, entry, keymaps);
+	else
+		TAILQ_INSERT_TAIL(&map->m, entry, keymaps);
+
+        if (*key != '\0') {
+		map = &entry->map;
+		goto again;
+	}
+
+	entry->fn = fn;
+
+	return 1;
+}
+
blob - 63c9cc3e4fa8ef04821a5fc9a38f8eb4a981a1b4
blob + 6dcb8f235e8c26e0188846169cfb36cd4ea4a490
--- telescope.h
+++ telescope.h
@@ -109,6 +109,20 @@ struct proto {
 	void		 (*loadfn)(struct tab*, const char*);
 };
 
+struct kmap {
+	TAILQ_HEAD(map, keymap)	m;
+	void			(*unhandled_input)(void);
+};
+
+struct keymap {
+	int			 meta;
+	int			 key;
+	struct kmap		 map;
+	void			(*fn)(struct tab*);
+
+	TAILQ_ENTRY(keymap)	 keymaps;
+};
+
 extern struct event		 imsgev;
 
 /* gemini.c */
@@ -117,6 +131,11 @@ int		 client_main(struct imsgbuf *b);
 /* gemtext.c */
 void		 gemtext_initparser(struct parser*);
 
+/* keymap.c */
+int		 kbd(const char*);
+const char	*unkbd(int);
+int		 kmap_define_key(struct kmap*, const char*, void(*)(struct tab*));
+
 /* mime.c */
 int		 setup_parser_for(struct tab*);
 
blob - 13f4cfecae972a2d9edca803451b11921edd1409
blob + 8ff7ebb98d769f947eab3b294d0b3b08c7d4916b
--- ui.c
+++ ui.c
@@ -78,8 +78,6 @@ struct minibuf_histhead;
 
 static struct event	stdioev, winchev;
 
-static int		 kbd(const char*);
-static void		 kmap_define_key(struct kmap*, const char*, void(*)(struct tab*));
 static void		 load_default_keys(void);
 static int		 push_line(struct tab*, const struct line*, const char*, size_t, int);
 static void		 empty_vlist(struct tab*);
@@ -185,52 +183,12 @@ struct ui_state {
 };
 
 static char	keybuf[64];
-
-#define CTRL(n)	((n)&0x1F)
-
-struct keytable {
-	char	*p;
-	int	 k;
-} keytable[] = {
-	{ "<up>",	KEY_UP },
-	{ "<down>",	KEY_DOWN },
-	{ "<left>",	KEY_LEFT },
-	{ "<right>",	KEY_RIGHT },
-	{ "<prior>",	KEY_PPAGE },
-	{ "<next>",	KEY_NPAGE },
-	{ "<home>",	KEY_HOME },
-	{ "<end>",	KEY_END },
-	/* ... */
-	{ "del",	KEY_BACKSPACE },
-	{ "esc",	27 },
-	{ "space",	' ' },
-	{ "spc",	' ' },
-	{ "enter",	CTRL('m') },
-	{ "ret",	CTRL('m' )},
-	{ "tab",	CTRL('i') },
-	/* ... */
-	{ NULL, 0 },
-};
-
-struct kmap {
-	TAILQ_HEAD(map, keymap)	m;
-	void			(*unhandled_input)(void);
-};
 
 struct kmap global_map,
 	minibuffer_map,
 	*current_map,
 	*base_map;
 
-struct keymap {
-	int			 meta;
-	int			 key;
-	struct kmap		 map;
-	void			(*fn)(struct tab*);
-
-	TAILQ_ENTRY(keymap)	 keymaps;
-};
-
 /* TODO: limit to a maximum number of entries */
 struct minibuf_histhead {
 	TAILQ_HEAD(mhisthead, minibuf_hist)	head;
@@ -292,97 +250,18 @@ struct line_face {
 	[LINE_PRE_END] =	{ 0 },
 };
 
-static int
-kbd(const char *key)
-{
-	struct keytable *t;
-
-	for (t = keytable; t->p != NULL; ++t) {
-		if (has_prefix(key, t->p))
-			return t->k;
-	}
-
-        return *key;
-}
-
-static const char *
-unkbd(int k)
-{
-	struct keytable *t;
-
-	for (t = keytable; t->p != NULL; ++t) {
-		if (k == t->k)
-			return t->p;
-	}
-
-	return NULL;
-}
-
-static void
-kmap_define_key(struct kmap *map, const char *key, void (*fn)(struct tab*))
-{
-	int ctrl, meta, k;
-	struct keymap	*entry;
-
-again:
-	if ((ctrl = has_prefix(key, "C-")))
-		key += 2;
-	if ((meta = has_prefix(key, "M-")))
-		key += 2;
-	if (*key == '\0')
-		_exit(1);
-	k = kbd(key);
-
-	if (ctrl)
-		k = CTRL(k);
-
-	/* skip key & spaces */
-	while (*key != '\0' && !isspace(*key))
-		++key;
-	while (*key != '\0' && isspace(*key))
-		++key;
-
-	TAILQ_FOREACH(entry, &map->m, keymaps) {
-		if (entry->meta == meta && entry->key == k) {
-			if (*key == '\0') {
-				entry->fn = fn;
-				return;
-			}
-			map = &entry->map;
-			goto again;
-		}
-	}
-
-	if ((entry = calloc(1, sizeof(*entry))) == NULL)
-		abort();
-
-	entry->meta = meta;
-	entry->key = k;
-	TAILQ_INIT(&entry->map.m);
-
-	if (TAILQ_EMPTY(&map->m))
-		TAILQ_INSERT_HEAD(&map->m, entry, keymaps);
-	else
-		TAILQ_INSERT_TAIL(&map->m, entry, keymaps);
-
-        if (*key != '\0') {
-		map = &entry->map;
-		goto again;
-	}
-
-	entry->fn = fn;
-}
-
 static inline void
 global_set_key(const char *key, void (*fn)(struct tab*))
 {
-	kmap_define_key(&global_map, key, fn);
+	if (!kmap_define_key(&global_map, key, fn))
+		_exit(1);
 }
 
 static inline void
 minibuffer_set_key(const char *key, void (*fn)(struct tab*))
 {
-	kmap_define_key(&minibuffer_map, key, fn);
+	if (!kmap_define_key(&minibuffer_map, key, fn))
+		_exit(1);
 }
 
 static void