aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.def.h77
-rw-r--r--main.c4
-rw-r--r--vis.c126
-rw-r--r--vis.h16
4 files changed, 209 insertions, 14 deletions
diff --git a/config.def.h b/config.def.h
index f4d20a3..4eb0d2b 100644
--- a/config.def.h
+++ b/config.def.h
@@ -29,6 +29,8 @@ enum {
VIS_MODE_REGISTER,
VIS_MODE_NORMAL,
VIS_MODE_VISUAL,
+ VIS_MODE_READLINE,
+ VIS_MODE_PROMPT,
VIS_MODE_INSERT,
VIS_MODE_REPLACE,
};
@@ -459,6 +461,26 @@ static void insert_register(const Arg *arg) {
vis_insert(vis, window_cursor_get(vis->win->win), reg->data, reg->len);
}
+static void prompt(const Arg *arg) {
+ vis_prompt_show(vis, arg->s);
+ switchmode(&(const Arg){ .i = VIS_MODE_PROMPT });
+}
+
+static void prompt_enter(const Arg *arg) {
+ char *s = vis_prompt_get(vis);
+ fprintf(stderr, "prompt: %s\n", s);
+ free(s);
+ switchmode(&(const Arg){ .i = VIS_MODE_NORMAL });
+}
+
+static void prompt_up(const Arg *arg) {
+
+}
+
+static void prompt_down(const Arg *arg) {
+
+}
+
static void insert_verbatim(const Arg *arg) {
int value = 0;
for (int i = 0; i < 3; i++) {
@@ -581,11 +603,11 @@ static KeyBinding vis_operators[] = {
{ /* empty last element, array terminator */ },
};
-static void vis_operators_enter(void) {
+static void vis_operators_enter(Mode *old) {
vis_modes[VIS_MODE_OPERATOR].parent = &vis_modes[VIS_MODE_OPERATOR_OPTION];
}
-static void vis_operators_leave(void) {
+static void vis_operators_leave(Mode *new) {
vis_modes[VIS_MODE_OPERATOR].parent = &vis_modes[VIS_MODE_MOVE];
}
@@ -639,6 +661,9 @@ static KeyBinding vis_normal[] = {
{ { NONE('u') }, call, { .f = vis_undo } },
{ { CONTROL('R') }, call, { .f = vis_redo } },
{ { CONTROL('L') }, call, { .f = vis_draw } },
+ { { NONE(':') }, prompt, { .s = ":" } },
+ { { NONE('/') }, prompt, { .s = "/" } },
+ { { NONE('?') }, prompt, { .s = "?" } },
{ /* empty last element, array terminator */ },
};
@@ -656,27 +681,43 @@ static KeyBinding vis_visual[] = {
{ /* empty last element, array terminator */ },
};
-static void vis_visual_enter(void) {
+static void vis_visual_enter(Mode *old) {
window_selection_start(vis->win->win);
}
-static void vis_visual_leave(void) {
+static void vis_visual_leave(Mode *new) {
window_selection_clear(vis->win->win);
}
-static KeyBinding vis_insert_mode[] = {
+static KeyBinding vis_readline_mode[] = {
{ { NONE(ESC) }, switchmode, { .i = VIS_MODE_NORMAL } },
{ { CONTROL('c') }, switchmode, { .i = VIS_MODE_NORMAL } },
+ BACKSPACE( call, f, vis_backspace_key ),
+ { { CONTROL('D') }, call, { .f = vis_delete_key } },
+ { { CONTROL('W') }, delete_word, { NULL } },
+ { /* empty last element, array terminator */ },
+};
+
+static KeyBinding vis_prompt_mode[] = {
+ { { KEY(ENTER) }, prompt_enter, { NULL } },
+ { { CONTROL('J') }, prompt_enter, { NULL } },
+ { { KEY(UP) }, prompt_up, { NULL } },
+ { { KEY(DOWN) }, prompt_down, { NULL } },
+ { /* empty last element, array terminator */ },
+};
+
+static void vis_prompt_leave(Mode *new) {
+ if (new != &vis_modes[VIS_MODE_OPERATOR])
+ vis_prompt_hide(vis);
+}
+
+static KeyBinding vis_insert_mode[] = {
{ { CONTROL('L') }, switchmode, { .i = VIS_MODE_NORMAL } },
{ { CONTROL('[') }, switchmode, { .i = VIS_MODE_NORMAL } },
- { { CONTROL('D') }, call, { .f = vis_delete_key } },
- BACKSPACE( call, f, vis_backspace_key ),
- { { CONTROL('H') }, call, { .f = vis_backspace_key } },
{ { CONTROL('I') }, insert_tab, { NULL } },
{ { CONTROL('J') }, insert_newline, { NULL } },
{ { CONTROL('M') }, insert_newline, { NULL } },
{ { CONTROL('O') }, switchmode, { .i = VIS_MODE_OPERATOR } },
- { { CONTROL('W') }, delete_word, { NULL } },
{ { CONTROL('R'), NONE('a') }, insert_register, { .i = REG_a } },
{ { CONTROL('R'), NONE('b') }, insert_register, { .i = REG_b } },
{ { CONTROL('R'), NONE('c') }, insert_register, { .i = REG_c } },
@@ -764,9 +805,21 @@ static Mode vis_modes[] = {
.enter = vis_visual_enter,
.leave = vis_visual_leave,
},
+ [VIS_MODE_READLINE] = {
+ .name = "READLINE",
+ .parent = &vis_modes[VIS_MODE_BASIC],
+ .bindings = vis_readline_mode,
+ },
+ [VIS_MODE_PROMPT] = {
+ .name = "PROMPT",
+ .parent = &vis_modes[VIS_MODE_READLINE],
+ .bindings = vis_prompt_mode,
+ .input = vis_insert_input,
+ .leave = vis_prompt_leave,
+ },
[VIS_MODE_INSERT] = {
.name = "INSERT",
- .parent = &vis_modes[VIS_MODE_BASIC],
+ .parent = &vis_modes[VIS_MODE_READLINE],
.bindings = vis_insert_mode,
.input = vis_insert_input,
},
@@ -782,12 +835,12 @@ static void switchmode_to(Mode *new_mode) {
if (mode == new_mode)
return;
if (mode->leave)
- mode->leave();
+ mode->leave(new_mode);
mode_prev = mode;
//fprintf(stderr, "%s -> %s\n", mode_prev->name, new_mode->name);
mode = new_mode;
if (mode->enter)
- mode->enter();
+ mode->enter(mode_prev);
// TODO display mode name somewhere?
}
diff --git a/main.c b/main.c
index d6c505f..18bb5b4 100644
--- a/main.c
+++ b/main.c
@@ -43,8 +43,8 @@ struct Mode {
KeyBinding *bindings;
const char *name;
bool common_prefix;
- void (*enter)(void);
- void (*leave)(void);
+ void (*enter)(Mode *old);
+ void (*leave)(Mode *new);
bool (*unknown)(Key *key0, Key *key1); /* unknown key for this mode, return value determines whether parent modes will be checked */
bool (*input)(const char *str, size_t len); /* unknown key for this an all parent modes */
};
diff --git a/vis.c b/vis.c
index e593cc3..8487a69 100644
--- a/vis.c
+++ b/vis.c
@@ -1,4 +1,6 @@
+#define _BSD_SOURCE
#include <stdlib.h>
+#include <string.h>
#include "vis.h"
#include "util.h"
@@ -12,6 +14,13 @@ static void vis_search_backward(Vis *vis, Regex *regex);
static void vis_windows_arrange_horizontal(Vis *vis);
static void vis_windows_arrange_vertical(Vis *vis);
+static Prompt *vis_prompt_new();
+static void vis_prompt_free(Prompt *prompt);
+static void vis_prompt_clear(Prompt *prompt);
+static void vis_prompt_resize(Prompt *prompt, int width, int height);
+static void vis_prompt_move(Prompt *prompt, int x, int y);
+static void vis_prompt_draw(Prompt *prompt);
+static void vis_prompt_update(Prompt *prompt);
static void vis_window_resize(VisWin *win, int width, int height) {
window_resize(win->win, width, win->statuswin ? height - 1 : height);
@@ -163,6 +172,12 @@ void vis_window_vsplit(Vis *vis, const char *filename) {
void vis_resize(Vis *vis, int width, int height) {
vis->width = width;
vis->height = height;
+ if (vis->prompt->active) {
+ vis->height--;
+ vis_prompt_resize(vis->prompt, vis->width, 1);
+ vis_prompt_move(vis->prompt, 0, vis->height);
+ vis_prompt_draw(vis->prompt);
+ }
vis_draw(vis);
}
@@ -268,6 +283,8 @@ void vis_update(Vis *vis) {
if (vis->win->statuswin)
wnoutrefresh(vis->win->statuswin);
+ if (vis->prompt && vis->prompt->active)
+ vis_prompt_update(vis->prompt);
window_update(vis->win->win);
}
@@ -333,6 +350,10 @@ Vis *vis_new(int width, int height) {
Vis *vis = calloc(1, sizeof(Vis));
if (!vis)
return NULL;
+ if (!(vis->prompt = vis_prompt_new())) {
+ vis_free(vis);
+ return NULL;
+ }
vis->width = width;
vis->height = height;
vis->windows_arrange = vis_windows_arrange_horizontal;
@@ -344,6 +365,7 @@ void vis_free(Vis *vis) {
next = win->next;
vis_window_free(win);
}
+ vis_prompt_free(vis->prompt);
free(vis);
}
@@ -382,3 +404,107 @@ void vis_delete(Vis *vis, size_t pos, size_t len) {
text_delete(vis->win->text, pos, len);
vis_windows_invalidate(vis, pos, pos + len);
}
+
+
+static void vis_prompt_free(Prompt *prompt) {
+ if (!prompt)
+ return;
+ vis_window_free(prompt->win);
+ if (prompt->titlewin)
+ delwin(prompt->titlewin);
+ free(prompt->title);
+ free(prompt);
+}
+
+static Prompt *vis_prompt_new() {
+ Text *text = text_load(NULL);
+ if (!text)
+ return NULL;
+ Prompt *prompt = calloc(1, sizeof(Prompt));
+ if (!prompt)
+ goto err;
+
+ if (!(prompt->win = calloc(1, sizeof(VisWin))))
+ goto err;
+
+ if (!(prompt->win->win = window_new(text)))
+ goto err;
+
+ prompt->win->text = text;
+
+ if (!(prompt->titlewin = newwin(0, 0, 0, 0)))
+ goto err;
+
+ return prompt;
+err:
+ if (!prompt || !prompt->win)
+ text_free(text);
+ vis_prompt_free(prompt);
+ return NULL;
+}
+
+static void vis_prompt_resize(Prompt *prompt, int width, int height) {
+ size_t title_width = strlen(prompt->title);
+ wresize(prompt->titlewin, height, title_width);
+ vis_window_resize(prompt->win, width - title_width, height);
+}
+
+static void vis_prompt_move(Prompt *prompt, int x, int y) {
+ size_t title_width = strlen(prompt->title);
+ mvwin(prompt->titlewin, y, x);
+ vis_window_move(prompt->win, x + title_width, y);
+}
+
+void vis_prompt_show(Vis *vis, const char *title) {
+ Prompt *prompt = vis->prompt;
+ if (prompt->active)
+ return;
+ prompt->active = true;
+ prompt->editor = vis->win;
+ vis->win = prompt->win;
+ free(prompt->title);
+ prompt->title = strdup(title);
+ vis_resize(vis, vis->width, vis->height);
+}
+
+static void vis_prompt_draw(Prompt *prompt) {
+ mvwaddstr(prompt->titlewin, 0, 0, prompt->title);
+}
+
+static void vis_prompt_update(Prompt *prompt) {
+ wnoutrefresh(prompt->titlewin);
+}
+
+static void vis_prompt_clear(Prompt *prompt) {
+ Text *text = prompt->win->text;
+ while (text_undo(text));
+}
+
+void vis_prompt_hide(Vis *vis) {
+ Prompt *prompt = vis->prompt;
+ if (!prompt->active)
+ return;
+ prompt->active = false;
+ vis->win = prompt->editor;
+ prompt->editor = NULL;
+ vis->height++;
+ vis_prompt_clear(prompt);
+ vis_draw(vis);
+}
+
+void vis_prompt_set(Vis *vis, const char *line) {
+ Text *text = vis->prompt->win->text;
+ vis_prompt_clear(vis->prompt);
+ text_insert_raw(text, 0, line, strlen(line));
+ vis_window_draw(vis->prompt->win);
+}
+
+char *vis_prompt_get(Vis *vis) {
+ Text *text = vis->prompt->win->text;
+ char *buf = malloc(text_size(text) + 1);
+ if (!buf)
+ return NULL;
+ size_t len = text_bytes_get(text, 0, text_size(text), buf);
+ buf[len] = '\0';
+ return buf;
+}
diff --git a/vis.h b/vis.h
index fe504ab..b35208e 100644
--- a/vis.h
+++ b/vis.h
@@ -20,6 +20,14 @@ struct VisWin {
VisWin *prev, *next; /* neighbouring windows */
};
+typedef struct {
+ VisWin *win;
+ VisWin *editor; /* active editor window before prompt is shown */
+ char *title;
+ WINDOW *titlewin;
+ bool active;
+} Prompt;
+
typedef void (*vis_statusbar_t)(WINDOW *win, bool active, const char *filename, size_t line, size_t col);
enum Reg {
@@ -47,6 +55,7 @@ struct Vis {
VisWin *win; /* currently active window */
Syntax *syntaxes; /* NULL terminated array of syntax definitions */
Register registers[REG_LAST];
+ Prompt *prompt;
void (*windows_arrange)(Vis*); /* current layout which places the windows */
vis_statusbar_t statusbar; /* configurable user hook to draw statusbar */
};
@@ -102,6 +111,13 @@ void vis_window_vsplit(Vis*, const char *filename);
void vis_window_next(Vis*);
void vis_window_prev(Vis*);
+
+char *vis_prompt_get(Vis *vis);
+void vis_prompt_set(Vis *vis, const char *line);
+void vis_prompt_show(Vis *vis, const char *title);
+void vis_prompt_hide(Vis *vis);
+
+
void vis_statusbar_set(Vis*, vis_statusbar_t);
/* library initialization code, should be run at startup */