From f5a693ee28131bfbe363daa43a2af557f9448da7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Andr=C3=A9=20Tanner?= Date: Thu, 14 Jan 2016 21:40:47 +0100 Subject: vis: move prompt handling to separate file --- vis-prompt.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 vis-prompt.c (limited to 'vis-prompt.c') diff --git a/vis-prompt.c b/vis-prompt.c new file mode 100644 index 0000000..ad9c9d5 --- /dev/null +++ b/vis-prompt.c @@ -0,0 +1,177 @@ +#include +#include "vis-core.h" +#include "text-objects.h" +#include "text-util.h" + +bool vis_prompt_cmd(Vis *vis, const char *cmd) { + if (!cmd || !cmd[0] || !cmd[1]) + return true; + switch (cmd[0]) { + case '/': + return vis_motion(vis, VIS_MOVE_SEARCH_FORWARD, cmd+1); + case '?': + return vis_motion(vis, VIS_MOVE_SEARCH_BACKWARD, cmd+1); + case '+': + case ':': + return vis_cmd(vis, cmd+1); + } + return false; +} + +static void prompt_hide(Win *win) { + Text *txt = win->file->text; + size_t size = text_size(txt); + /* make sure that file is new line terminated */ + char lastchar; + if (size > 1 && text_byte_get(txt, size-1, &lastchar) && lastchar != '\n') + text_insert(txt, size, "\n", 1); + /* remove empty entries */ + Filerange line = text_object_line(txt, size); + size_t line_size = text_range_size(&line); + if (line_size <= 2) + text_delete(txt, line.start, line_size); + vis_window_close(win); +} + +static void prompt_restore(Win *win) { + Vis *vis = win->vis; + /* restore window and mode which was active before the prompt window + * we deliberately don't use vis_mode_switch because we do not want + * to invoke the modes enter/leave functions */ + if (win->parent) + vis->win = win->parent; + vis->mode = win->parent_mode; +} + +static const char *prompt_enter(Vis *vis, const char *keys, const Arg *arg) { + Win *prompt = vis->win; + View *view = prompt->view; + Text *txt = prompt->file->text; + Win *win = prompt->parent; + char *cmd = NULL; + + Filerange range = view_selection_get(view); + if (!text_range_valid(&range)) + range = text_object_line_inner(txt, view_cursor_get(view)); + if (text_range_valid(&range)) + cmd = text_bytes_alloc0(txt, range.start, text_range_size(&range)); + + if (!win || !cmd) { + vis_info_show(vis, "Prompt window invalid\n"); + prompt_restore(prompt); + prompt_hide(prompt); + free(cmd); + return keys; + } + + prompt_restore(prompt); + if (vis_prompt_cmd(vis, cmd)) { + prompt_hide(prompt); + } else { + vis->win = prompt; + vis->mode = &vis_modes[VIS_MODE_INSERT]; + } + free(cmd); + vis_draw(vis); + return keys; +} + +static const char *prompt_esc(Vis *vis, const char *keys, const Arg *arg) { + Win *prompt = vis->win; + if (view_cursors_count(prompt->view) > 1) { + view_cursors_clear(prompt->view); + } else { + prompt_restore(prompt); + prompt_hide(prompt); + } + return keys; +} + +static const char *prompt_up(Vis *vis, const char *keys, const Arg *arg) { + vis_motion(vis, VIS_MOVE_LINE_UP); + vis_window_mode_unmap(vis->win, VIS_MODE_INSERT, ""); + view_options_set(vis->win->view, UI_OPTION_NONE); + return keys; +} + +static const char *prompt_backspace(Vis *vis, const char *keys, const Arg *arg) { + Win *prompt = vis->win; + Text *txt = prompt->file->text; + size_t size = text_size(txt); + size_t pos = view_cursor_get(prompt->view); + char c; + if (pos == size && (pos == 1 || (size >= 2 && text_byte_get(txt, size-2, &c) && c == '\n'))) { + prompt_restore(prompt); + prompt_hide(prompt); + } else { + vis_operator(vis, VIS_OP_DELETE); + vis_motion(vis, VIS_MOVE_CHAR_PREV); + } + return keys; +} + +static const KeyBinding prompt_enter_binding = { + .key = "", + .action = &(KeyAction){ + .func = prompt_enter, + }, +}; + +static const KeyBinding prompt_esc_binding = { + .key = "", + .action = &(KeyAction){ + .func = prompt_esc, + }, +}; + +static const KeyBinding prompt_up_binding = { + .key = "", + .action = &(KeyAction){ + .func = prompt_up, + }, +}; + +static const KeyBinding prompt_backspace_binding = { + .key = "", + .action = &(KeyAction){ + .func = prompt_backspace, + }, +}; + +void vis_prompt_show(Vis *vis, const char *title) { + Win *active = vis->win; + Win *prompt = window_new_file(vis, title[0] == ':' ? vis->command_file : vis->search_file); + if (!prompt) + return; + if (vis->mode->visual) + window_selection_save(active); + view_options_set(prompt->view, UI_OPTION_ONELINE); + Text *txt = prompt->file->text; + text_insert(txt, text_size(txt), title, strlen(title)); + view_cursors_scroll_to(view_cursor(prompt->view), text_size(txt)); + view_draw(prompt->view); + prompt->parent = active; + prompt->parent_mode = vis->mode; + vis_window_mode_map(prompt, VIS_MODE_NORMAL, "", &prompt_enter_binding); + vis_window_mode_map(prompt, VIS_MODE_INSERT, "", &prompt_enter_binding); + vis_window_mode_map(prompt, VIS_MODE_REPLACE, "", &prompt_enter_binding); + vis_window_mode_map(prompt, VIS_MODE_VISUAL, "", &prompt_enter_binding); + vis_window_mode_map(prompt, VIS_MODE_VISUAL_LINE, "", &prompt_enter_binding); + vis_window_mode_map(prompt, VIS_MODE_NORMAL, "", &prompt_esc_binding); + vis_window_mode_map(prompt, VIS_MODE_INSERT, "", &prompt_up_binding); + vis_window_mode_map(prompt, VIS_MODE_INSERT, "", &prompt_backspace_binding); + vis_mode_switch(vis, VIS_MODE_INSERT); + vis_draw(vis); +} + +void vis_info_show(Vis *vis, const char *msg, ...) { + va_list ap; + va_start(ap, msg); + vis->ui->info(vis->ui, msg, ap); + va_end(ap); +} + +void vis_info_hide(Vis *vis) { + vis->ui->info_hide(vis->ui); +} + -- cgit v1.2.3