diff options
| author | Marc André Tanner <mat@brain-dump.org> | 2014-09-23 22:07:19 +0200 |
|---|---|---|
| committer | Marc André Tanner <mat@brain-dump.org> | 2014-09-23 22:07:19 +0200 |
| commit | 6c080d01873be2670ecc74b698ac5d73d0acd77f (patch) | |
| tree | 5988e8bd70e5daf70269f7509e8e78356d09028d | |
| parent | 637b1adbdda1af761518b90b52fb6ae7798584bc (diff) | |
| download | vis-6c080d01873be2670ecc74b698ac5d73d0acd77f.tar.gz vis-6c080d01873be2670ecc74b698ac5d73d0acd77f.tar.xz | |
Implement linewise visual mode
| -rw-r--r-- | README | 4 | ||||
| -rw-r--r-- | config.def.h | 43 | ||||
| -rw-r--r-- | vis.c | 22 | ||||
| -rw-r--r-- | window.c | 9 | ||||
| -rw-r--r-- | window.h | 2 |
5 files changed, 63 insertions, 17 deletions
@@ -382,9 +382,7 @@ and their current support in vis. ----- At the moment there exists a more or less functional insert, replace - and character wise visual mode. - - A line wise visual mode is planned. + and visual mode (in both line and character wise variants). Marks ----- diff --git a/config.def.h b/config.def.h index 46ff32b..6003918 100644 --- a/config.def.h +++ b/config.def.h @@ -37,6 +37,7 @@ enum { VIS_MODE_REGISTER, VIS_MODE_NORMAL, VIS_MODE_VISUAL, + VIS_MODE_VISUAL_LINE, VIS_MODE_READLINE, VIS_MODE_PROMPT, VIS_MODE_INSERT_REGISTER, @@ -372,6 +373,7 @@ static KeyBinding vis_mode_normal[] = { { { NONE('r') }, replace, { NULL } }, { { NONE('i') }, switchmode, { .i = VIS_MODE_INSERT } }, { { NONE('v') }, switchmode, { .i = VIS_MODE_VISUAL } }, + { { NONE('V') }, switchmode, { .i = VIS_MODE_VISUAL_LINE } }, { { NONE('R') }, switchmode, { .i = VIS_MODE_REPLACE } }, { { NONE('S') }, operator_twice, { .i = OP_CHANGE } }, { { NONE('s') }, change, { .i = MOVE_CHAR_NEXT } }, @@ -388,6 +390,7 @@ static KeyBinding vis_mode_visual[] = { { { NONE(ESC) }, switchmode, { .i = VIS_MODE_NORMAL } }, { { CONTROL('c') }, switchmode, { .i = VIS_MODE_NORMAL } }, { { NONE('v') }, switchmode, { .i = VIS_MODE_NORMAL } }, + { { NONE('V') }, switchmode, { .i = VIS_MODE_VISUAL_LINE } }, BACKSPACE( operator, i, OP_DELETE ), { { CONTROL('H') }, operator, { .i = OP_DELETE } }, { { NONE('d') }, operator, { .i = OP_DELETE } }, @@ -400,11 +403,32 @@ static KeyBinding vis_mode_visual[] = { }; static void vis_mode_visual_enter(Mode *old) { - window_selection_start(vis->win->win); + if (old != &vis_modes[VIS_MODE_VISUAL_LINE]) + window_selection_start(vis->win->win); } static void vis_mode_visual_leave(Mode *new) { - window_selection_clear(vis->win->win); + if (new != &vis_modes[VIS_MODE_VISUAL_LINE]) + window_selection_clear(vis->win->win); +} + +static KeyBinding vis_mode_visual_line[] = { + { { NONE('v') }, switchmode, { .i = VIS_MODE_VISUAL } }, + { { NONE('V') }, switchmode, { .i = VIS_MODE_NORMAL } }, + { /* empty last element, array terminator */ }, +}; + +static void vis_mode_visual_line_enter(Mode *old) { + Win *win = vis->win->win; + window_cursor_to(win, text_line_begin(vis->win->text, window_cursor_get(win))); + if (old != &vis_modes[VIS_MODE_VISUAL]) + window_selection_start(vis->win->win); + movement(&(const Arg){ .i = MOVE_LINE_END }); +} + +static void vis_mode_visual_line_leave(Mode *new) { + if (new != &vis_modes[VIS_MODE_VISUAL]) + window_selection_clear(vis->win->win); } static KeyBinding vis_mode_readline[] = { @@ -543,10 +567,10 @@ static void vis_mode_replace_input(const char *str, size_t len) { * /-----------/ | \\ | * / | \\ | * VISUAL MARK-SET \\ OPERATOR-OPTION - * (m [a-z]) \\ (v,V) - * | \\ // - * | \\======// - * NORMAL + * | (m [a-z]) \\ (v,V) + * | | \\ // + * | | \\======// + * VISUAL-LINE NORMAL */ static Mode vis_modes[] = { @@ -621,6 +645,13 @@ static Mode vis_modes[] = { .enter = vis_mode_visual_enter, .leave = vis_mode_visual_leave, }, + [VIS_MODE_VISUAL_LINE] = { + .name = "--VISUAL LINE--", + .parent = &vis_modes[VIS_MODE_VISUAL], + .bindings = vis_mode_visual_line, + .enter = vis_mode_visual_line_enter, + .leave = vis_mode_visual_line_leave, + }, [VIS_MODE_READLINE] = { .name = "READLINE", .parent = &vis_modes[VIS_MODE_BASIC], @@ -626,7 +626,7 @@ static void linewise(const Arg *arg) { static void operator(const Arg *arg) { Operator *op = &ops[arg->i]; - if (mode == &vis_modes[VIS_MODE_VISUAL]) { + if (mode == &vis_modes[VIS_MODE_VISUAL] || mode == &vis_modes[VIS_MODE_VISUAL_LINE]) { action.op = op; action_do(&action); return; @@ -918,6 +918,22 @@ static void action_do(Action *a) { window_scroll_to(win, pos); else window_cursor_to(win, pos); + + if (mode == &vis_modes[VIS_MODE_VISUAL_LINE]) { + Filerange sel = window_selection_get(win); + sel.end = text_char_prev(txt, sel.end); + size_t start = text_line_begin(txt, sel.start); + size_t end = text_line_end(txt, sel.end); + if (sel.start == pos) { /* extend selection upwards */ + sel.end = start; + sel.start = end; + } else { /* extend selection downwards */ + sel.start = start; + sel.end = end; + } + window_selection_set(win, &sel); + c.range = sel; + } } else if (a->movement->type & INCLUSIVE) { Iterator it = text_iterator_get(txt, c.range.end); text_iterator_char_next(&it, NULL); @@ -945,7 +961,7 @@ static void action_do(Action *a) { } } } - } else if (mode == &vis_modes[VIS_MODE_VISUAL]) { + } else if (mode == &vis_modes[VIS_MODE_VISUAL] || mode == &vis_modes[VIS_MODE_VISUAL_LINE]) { c.range = window_selection_get(win); if (!text_range_valid(&c.range)) c.range.start = c.range.end = pos; @@ -955,7 +971,7 @@ static void action_do(Action *a) { a->op->func(&c); if (mode == &vis_modes[VIS_MODE_OPERATOR]) switchmode_to(mode_prev); - else if (mode == &vis_modes[VIS_MODE_VISUAL]) + else if (mode == &vis_modes[VIS_MODE_VISUAL] || mode == &vis_modes[VIS_MODE_VISUAL_LINE]) switchmode(&(const Arg){ .i = VIS_MODE_NORMAL }); text_snapshot(txt); } @@ -137,6 +137,11 @@ Filerange window_selection_get(Win *win) { return sel; } +void window_selection_set(Win *win, Filerange *sel) { + win->sel = *sel; + window_draw(win); +} + Filerange window_viewport_get(Win *win) { return (Filerange){ .start = win->start, .end = win->end }; } @@ -782,10 +787,6 @@ void window_selection_start(Win *win) { curs_set(0); } -void window_selection_end(Win *win) { - win->sel.end = window_cursor_get(win); -} - void window_syntax_set(Win *win, Syntax *syntax) { win->syntax = syntax; } @@ -58,10 +58,10 @@ void window_cursor_to(Win*, size_t pos); /* start selected area at current cursor position. further cursor movements will * affect the selected region. */ void window_selection_start(Win*); -void window_selection_end(Win*); /* returns the currently selected text region, is either empty or well defined, * i.e. sel.start <= sel.end */ Filerange window_selection_get(Win*); +void window_selection_set(Win*, Filerange *sel); /* clear selection and redraw window */ void window_selection_clear(Win*); /* get the currently displayed area in bytes from the start of the file */ |
