commit - 7943bb816bd80662aa2a36f1d4f1ee0584052357
commit + 84b880390e4a2a475936742c3b1aa37609ca2cab
blob - 669e558b248be11c4f2e7e695af4a9d5567ffb60
blob + 4cf6090fd4e119dbe9786d16b60ec2f58f0b7bf5
--- Makefile.am
+++ Makefile.am
hist.c \
keymap.c \
mime.c \
+ minibuffer.c \
pages.c \
parse.y \
parser.c \
blob - /dev/null
blob + 9c208d86af425dd4ff8edc99b0d903e25b1f9cea (mode 644)
--- /dev/null
+++ minibuffer.c
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include "telescope.h"
+
+static void minibuffer_hist_save_entry(void);
+static void minibuffer_self_insert(void);
+static void yornp_self_insert(void);
+static void yornp_abort(void);
+static void read_self_insert(void);
+static void read_abort(void);
+static void read_select(void);
+
+static void (*yornp_cb)(int, struct tab *);
+static struct tab *yornp_data;
+
+static void (*read_cb)(const char*, unsigned int);
+static unsigned int read_data;
+
+struct histhead eecmd_history,
+ ir_history,
+ lu_history,
+ read_history;
+
+struct ministate ministate;
+
+static void
+minibuffer_hist_save_entry(void)
+{
+ struct hist *hist;
+
+ if (ministate.history == NULL)
+ return;
+
+ if ((hist = calloc(1, sizeof(*hist))) == NULL)
+ abort();
+
+ strlcpy(hist->h, ministate.buf, sizeof(hist->h));
+
+ if (TAILQ_EMPTY(&ministate.history->head))
+ TAILQ_INSERT_HEAD(&ministate.history->head, hist, entries);
+ else
+ TAILQ_INSERT_TAIL(&ministate.history->head, hist, entries);
+ ministate.history->len++;
+}
+
+/*
+ * taint the minibuffer cache: if we're currently showing a history
+ * element, copy that to the current buf and reset the "history
+ * navigation" thing.
+ */
+void
+minibuffer_taint_hist(void)
+{
+ if (ministate.hist_cur == NULL)
+ return;
+
+ strlcpy(ministate.buf, ministate.hist_cur->h, sizeof(ministate.buf));
+ ministate.hist_cur = NULL;
+}
+
+static void
+minibuffer_self_insert(void)
+{
+ char *c, tmp[5] = {0};
+ size_t len;
+
+ minibuffer_taint_hist();
+
+ if (thiskey.cp == 0)
+ return;
+
+ len = utf8_encode(thiskey.cp, tmp);
+ c = utf8_nth(ministate.buffer.current_line->line, ministate.buffer.cpoff);
+ if (c + len > ministate.buf + sizeof(ministate.buf) - 1)
+ return;
+
+ memmove(c + len, c, strlen(c)+1);
+ memcpy(c, tmp, len);
+ ministate.buffer.cpoff++;
+}
+
+void
+eecmd_self_insert(void)
+{
+ if (thiskey.meta || unicode_isspace(thiskey.cp) ||
+ !unicode_isgraph(thiskey.cp)) {
+ global_key_unbound();
+ return;
+ }
+
+ minibuffer_self_insert();
+}
+
+void
+eecmd_select(void)
+{
+ struct cmd *cmd;
+
+ for (cmd = cmds; cmd->cmd != NULL; ++cmd) {
+ if (!strcmp(cmd->cmd, ministate.buf)) {
+ exit_minibuffer();
+ minibuffer_hist_save_entry();
+ cmd->fn(current_buffer());
+ return;
+ }
+ }
+
+ message("No match");
+}
+
+void
+ir_self_insert(void)
+{
+ minibuffer_self_insert();
+}
+
+void
+ir_select(void)
+{
+ char buf[1025] = {0};
+ struct phos_uri uri;
+ struct tab *tab;
+
+ tab = current_tab();
+
+ exit_minibuffer();
+ minibuffer_hist_save_entry();
+
+ /* a bit ugly but... */
+ memcpy(&uri, &tab->uri, sizeof(tab->uri));
+ phos_uri_set_query(&uri, ministate.buf);
+ phos_serialize_uri(&uri, buf, sizeof(buf));
+ load_url_in_tab(tab, buf);
+}
+
+void
+lu_self_insert(void)
+{
+ if (thiskey.meta || unicode_isspace(thiskey.key) ||
+ !unicode_isgraph(thiskey.key)) {
+ global_key_unbound();
+ return;
+ }
+
+ minibuffer_self_insert();
+}
+
+void
+lu_select(void)
+{
+ exit_minibuffer();
+ minibuffer_hist_save_entry();
+ load_url_in_tab(current_tab(), ministate.buf);
+}
+
+void
+bp_select(void)
+{
+ exit_minibuffer();
+ if (*ministate.buf != '\0')
+ add_to_bookmarks(ministate.buf);
+ else
+ message("Abort.");
+}
+
+static void
+yornp_self_insert(void)
+{
+ if (thiskey.key != 'y' && thiskey.key != 'n') {
+ message("Please answer y or n");
+ return;
+ }
+
+ exit_minibuffer();
+ yornp_cb(thiskey.key == 'y', yornp_data);
+}
+
+static void
+yornp_abort(void)
+{
+ exit_minibuffer();
+ yornp_cb(0, yornp_data);
+}
+
+static void
+read_self_insert(void)
+{
+ if (thiskey.meta || !unicode_isgraph(thiskey.cp)) {
+ global_key_unbound();
+ return;
+ }
+
+ minibuffer_self_insert();
+}
+
+static void
+read_abort(void)
+{
+ exit_minibuffer();
+ read_cb(NULL, read_data);
+}
+
+static void
+read_select(void)
+{
+ exit_minibuffer();
+ minibuffer_hist_save_entry();
+ read_cb(ministate.buf, read_data);
+}
+
+void
+enter_minibuffer(void (*self_insert_fn)(void), void (*donefn)(void),
+ void (*abortfn)(void), struct histhead *hist)
+{
+ in_minibuffer = 1;
+ base_map = &minibuffer_map;
+ current_map = &minibuffer_map;
+
+ base_map->unhandled_input = self_insert_fn;
+
+ ministate.donefn = donefn;
+ ministate.abortfn = abortfn;
+ memset(ministate.buf, 0, sizeof(ministate.buf));
+ ministate.buffer.current_line = &ministate.vline;
+ ministate.buffer.current_line->line = ministate.buf;
+ ministate.buffer.cpoff = 0;
+ strlcpy(ministate.buf, "", sizeof(ministate.prompt));
+
+ ministate.history = hist;
+ ministate.hist_cur = NULL;
+ ministate.hist_off = 0;
+}
+
+void
+exit_minibuffer(void)
+{
+ in_minibuffer = 0;
+ base_map = &global_map;
+ current_map = &global_map;
+}
+
+void
+yornp(const char *prompt, void (*fn)(int, struct tab*),
+ struct tab *data)
+{
+ size_t len;
+
+ if (in_minibuffer) {
+ fn(0, data);
+ return;
+ }
+
+ yornp_cb = fn;
+ yornp_data = data;
+ enter_minibuffer(yornp_self_insert, yornp_self_insert,
+ yornp_abort, NULL);
+
+ len = sizeof(ministate.prompt);
+ strlcpy(ministate.prompt, prompt, len);
+ strlcat(ministate.prompt, " (y or n) ", len);
+}
+
+/*
+ * Not yet "completing", but soon maybe...
+ */
+void
+completing_read(const char *prompt, void (*fn)(const char *, unsigned int),
+ unsigned int data)
+{
+ size_t len;
+
+ if (in_minibuffer)
+ return;
+
+ read_cb = fn;
+ read_data = data;
+ enter_minibuffer(read_self_insert, read_select, read_abort,
+ &read_history);
+
+ len = sizeof(ministate.prompt);
+ strlcpy(ministate.prompt, prompt, len);
+ strlcat(ministate.prompt, ": ", len);
+}
blob - 17475e59659c68fa7e64a500759111da5ddce936
blob + 5adf485a07ae9fee6013a4d24bd3987c75255895
--- telescope.h
+++ telescope.h
/* mime.c */
int setup_parser_for(struct tab*);
+
+/* minibuffer.c */
+void enter_minibuffer(void(*)(void), void(*)(void), void(*)(void),
+ struct histhead *);
+void exit_minibuffer(void);
+void yornp(const char *, void (*)(int, struct tab *), struct tab *);
+void completing_read(const char *,
+ void (*)(const char *, unsigned int),
+ unsigned int);
/* pages.c */
extern const char *about_about;
extern int body_cols;
extern int in_minibuffer;
+extern struct kmap global_map, minibuffer_map, *current_map, *base_map;
+
struct excursion {
int curs_x, curs_y;
size_t line_off;
void message(const char*, ...) __attribute__((format(printf, 1, 2)));
void start_loading_anim(struct tab *tab);
void load_url_in_tab(struct tab *, const char *);
-void enter_minibuffer(void(*)(void), void(*)(void), void(*)(void), struct histhead *);
-void exit_minibuffer(void);
void switch_to_tab(struct tab *);
struct tab *current_tab(void);
+struct buffer *current_buffer(void);
struct tab *new_tab(const char *);
unsigned int tab_new_id(void);
int ui_init(void);
blob - 55aebbdf2cc9f89d144d15ead94dfd811d16ea03
blob + 8055b9d85b8cacb91708ce0f17d71ba19cfdb826
--- ui.c
+++ ui.c
static struct event stdioev, winchev;
static void restore_curs_x(struct buffer *);
-static void minibuffer_hist_save_entry(void);
-static void minibuffer_self_insert(void);
-static void yornp_self_insert(void);
-static void yornp_abort(void);
-static void read_self_insert(void);
-static void read_abort(void);
-static void read_select(void);
static struct vline *nth_line(struct buffer*, size_t);
-static struct buffer *current_buffer(void);
static int readkey(void);
static void dispatch_stdio(int, short, void*);
static void handle_clear_echoarea(int, short, void*);
static char keybuf[64];
-static void (*yornp_cb)(int, struct tab *);
-static struct tab *yornp_data;
-
-static void (*read_cb)(const char*, unsigned int);
-static unsigned int read_data;
-
struct kmap global_map,
minibuffer_map,
*current_map,
*base_map;
-struct histhead eecmd_history,
- ir_history,
- lu_history,
- read_history;
-
int in_minibuffer;
-struct ministate ministate;
-
static inline void
update_x_offset(void)
{
message("%s is undefined", keybuf);
}
-static void
-minibuffer_hist_save_entry(void)
-{
- struct hist *hist;
-
- if (ministate.history == NULL)
- return;
-
- if ((hist = calloc(1, sizeof(*hist))) == NULL)
- abort();
-
- strlcpy(hist->h, ministate.buf, sizeof(hist->h));
-
- if (TAILQ_EMPTY(&ministate.history->head))
- TAILQ_INSERT_HEAD(&ministate.history->head, hist, entries);
- else
- TAILQ_INSERT_TAIL(&ministate.history->head, hist, entries);
- ministate.history->len++;
-}
-
-/*
- * taint the minibuffer cache: if we're currently showing a history
- * element, copy that to the current buf and reset the "history
- * navigation" thing.
- */
-void
-minibuffer_taint_hist(void)
-{
- if (ministate.hist_cur == NULL)
- return;
-
- strlcpy(ministate.buf, ministate.hist_cur->h, sizeof(ministate.buf));
- ministate.hist_cur = NULL;
-}
-
-static void
-minibuffer_self_insert(void)
-{
- char *c, tmp[5] = {0};
- size_t len;
-
- minibuffer_taint_hist();
-
- if (thiskey.cp == 0)
- return;
-
- len = utf8_encode(thiskey.cp, tmp);
- c = utf8_nth(ministate.buffer.current_line->line, ministate.buffer.cpoff);
- if (c + len > ministate.buf + sizeof(ministate.buf) - 1)
- return;
-
- memmove(c + len, c, strlen(c)+1);
- memcpy(c, tmp, len);
- ministate.buffer.cpoff++;
-}
-
-void
-eecmd_self_insert(void)
-{
- if (thiskey.meta || unicode_isspace(thiskey.cp) ||
- !unicode_isgraph(thiskey.cp)) {
- global_key_unbound();
- return;
- }
-
- minibuffer_self_insert();
-}
-
-void
-eecmd_select(void)
-{
- struct cmd *cmd;
-
- for (cmd = cmds; cmd->cmd != NULL; ++cmd) {
- if (!strcmp(cmd->cmd, ministate.buf)) {
- exit_minibuffer();
- minibuffer_hist_save_entry();
- cmd->fn(current_buffer());
- return;
- }
- }
-
- message("No match");
-}
-
-void
-ir_self_insert(void)
-{
- minibuffer_self_insert();
-}
-
-void
-ir_select(void)
-{
- char buf[1025] = {0};
- struct phos_uri uri;
- struct tab *tab;
-
- tab = current_tab();
-
- exit_minibuffer();
- minibuffer_hist_save_entry();
-
- /* a bit ugly but... */
- memcpy(&uri, &tab->uri, sizeof(tab->uri));
- phos_uri_set_query(&uri, ministate.buf);
- phos_serialize_uri(&uri, buf, sizeof(buf));
- load_url_in_tab(tab, buf);
-}
-
-void
-lu_self_insert(void)
-{
- if (thiskey.meta || unicode_isspace(thiskey.key) ||
- !unicode_isgraph(thiskey.key)) {
- global_key_unbound();
- return;
- }
-
- minibuffer_self_insert();
-}
-
-void
-lu_select(void)
-{
- exit_minibuffer();
- minibuffer_hist_save_entry();
- load_url_in_tab(current_tab(), ministate.buf);
-}
-
-void
-bp_select(void)
-{
- exit_minibuffer();
- if (*ministate.buf != '\0')
- add_to_bookmarks(ministate.buf);
- else
- message("Abort.");
-}
-
-static void
-yornp_self_insert(void)
-{
- if (thiskey.key != 'y' && thiskey.key != 'n') {
- message("Please answer y or n");
- return;
- }
-
- exit_minibuffer();
- yornp_cb(thiskey.key == 'y', yornp_data);
-}
-
-static void
-yornp_abort(void)
-{
- exit_minibuffer();
- yornp_cb(0, yornp_data);
-}
-
-static void
-read_self_insert(void)
-{
- if (thiskey.meta || !unicode_isgraph(thiskey.cp)) {
- global_key_unbound();
- return;
- }
-
- minibuffer_self_insert();
-}
-
-static void
-read_abort(void)
-{
- exit_minibuffer();
- read_cb(NULL, read_data);
-}
-
-static void
-read_select(void)
-{
- exit_minibuffer();
- minibuffer_hist_save_entry();
- read_cb(ministate.buf, read_data);
-}
-
static struct vline *
nth_line(struct buffer *buffer, size_t n)
{
tab->buffer.curs_x = 0;
tab->buffer.curs_y = 0;
redraw_tab(tab);
-}
-
-void
-enter_minibuffer(void (*self_insert_fn)(void), void (*donefn)(void),
- void (*abortfn)(void), struct histhead *hist)
-{
- in_minibuffer = 1;
- base_map = &minibuffer_map;
- current_map = &minibuffer_map;
-
- base_map->unhandled_input = self_insert_fn;
-
- ministate.donefn = donefn;
- ministate.abortfn = abortfn;
- memset(ministate.buf, 0, sizeof(ministate.buf));
- ministate.buffer.current_line = &ministate.vline;
- ministate.buffer.current_line->line = ministate.buf;
- ministate.buffer.cpoff = 0;
- strlcpy(ministate.buf, "", sizeof(ministate.prompt));
-
- ministate.history = hist;
- ministate.hist_cur = NULL;
- ministate.hist_off = 0;
-}
-
-void
-exit_minibuffer(void)
-{
- werase(echoarea);
-
- in_minibuffer = 0;
- base_map = &global_map;
- current_map = &global_map;
}
void
ui_yornp(const char *prompt, void (*fn)(int, struct tab *),
struct tab *data)
{
- size_t len;
-
- if (in_minibuffer) {
- fn(0, data);
- return;
- }
-
- yornp_cb = fn;
- yornp_data = data;
- enter_minibuffer(yornp_self_insert, yornp_self_insert,
- yornp_abort, NULL);
-
- len = sizeof(ministate.prompt);
- strlcpy(ministate.prompt, prompt, len);
- strlcat(ministate.prompt, " (y or n) ", len);
+ yornp(prompt, fn, data);
redraw_tab(current_tab());
}
ui_read(const char *prompt, void (*fn)(const char*, unsigned int),
unsigned int data)
{
- size_t len;
-
- if (in_minibuffer)
- return;
-
- read_cb = fn;
- read_data = data;
- enter_minibuffer(read_self_insert, read_select, read_abort,
- &read_history);
-
- len = sizeof(ministate.prompt);
- strlcpy(ministate.prompt, prompt, len);
- strlcat(ministate.prompt, ": ", len);
+ completing_read(prompt, fn, data);
redraw_tab(current_tab());
}