aboutsummaryrefslogtreecommitdiff
path: root/config.def.h
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2014-09-03 16:22:16 +0200
committerMarc André Tanner <mat@brain-dump.org>2014-09-03 16:22:16 +0200
commit87ffbb9c0ab201efc3e729876455bc4ca9921124 (patch)
treedec19f99e8aee0da2007b80085c3948f0f109744 /config.def.h
parent3ef242ae90ed7c798b83e2765cb721ef64e7516d (diff)
downloadvis-87ffbb9c0ab201efc3e729876455bc4ca9921124.tar.gz
vis-87ffbb9c0ab201efc3e729876455bc4ca9921124.tar.xz
Enable text objects, introduce operator options
Diffstat (limited to 'config.def.h')
-rw-r--r--config.def.h129
1 files changed, 110 insertions, 19 deletions
diff --git a/config.def.h b/config.def.h
index dbdded9..1996ecf 100644
--- a/config.def.h
+++ b/config.def.h
@@ -9,13 +9,19 @@
{ { NONE(127) }, (func), { .name = (arg) } }, \
{ { CONTROL('B') }, (func), { .name = (arg) } }
+static Mode *mode, *mode_prev;
+static Vis *vis;
+static Mode vis_modes[];
+
static void switchmode(const Arg *arg);
+static void switchmode_to(Mode *new_mode);
enum {
VIS_MODE_BASIC,
VIS_MODE_MOVE,
VIS_MODE_TEXTOBJ,
VIS_MODE_OPERATOR,
+ VIS_MODE_OPERATOR_OPTION,
VIS_MODE_NORMAL,
VIS_MODE_VISUAL,
VIS_MODE_INSERT,
@@ -51,14 +57,14 @@ static Operator *ops[] = {
};
enum {
- MOVE_CHAR_PREV,
- MOVE_CHAR_NEXT,
MOVE_LINE_UP,
MOVE_LINE_DOWN,
MOVE_LINE_BEGIN,
MOVE_LINE_START,
MOVE_LINE_FINISH,
MOVE_LINE_END,
+ MOVE_CHAR_PREV,
+ MOVE_CHAR_NEXT,
MOVE_WORD_START_PREV,
MOVE_WORD_START_NEXT,
MOVE_WORD_END_PREV,
@@ -73,14 +79,14 @@ enum {
};
static Movement moves[] = {
- [MOVE_CHAR_PREV] = { .win = window_char_prev },
- [MOVE_CHAR_NEXT] = { .win = window_char_next },
[MOVE_LINE_UP] = { .win = window_line_up },
[MOVE_LINE_DOWN] = { .win = window_line_down },
[MOVE_LINE_BEGIN] = { .txt = text_line_begin, .type = LINEWISE },
[MOVE_LINE_START] = { .txt = text_line_start, .type = LINEWISE },
[MOVE_LINE_FINISH] = { .txt = text_line_finish, .type = LINEWISE },
[MOVE_LINE_END] = { .txt = text_line_end, .type = LINEWISE },
+ [MOVE_CHAR_PREV] = { .win = window_char_prev },
+ [MOVE_CHAR_NEXT] = { .win = window_char_next },
[MOVE_WORD_START_PREV] = { .txt = text_word_start_prev, .type = CHARWISE },
[MOVE_WORD_START_NEXT] = { .txt = text_word_start_next, .type = CHARWISE },
[MOVE_WORD_END_PREV] = { .txt = text_word_end_prev, .type = CHARWISE|INCLUSIVE },
@@ -96,6 +102,8 @@ static Movement moves[] = {
enum {
TEXT_OBJ_WORD,
+ TEXT_OBJ_LINE_UP,
+ TEXT_OBJ_LINE_DOWN,
TEXT_OBJ_SENTENCE,
TEXT_OBJ_PARAGRAPH,
TEXT_OBJ_OUTER_SQUARE_BRACKET,
@@ -116,6 +124,8 @@ enum {
static TextObject textobjs[] = {
[TEXT_OBJ_WORD] = { text_object_word },
+ [TEXT_OBJ_LINE_UP] = { text_object_line },
+ [TEXT_OBJ_LINE_DOWN] = { text_object_line },
[TEXT_OBJ_SENTENCE] = { text_object_sentence },
[TEXT_OBJ_PARAGRAPH] = { text_object_paragraph },
[TEXT_OBJ_OUTER_SQUARE_BRACKET] = { text_object_square_bracket, OUTER },
@@ -134,6 +144,11 @@ static TextObject textobjs[] = {
[TEXT_OBJ_INNER_BACKTICK] = { text_object_backtick, INNER },
};
+static TextObject *moves_linewise[] = {
+ [MOVE_LINE_UP] = &textobjs[TEXT_OBJ_LINE_UP],
+ [MOVE_LINE_DOWN] = &textobjs[TEXT_OBJ_LINE_DOWN],
+};
+
/* draw a statubar, do whatever you want with the given curses window */
static void statusbar(WINDOW *win, bool active, const char *filename, size_t line, size_t col) {
int width, height;
@@ -150,7 +165,7 @@ static void statusbar(WINDOW *win, bool active, const char *filename, size_t lin
}
}
-void quit(const Arg *arg) {
+static void quit(const Arg *arg) {
endwin();
exit(0);
}
@@ -169,6 +184,7 @@ static void mark_goto(const Arg *arg) {
static Action action, action_prev;
void action_do(Action *a);
+void action_reset(Action *a);
static void repeat(const Arg *arg) {
action_do(&action_prev);
@@ -178,17 +194,34 @@ static void count(const Arg *arg) {
action.count = action.count * 10 + arg->i;
}
+static void linewise(const Arg *arg) {
+ action.linewise = arg->b;
+}
+
static void operator(const Arg *arg) {
- action.op = ops[arg->i];
+ switchmode(&(const Arg){ .i = VIS_MODE_OPERATOR });
+ Operator *op = ops[arg->i];
+ if (action.op == op) {
+ /* hacky way to handle double operators i.e. things like
+ * dd, yy etc where the second char isn't a movement */
+ action.textobj = moves_linewise[MOVE_LINE_DOWN];
+ action_do(&action);
+ } else {
+ action.op = op;
+ }
}
-static bool operator_unknown(Key *key1, Key *key2) {
- action.op = NULL;
- return true;
+static bool operator_invalid(const char *str, size_t len) {
+ action_reset(&action);
+ switchmode_to(mode_prev);
+ return false;
}
static void movement(const Arg *arg) {
- action.movement = &moves[arg->i];
+ if (action.linewise && arg->i < LENGTH(moves_linewise))
+ action.textobj = moves_linewise[arg->i];
+ else
+ action.movement = &moves[arg->i];
action_do(&action);
}
@@ -199,6 +232,7 @@ static void textobj(const Arg *arg) {
void action_reset(Action *a) {
a->count = 0;
+ a->linewise = false;
a->op = NULL;
a->movement = NULL;
a->textobj = NULL;
@@ -234,20 +268,43 @@ void action_do(Action *a) {
c.range.end = it.pos;
}
} else if (a->textobj) {
- c.range = a->textobj->range(txt, pos);
- if (c.range.start != (size_t)-1 && a->textobj->type == OUTER) {
- c.range.start--;
- c.range.end++;
+ Filerange r;
+ c.range.start = c.range.end = pos;
+ for (int i = 0; i < a->count; i++) {
+ r = a->textobj->range(txt, pos);
+ // TODO range_valid?
+ if (r.start == (size_t)-1 || r.end == (size_t)-1)
+ continue;
+ if (a->textobj->type == OUTER) {
+ r.start--;
+ r.end++;
+ }
+ // TODO c.range = range_union(&c.range, &r);
+ c.range.start = MIN(c.range.start, r.start);
+ c.range.end = MAX(c.range.end, r.end);
+ if (i < a->count - 1) {
+ if (a->textobj == &textobjs[TEXT_OBJ_LINE_UP]) {
+ pos = c.range.start - 1;
+ } else {
+ pos = c.range.end + 1;
+ }
+ }
}
}
+
c.count = a->count;
- if (a->op)
+ if (a->op) {
a->op(&c);
+ if (mode == &vis_modes[VIS_MODE_OPERATOR])
+ switchmode_to(mode_prev);
+ }
+
if (a != &action_prev) {
if (a->op)
action_prev = *a;
action_reset(a);
}
+
}
/* use vim's
@@ -365,6 +422,20 @@ static KeyBinding vis_operators[] = {
{ /* empty last element, array terminator */ },
};
+static void vis_operators_enter(void) {
+ vis_modes[VIS_MODE_OPERATOR].parent = &vis_modes[VIS_MODE_OPERATOR_OPTION];
+}
+
+static void vis_operators_leave(void) {
+ vis_modes[VIS_MODE_OPERATOR].parent = &vis_modes[VIS_MODE_MOVE];
+}
+
+static KeyBinding vis_operator_options[] = {
+ { { NONE('v') }, linewise, { .b = false } },
+ { { NONE('V') }, linewise, { .b = true } },
+ { /* empty last element, array terminator */ },
+};
+
static KeyBinding vis_registers[] = { /* {a-zA-Z0-9.%#:-"} */
// { { NONE('"'), NONE('a') }, reg, { .i = 1 } },
{ /* empty last element, array terminator */ },
@@ -384,7 +455,7 @@ static KeyBinding vis_normal[] = {
{ { CONTROL('B') }, cursor, { .m = window_page_down } },
{ { NONE('.') }, repeat, { } },
{ { NONE('n') }, find_forward, { .s = "if" } },
- { { NONE('p') }, find_backward, { .s = "if" } },
+ { { NONE('N') }, find_backward, { .s = "if" } },
{ { NONE('x') }, cursor, { .f = vis_delete_key } },
{ { NONE('i') }, switchmode, { .i = VIS_MODE_INSERT } },
{ { NONE('v') }, switchmode, { .i = VIS_MODE_VISUAL } },
@@ -432,22 +503,35 @@ static bool vis_replace_input(const char *str, size_t len) {
static Mode vis_modes[] = {
[VIS_MODE_BASIC] = {
+ .name = "BASIC",
.parent = NULL,
.bindings = basic_movement,
},
[VIS_MODE_MOVE] = {
+ .name = "MOVE",
.parent = &vis_modes[VIS_MODE_BASIC],
.bindings = vis_movements,
},
[VIS_MODE_TEXTOBJ] = {
+ .name = "TEXTOBJ",
.parent = &vis_modes[VIS_MODE_MOVE],
.bindings = vis_textobjs,
},
- [VIS_MODE_OPERATOR] = {
+ [VIS_MODE_OPERATOR_OPTION] = {
+ .name = "OPERATOR-OPTION",
+ .parent = &vis_modes[VIS_MODE_TEXTOBJ],
+ .bindings = vis_operator_options,
+ },
+ [VIS_MODE_OPERATOR] = {
+ .name = "OPERATOR",
.parent = &vis_modes[VIS_MODE_MOVE],
.bindings = vis_operators,
+ .enter = vis_operators_enter,
+ .leave = vis_operators_leave,
+ .input = operator_invalid,
},
[VIS_MODE_NORMAL] = {
+ .name = "NORMAL",
.parent = &vis_modes[VIS_MODE_OPERATOR],
.bindings = vis_normal,
},
@@ -472,13 +556,20 @@ static Mode vis_modes[] = {
},
};
-static void switchmode(const Arg *arg) {
+static void switchmode_to(Mode *new_mode) {
if (mode->leave)
mode->leave();
- mode = &vis_modes[arg->i];
+ mode_prev = mode;
+ //fprintf(stderr, "%s -> %s\n", mode_prev->name, new_mode->name);
+ mode = new_mode;
if (mode->enter)
mode->enter();
// TODO display mode name somewhere?
+
+}
+
+static void switchmode(const Arg *arg) {
+ switchmode_to(&vis_modes[arg->i]);
}
/* incomplete list of usefule but currently missing functionality from nanos help ^G: