From 9eda570311ffd292d333f7687074403ff46cc838 Mon Sep 17 00:00:00 2001 From: Albert Cervin Date: Mon, 23 Jan 2023 21:56:39 +0100 Subject: Implement some more commands - More bug fixes for keys: You can now have mod-less keys in keymaps as binds. - Fix calculation bug with space fillouts. --- src/minibuffer.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 97 insertions(+), 3 deletions(-) (limited to 'src/minibuffer.c') diff --git a/src/minibuffer.c b/src/minibuffer.c index b622ab0..a424af8 100644 --- a/src/minibuffer.c +++ b/src/minibuffer.c @@ -1,16 +1,77 @@ #include "minibuffer.h" +#include "binding.h" #include "buffer.h" #include "display.h" #include #include #include +#include static struct minibuffer { struct buffer *buffer; struct timespec expires; + char prompt[128]; + struct command_ctx prompt_command_ctx; + bool prompt_active; + struct keymap keymap; } g_minibuffer = {0}; +void draw_prompt(struct text_chunk *line_data, uint32_t line, + struct command_list *commands, void *userdata) { + uint32_t len = strlen(g_minibuffer.prompt); + command_list_set_index_color_fg(commands, 4); + command_list_draw_text(commands, 0, line, (uint8_t *)g_minibuffer.prompt, + len); + command_list_reset_color(commands); +} + +int32_t execute(struct command_ctx ctx, int argc, const char *argv[]) { + if (g_minibuffer.prompt_active) { + struct text_chunk line = buffer_get_line(g_minibuffer.buffer, 0); + char *l = (char *)malloc(line.nbytes + 1); + memcpy(l, line.text, line.nbytes); + + // split on ' ' + const char *argv[128] = {l}; + argc = 1; + for (uint32_t bytei = 0; bytei < line.nbytes; ++bytei) { + uint8_t byte = line.text[bytei]; + if (byte == ' ') { + l[bytei] = '\0'; + argv[argc] = l + bytei; + ++argc; + } + } + + minibuffer_abort_prompt(); + struct command_ctx *ctx = &g_minibuffer.prompt_command_ctx; + uint32_t res = execute_command(ctx->self, ctx->commands, ctx->active_window, + ctx->buffers, argc, argv); + + free(l); + return res; + } else { + return 0; + } +} + +struct command execute_minibuffer_command = { + .fn = execute, + .name = "minibuffer-execute", + .userdata = NULL, +}; + +int32_t complete(struct command_ctx ctx, int argc, const char *argv[]) { + return 0; +} + +struct command complete_minibuffer_command = { + .fn = complete, + .name = "minibuffer-complete", + .userdata = NULL, +}; + struct update_hook_result update(struct buffer *buffer, struct command_list *commands, uint32_t width, uint32_t height, uint64_t frame_time, @@ -18,19 +79,36 @@ struct update_hook_result update(struct buffer *buffer, struct timespec current; struct minibuffer *mb = (struct minibuffer *)userdata; clock_gettime(CLOCK_MONOTONIC, ¤t); - if (current.tv_sec >= mb->expires.tv_sec) { + if (!mb->prompt_active && current.tv_sec >= mb->expires.tv_sec) { buffer_clear(buffer); } - return (struct update_hook_result){0}; + struct update_hook_result res = {0}; + if (g_minibuffer.prompt_active) { + res.margins.left = strlen(g_minibuffer.prompt); + res.line_render_hook.callback = draw_prompt; + } + + return res; } void minibuffer_init(struct buffer *buffer) { g_minibuffer.buffer = buffer; + struct binding bindings[] = { + ANONYMOUS_BINDING(Ctrl, 'M', &execute_minibuffer_command), + ANONYMOUS_BINDING(Ctrl, 'I', &complete_minibuffer_command), + }; + keymap_bind_keys(&g_minibuffer.keymap, bindings, + sizeof(bindings) / sizeof(bindings[0])); + buffer_add_keymap(g_minibuffer.buffer, &g_minibuffer.keymap); buffer_add_update_hook(g_minibuffer.buffer, update, &g_minibuffer); } void echo(uint32_t timeout, const char *fmt, va_list args) { + if (g_minibuffer.prompt_active) { + return; + } + char buff[2048]; size_t nbytes = vsnprintf(buff, 2048, fmt, args); @@ -58,5 +136,21 @@ void minibuffer_echo_timeout(uint32_t timeout, const char *fmt, ...) { va_end(args); } +void minibuffer_prompt(struct command_ctx command_ctx, const char *fmt, ...) { + minibuffer_clear(); + g_minibuffer.prompt_active = true; + g_minibuffer.prompt_command_ctx = command_ctx; + va_list args; + va_start(args, fmt); + vsnprintf(g_minibuffer.prompt, sizeof(g_minibuffer.prompt), fmt, args); + va_end(args); +} + +void minibuffer_abort_prompt() { + minibuffer_clear(); + g_minibuffer.prompt_active = false; +} + bool minibuffer_displaying() { return !buffer_is_empty(g_minibuffer.buffer); } -void minibuffer_clear() { g_minibuffer.expires.tv_nsec = 0; } +void minibuffer_clear() { buffer_clear(g_minibuffer.buffer); } +bool minibuffer_focused() { return g_minibuffer.prompt_active; } -- cgit v1.2.3