commit - af29d739553d6efe6ff97d2cba50406122a99ff6
commit + b1e1e41a7e4757b4b9e028031431db0e0a304f25
blob - b7f36fd2312f9fcc2535cd7cfc24023380fa91a9
blob + e1a1f074b8ab728c5cb9320c8938c8195a08f358
--- Makefile.am
+++ Makefile.am
cmd.h \
compat.h \
compat/*.[ch] \
+ compl.c \
+ compl.h \
defaults.c \
defaults.h \
fs.c \
blob - 42c6cf2f7c3255420553a008549209927297e980
blob + 3c700286dfa06f282179020891c070f993c8960e
--- cmd.c
+++ cmd.c
#include <stdlib.h>
#include <string.h>
+#include "compl.h"
#include "defaults.h"
#include "minibuffer.h"
#include "telescope.h"
}
enter_minibuffer(eecmd_self_insert, eecmd_select, exit_minibuffer,
- &eecmd_history, NULL, NULL);
+ &eecmd_history, compl_eecmd, NULL);
len = sizeof(ministate.prompt);
strlcpy(ministate.prompt, "", len);
n = utf8_next_cp(c);
memmove(c, n, strlen(n)+1);
+
+ recompute_completions(0);
}
void
memmove(p, c, strlen(c)+1);
buffer->cpoff--;
+
+ recompute_completions(0);
}
void
minibuffer_taint_hist();
c = utf8_nth(buffer->current_line->line, buffer->cpoff);
*c = '\0';
+
+ recompute_completions(0);
}
void
blob - /dev/null
blob + 8d01e57a79a67f027ffbb5055e4b6d1189314455 (mode 644)
--- /dev/null
+++ compl.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 "compl.h"
+#include "telescope.h"
+
+const char *
+compl_eecmd(void **data)
+{
+ struct cmd **state = (struct cmd **)data;
+
+ /* first time: init the state */
+ if (*state == NULL)
+ *state = cmds;
+
+ if ((*state)->cmd == NULL)
+ return NULL;
+
+ (*state)++;
+ return (*state)->cmd;
+}
blob - /dev/null
blob + 8bf04bcb4c4660854bfa2ed924c52f23eb9c1c0c (mode 644)
--- /dev/null
+++ compl.h
+/*
+ * 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.
+ */
+
+#ifndef COMPL_H
+#define COMPL_H
+
+const char *compl_eecmd(void **);
+
+#endif
blob - 5354c5fd3f762db6e1f280b5d2f04c8d41708314
blob + 00e7a2d4e24e1f49fbd241b3dacfecb83efeb8f1
--- minibuffer.c
+++ minibuffer.c
struct ministate ministate;
+struct buffer minibufferwin;
+
+/*
+ * Recompute the visible completions. If add is 1, don't consider the
+ * ones already hidden.
+ */
+void
+recompute_completions(int add)
+{
+ struct line *l;
+
+ if (in_minibuffer != MB_COMPREAD)
+ return;
+
+ TAILQ_FOREACH(l, &ministate.compl.buffer.page.head, lines) {
+ if (add && l->flags & L_HIDDEN)
+ continue;
+ if (strstr(l->line, ministate.buf) != NULL)
+ l->flags &= ~L_HIDDEN;
+ else
+ l->flags |= L_HIDDEN;
+ }
+}
+
static void
minibuffer_hist_save_entry(void)
{
memmove(c + len, c, strlen(c)+1);
memcpy(c, tmp, len);
ministate.buffer.cpoff++;
+
+ recompute_completions(1);
}
void
exit_minibuffer();
minibuffer_hist_save_entry();
read_cb(ministate.buf, read_data);
+}
+
+/*
+ * Just like erase_buffer, but don't call free(l->line);
+ */
+static inline void
+erase_compl_buffer(struct buffer *buffer)
+{
+ struct line *l, *lt;
+
+ empty_vlist(buffer);
+
+ TAILQ_FOREACH_SAFE(l, &buffer->page.head, lines, lt) {
+ TAILQ_REMOVE(&buffer->page.head, l, lines);
+ /* don't free l->line! */
+ free(l);
+ }
+}
+
+/*
+ * TODO: we should collect this asynchronously...
+ */
+static inline void
+populate_compl_buffer(complfn *fn, void *data)
+{
+ const char *s;
+ struct line *l;
+ struct buffer *b;
+ struct parser *p;
+
+ b = &ministate.compl.buffer;
+ p = &b->page;
+
+ while ((s = fn(&data)) != NULL) {
+ if ((l = calloc(1, sizeof(*l))) == NULL)
+ abort();
+
+ l->type = LINE_TEXT;
+ l->line = s;
+
+ if (TAILQ_EMPTY(&p->head))
+ TAILQ_INSERT_HEAD(&p->head, l, lines);
+ else
+ TAILQ_INSERT_TAIL(&p->head, l, lines);
+ }
}
void
void (*abortfn)(void), struct histhead *hist,
complfn *complfn, void *compldata)
{
- in_minibuffer = 1;
+ in_minibuffer = complfn == NULL ? MB_READ : MB_COMPREAD;
+ if (in_minibuffer == MB_COMPREAD) {
+ ui_schedule_redraw();
+
+ erase_compl_buffer(&ministate.compl.buffer);
+
+ ministate.compl.fn = complfn;
+ ministate.compl.data = compldata;
+ populate_compl_buffer(complfn, compldata);
+ }
+
base_map = &minibuffer_map;
current_map = &minibuffer_map;
void
exit_minibuffer(void)
{
+ if (in_minibuffer == MB_COMPREAD)
+ ui_schedule_redraw();
+
in_minibuffer = 0;
base_map = &global_map;
current_map = &global_map;
*/
void
completing_read(const char *prompt, void (*fn)(const char *, struct tab *),
- struct tab *data, complfn *complfn, void *compldata)
+ struct tab *data)
{
size_t len;
read_cb = fn;
read_data = data;
enter_minibuffer(read_self_insert, read_select, read_abort,
- &read_history, complfn, compldata);
+ &read_history, NULL, NULL);
len = sizeof(ministate.prompt);
strlcpy(ministate.prompt, prompt, len);
blob - e6577cbd7191c8338c24499cb418c43757f399fd
blob + 73e4f9f746397c6856c0ce65b15083e15bd7380c
--- minibuffer.h
+++ minibuffer.h
#define MB_READ 1
#define MB_COMPREAD 2
-typedef char *(complfn)(void *);
+/*
+ * Completion provider function. These functions are called
+ * asynchronously. The function should compute the next completion
+ * using the given parameter `state' and modify it eventually. To
+ * signal the end of the completions, complfn should return NULL: the
+ * value of state will then be discarded and the function never called
+ * again.
+ */
+typedef const char *(complfn)(void **);
+struct ministate {
+ char *curmesg;
+
+ char prompt[64];
+ void (*donefn)(void);
+ void (*abortfn)(void);
+
+ char buf[1025];
+ struct line line;
+ struct vline vline;
+ struct buffer buffer;
+
+ struct histhead *history;
+ struct hist *hist_cur;
+ size_t hist_off;
+
+ struct {
+ struct buffer buffer;
+ complfn *fn;
+ void *data;
+ } compl;
+};
+extern struct ministate ministate;
+
+extern struct buffer minibufferwin;
+
+void recompute_completions(int);
+
void enter_minibuffer(void(*)(void), void(*)(void), void(*)(void),
struct histhead *,
complfn *, void *);
* completing_read asks the user for something using the minibuffer.
* The first argument is the string prompt. The second and third are
* the callback to call when done and the data; the callback function
- * can't be NULL. The last two arguments are the completion function
- * and its data; if not given, no completion will be shown. The
- * function providing the completion will be called asynchronously.
+ * can't be NULL.
*/
void completing_read(const char *,
- void (*)(const char *, struct tab *), struct tab *,
- complfn *, void *);
+ void (*)(const char *, struct tab *), struct tab *);
#endif
blob - f06eeb66d293166c1ef048fc6445686a3dcaa295
blob + 540de79098f2017095d3d728b08ede7f01a69e79
--- ui.c
+++ ui.c
static void redraw_minibuffer(void);
static void do_redraw_echoarea(void);
static void do_redraw_minibuffer(void);
+static void do_redraw_minibuffer_compl(void);
static void place_cursor(int);
static void redraw_tab(struct tab*);
static void emit_help_item(char*, void*);
/* move and resize the windows, in reverse order! */
+ if (in_minibuffer == MB_COMPREAD) {
+ mvwin(minibuffer, lines-10, 0);
+ wresize(minibuffer, 10, COLS);
+ lines -= 10;
+
+ wrap_page(&ministate.compl.buffer, COLS);
+ }
+
mvwin(echoarea, --lines, 0);
wresize(echoarea, 1, COLS);
{
struct vline *t;
+ if (vl == NULL)
+ return NULL;
+
if (!(vl->parent->flags & L_HIDDEN))
return vl;
if (TAILQ_EMPTY(&buffer->head))
goto end;
+ if (buffer->top_line == NULL)
+ buffer->top_line = TAILQ_FIRST(&buffer->head);
+
buffer->top_line = adjust_line(buffer->top_line, buffer);
if (buffer->top_line == NULL)
goto end;
else
do_redraw_echoarea();
+ if (in_minibuffer == MB_COMPREAD)
+ do_redraw_minibuffer_compl();
+
wattr_off(echoarea, minibuffer_face.background, NULL);
}
wprintw(echoarea, " [%s]", ministate.curmesg);
wmove(echoarea, 0, off_x + utf8_swidth_between(start, c));
+}
+
+static void
+do_redraw_minibuffer_compl(void)
+{
+ redraw_window(minibuffer, 10, body_cols,
+ &ministate.compl.buffer);
}
/*
wnoutrefresh(tabline);
wnoutrefresh(modeline);
+ if (in_minibuffer == MB_COMPREAD)
+ wnoutrefresh(minibuffer);
+
place_cursor(1);
doupdate();
void
ui_schedule_redraw(void)
{
- handle_resize_nodelay(0, 0, NULL);
+ struct timeval tv = {0, 0};
+
+ if (event_pending(&resizeev, EV_TIMEOUT, NULL))
+ event_del(&resizeev);
+
+ evtimer_set(&resizeev, handle_resize_nodelay, NULL);
+ evtimer_add(&resizeev, &tv);
}
void
ui_read(const char *prompt, void (*fn)(const char*, struct tab *),
struct tab *data)
{
- completing_read(prompt, fn, data, NULL, NULL);
+ completing_read(prompt, fn, data);
redraw_tab(current_tab());
}
blob - f88c1530477be74f4bd8856b0c55dd1381795c9d
blob + 909ba81917a545d6a5e0a29aaad82c3b3ee8f1f8
--- ui.h
+++ ui.h
lu_history,
read_history;
-struct ministate {
- char *curmesg;
-
- char prompt[64];
- void (*donefn)(void);
- void (*abortfn)(void);
-
- char buf[1025];
- struct line line;
- struct vline vline;
- struct buffer buffer;
-
- struct histhead *history;
- struct hist *hist_cur;
- size_t hist_off;
-};
-extern struct ministate ministate;
-
void save_excursion(struct excursion *, struct buffer *);
void restore_excursion(struct excursion *, struct buffer *);
void global_key_unbound(void);