aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--toys/pending/vi.c390
1 files changed, 320 insertions, 70 deletions
diff --git a/toys/pending/vi.c b/toys/pending/vi.c
index 2beedf49..f7edc074 100644
--- a/toys/pending/vi.c
+++ b/toys/pending/vi.c
@@ -25,6 +25,11 @@ GLOBALS(
unsigned screen_height;
unsigned screen_width;
int vi_mode;
+ int count0;
+ int count1;
+ int vi_mov_flag;
+ int modified;
+ char vi_reg;
)
/*
@@ -38,9 +43,6 @@ GLOBALS(
* ex callbacks
*
* FEATURE: ex: / ? % //atleast easy cases
- * vi: x dw d$ d0
- * vi: yw yy (y0 y$)
- * vi+ex: gg G //line movements
* ex: r
* ex: !external programs
* ex: w filename //only writes to same file now
@@ -59,17 +61,17 @@ static int draw_str_until(int *drawn, char *str, int width, int bytes);
static void draw_char(char c, int x, int y, int highlight);
//utf8 support
static int utf8_lnw(int* width, char* str, int bytes);
-static int utf8_dec(char key, char *utf8_scratch, int *sta_p) ;
+static int utf8_dec(char key, char *utf8_scratch, int *sta_p);
static int utf8_len(char *str);
static int utf8_width(char *str, int bytes);
static int draw_rune(char *c, int x, int y, int highlight);
static char* utf8_last(char* str, int size);
-static int cur_left(int count);
-static int cur_right(int count);
-static int cur_up(int count);
-static int cur_down(int count);
+static int cur_left(int count0, int count1, char* unused);
+static int cur_right(int count0, int count1, char* unused);
+static int cur_up(int count0, int count1, char* unused);
+static int cur_down(int count0, int count1, char* unused);
static void check_cursor_bounds();
static void adjust_screen_buffer();
@@ -92,7 +94,7 @@ struct str_line *il;
struct linelist *text; //file loaded into buffer
struct linelist *scr_r;//current screen coord 0 row
struct linelist *c_r;//cursor position row
-int modified;
+
void dlist_insert_nomalloc(struct double_list **list, struct double_list *new)
{
@@ -114,6 +116,7 @@ struct double_list *dlist_insert(struct double_list **list, char *data)
return new;
}
+//TODO implement
void linelist_unload()
{
@@ -126,7 +129,7 @@ void write_file(char *filename)
if (!filename)
filename = (char*)*toys.optargs;
fp = fopen(filename, "w");
- if (!fp) return ;
+ if (!fp) return;
while (lst) {
fprintf(fp, "%s\n", lst->line->str_data);
lst = lst->down;
@@ -188,9 +191,16 @@ int linelist_load(char *filename)
return 1;
}
+
+int vi_yy(char reg, int count0, int count1)
+{
+ return 1;
+}
+
//TODO this is overly complicated refactor with lib dllist
-int ex_dd(int count)
+int vi_dd(char reg, int count0, int count1)
{
+ int count = count0*count1;
struct linelist *lst = c_r;
if (c_r == text && text == scr_r) {
if (!text->down && !text->up && text->line) {
@@ -235,26 +245,17 @@ int ex_dd(int count)
recursion_exit:
count--;
//make this recursive
- if (count)
- return ex_dd(count);
+ if (count>0)
+ return vi_dd(reg, count, 1);
success_exit:
check_cursor_bounds();
adjust_screen_buffer();
return 1;
}
-
-int ex_dw(int count)
-{
- return 1;
-}
-
-int ex_deol(int count)
-{
- return 1;
-}
-
-int vi_x(int count)
+//TODO i think this thing has bug when removing >40 chars from 80 wide line
+static int vi_x(char reg, int count0, int count1)
{
+ int count = count0;
char *s;
char *last;
int *l;
@@ -293,7 +294,7 @@ int vi_x(int count)
}
if (remaining) {
memmove(start, end, remaining);
- memset(end+remaining,0,end-start);
+ memset(start+remaining,0,end-start);
} else {
memset(start,0,(*l)-TT.cur_col);
}
@@ -307,34 +308,55 @@ int vi_x(int count)
}
//move commands does not behave correct way yet.
-//only jump to next space for now.
-int vi_movw(int count)
+int vi_movw(int count0, int count1, char* unused)
{
+ int count = count0*count1;
+ const char *empties = " \t\n\r";
+ const char *specials = ",.=-+*/(){}<>[]";
+// char *current = 0;
if (!c_r)
return 0;
- //could we call moveend first
- while (c_r->line->str_data[TT.cur_col] > ' ')
- TT.cur_col++;
- while (c_r->line->str_data[TT.cur_col] <= ' ') {
+ if (TT.cur_col == c_r->line->str_len-1 || !c_r->line->str_len)
+ goto next_line;
+ if (strchr(empties, c_r->line->str_data[TT.cur_col]))
+ goto find_non_empty;
+ if (strchr(specials, c_r->line->str_data[TT.cur_col])) {
+ for (;strchr(specials, c_r->line->str_data[TT.cur_col]); ) {
+ TT.cur_col++;
+ if (TT.cur_col == c_r->line->str_len-1)
+ goto next_line;
+ }
+ } else for (;!strchr(specials, c_r->line->str_data[TT.cur_col]) &&
+ !strchr(empties, c_r->line->str_data[TT.cur_col]);) {
+ TT.cur_col++;
+ if (TT.cur_col == c_r->line->str_len-1)
+ goto next_line;
+ }
+
+ for (;strchr(empties, c_r->line->str_data[TT.cur_col]); ) {
TT.cur_col++;
- if (!c_r->line->str_data[TT.cur_col]) {
+find_non_empty:
+ if (TT.cur_col == c_r->line->str_len-1) {
+next_line:
//we could call j and g0
if (!c_r->down) return 0;
c_r = c_r->down;
TT.cur_col = 0;
+ if (!c_r->line->str_len) break;
}
}
count--;
- if (count>1)
- return vi_movw(count);
+ if (count>0)
+ return vi_movw(count, 1, 0);
check_cursor_bounds();
adjust_screen_buffer();
return 1;
}
-int vi_movb(int count)
+static int vi_movb(int count0, int count1, char* unused)
{
+ int count = count0*count1;
if (!c_r)
return 0;
if (!TT.cur_col) {
@@ -357,24 +379,26 @@ int vi_movb(int count)
exit_function:
count--;
if (count>1)
- return vi_movb(count);
+ return vi_movb(count, 1, 0);
check_cursor_bounds();
adjust_screen_buffer();
return 1;
}
-int vi_move(int count)
+static int vi_move(int count0, int count1, char *unused)
{
+ int count = count0*count1;
if (!c_r)
return 0;
if (TT.cur_col < c_r->line->str_len)
TT.cur_col++;
if (c_r->line->str_data[TT.cur_col] <= ' ' || count > 1)
- vi_movw(count); //find next word;
+ vi_movw(count, 1, 0); //find next word;
while (c_r->line->str_data[TT.cur_col] > ' ')
TT.cur_col++;
if (TT.cur_col) TT.cur_col--;
+ TT.vi_mov_flag |= 2;
check_cursor_bounds();
adjust_screen_buffer();
return 1;
@@ -426,46 +450,266 @@ void i_split()
adjust_screen_buffer();
}
+static int vi_zero(int count0, int count1, char *unused)
+{
+ TT.cur_col = 0;
+ return 1;
+}
+
+static int vi_eol(int count0, int count1, char *unused)
+{
+ int count = count0*count1;
+ for (;count > 1 && c_r->down; count--)
+ c_r = c_r->down;
+
+ if (c_r && c_r->line->str_len)
+ TT.cur_col = c_r->line->str_len-1;
+ TT.vi_mov_flag |= 2;
+ check_cursor_bounds();
+ return 1;
+}
+
+static int vi_find_c(int count0, int count1, char *symbol)
+{
+ int count = count0*count1;
+ if (c_r && c_r->line->str_len) {
+ while (count--) {
+ char* pos = strstr(&c_r->line->str_data[TT.cur_col], symbol);
+ if (pos) {
+ TT.cur_col = pos-c_r->line->str_data;
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static int vi_find_cb(int count0, int count1, char *symbol)
+{
+ //do backward search
+ return 1;
+}
+
+//if count is not spesified should go to last line
+static int vi_go(int count0, int count1, char *symbol)
+{
+ c_r = text;
+ while(--count0) {
+ if (c_r && c_r->down) c_r = c_r->down;
+ }
+ TT.cur_col = 0;
+ check_cursor_bounds();
+ adjust_screen_buffer();
+ return 1;
+}
+
+//need to refactor when implementing yank buffers
+static int vi_delete(char reg, struct linelist *row, int col, int flags)
+{
+ if (row == c_r) {
+ if (col < TT.cur_col) {
+ int distance = TT.cur_col - col;
+ TT.cur_col = col;
+ vi_x(reg, distance, 1);
+ } else {
+ int distance = col - TT.cur_col;
+ if (distance > 0) vi_x(reg, distance, 1);
+ }
+ if (TT.vi_mov_flag&2)
+ vi_x(reg, 1, 1);
+ }
+ return 1;
+}
+
+static int vi_D(char reg, int count0, int count1)
+{
+ int prev_col = TT.cur_col;
+ struct linelist *pos = c_r;
+ if (!count0) return 1;
+ vi_eol(1, 1, 0);
+ vi_delete(reg, pos, prev_col, 0);
+ count0--;
+ if (count0 && c_r->down) {
+ c_r = c_r->down;
+ vi_dd(reg, count0, 1);
+ }
+ return 1;
+}
+
+static int vi_join(char reg, int count0, int count1)
+{
+ while (count0--) {
+ if (c_r && c_r->down) {
+ int size = c_r->line->str_len+c_r->down->line->str_len;
+ if (size > c_r->line->alloc_len) {
+ if (size > c_r->down->line->alloc_len) {
+ c_r->line->str_data = xrealloc(c_r->line->str_data,
+ c_r->line->alloc_len*2+il->alloc_len*2);
+ memmove(&c_r->line->str_data[c_r->line->str_len],
+ c_r->down->line->str_data,c_r->down->line->str_len);
+ c_r->line->str_len = size;
+ c_r = c_r->down;
+ c_r->line->alloc_len = c_r->line->alloc_len*2+2*il->alloc_len;
+ vi_dd(0,1,1);
+ } else {
+ memmove(&c_r->down->line->str_data[c_r->line->str_len],
+ c_r->down->line->str_data,c_r->down->line->str_len);
+ memmove(c_r->down->line->str_data,c_r->line->str_data,
+ c_r->line->str_len);
+ c_r->down->line->str_len = size;
+ vi_dd(0,1,1);
+ }
+ } else {
+ memmove(&c_r->line->str_data[c_r->line->str_len],
+ c_r->down->line->str_data,c_r->down->line->str_len);
+ c_r->line->str_len = size;
+ c_r = c_r->down;
+ vi_dd(0,1,1);
+ }
+ c_r = c_r->up;
+
+ }
+ }
+ return 1;
+}
+
+static int vi_change(char reg, struct linelist *row, int col, int flags)
+{
+ vi_delete(reg, row, col, flags);
+ TT.vi_mode = 2;
+ return 1;
+}
+
+static int vi_yank(char reg, struct linelist *row, int col, int flags)
+{
+ return 1;
+}
+
+//NOTES
+//vi-mode cmd syntax is
+//("[REG])[COUNT0]CMD[COUNT1](MOV)
+//where:
+//-------------------------------------------------------------
+//"[REG] is optional buffer where deleted/yanked text goes REG can be
+// atleast 0-9, a-z or default "
+//[COUNT] is optional multiplier for cmd execution if there is 2 COUNT
+// operations they are multiplied together
+//CMD is operation to be executed
+//(MOV) is movement operation, some CMD does not require MOV and some
+// have special cases such as dd, yy, also movements can work without
+// CMD
+//ex commands can be even more complicated than this....
+//
struct vi_cmd_param {
+ const char* cmd;
+ unsigned flags;
+ int (*vi_cmd)(char, struct linelist*, int, int);//REG,row,col,FLAGS
+};
+struct vi_mov_param {
+ const char* mov;
+ unsigned flags;
+ int (*vi_mov)(int, int, char*);//COUNT0,COUNT1,params
+};
+//spesial cases without MOV and such
+struct vi_spesial_param {
const char *cmd;
- int (*vi_cmd_ptr)(int);
+ int (*vi_spesial)(char, int, int);//REG,COUNT0,COUNT1
};
-
-struct vi_cmd_param vi_cmds[11] =
+struct vi_spesial_param vi_spesial[5] =
{
- {"dd", &ex_dd},
- {"dw", &ex_dw},
- {"d$", &ex_deol},
- {"w", &vi_movw},
- {"b", &vi_movb},
- {"e", &vi_move},
+ {"dd", &vi_dd},
+ {"yy", &vi_yy},
+ {"D", &vi_D},
+ {"J", &vi_join},
{"x", &vi_x},
- {"h", &cur_left},
- {"j", &cur_down},
- {"k", &cur_up},
- {"l", &cur_right},
+};
+//there is around ~47 vi moves
+//some of them need extra params
+//such as f and '
+struct vi_mov_param vi_movs[12] =
+{
+ {"0", 0, &vi_zero},
+ {"b", 0, &vi_movb},
+ {"e", 0, &vi_move},
+ {"G", 0, &vi_go},
+ {"h", 0, &cur_left},
+ {"j", 0, &cur_down},
+ {"k", 0, &cur_up},
+ {"l", 0, &cur_right},
+ {"w", 0, &vi_movw},
+ {"$", 0, &vi_eol},
+ {"f", 1, &vi_find_c},
+ {"F", 1, &vi_find_cb},
+};
+//change and delete unfortunately behave different depending on move command,
+//such as ce cw are same, but dw and de are not...
+//also dw stops at w position and cw seem to stop at e pos+1...
+//so after movement we need to possibly set up some flags before executing
+//command, and command needs to adjust...
+struct vi_cmd_param vi_cmds[3] =
+{
+ {"c", 1, &vi_change},
+ {"d", 1, &vi_delete},
+ {"y", 1, &vi_yank},
};
int run_vi_cmd(char *cmd)
{
+ int i = 0;
int val = 0;
char *cmd_e;
- errno = 0;
- int i = 0;
+ int (*vi_cmd)(char, struct linelist*, int, int) = 0;
+ int (*vi_mov)(int, int, char*) = 0;
+ TT.count0 = 0;
+ TT.count1 = 0;
+ TT.vi_reg = '"';
+ TT.vi_mov_flag = 0;
+ if (*cmd == '"') {
+ cmd++;
+ TT.vi_reg = *cmd; //TODO check validity
+ cmd++;
+ }
val = strtol(cmd, &cmd_e, 10);
- if (errno || val == 0) {
- val = 1;
+ if (errno || val == 0) val = 1;
+ else cmd = cmd_e;
+ TT.count0 = val;
+
+ for (i = 0; i < 5; i++) {
+ if (strstr(cmd, vi_spesial[i].cmd)) {
+ return vi_spesial[i].vi_spesial(TT.vi_reg, TT.count0, TT.count1);
+ }
}
- else {
- cmd = cmd_e;
+
+ for (i = 0; i < 3; i++) {
+ if (!strncmp(cmd, vi_cmds[i].cmd, strlen(vi_cmds[i].cmd))) {
+ vi_cmd = vi_cmds[i].vi_cmd;
+ cmd += strlen(vi_cmds[i].cmd);
+ break;
+ }
}
- for (; i < 11; i++) {
- if (strstr(cmd, vi_cmds[i].cmd)) {
- return vi_cmds[i].vi_cmd_ptr(val);
+ val = strtol(cmd, &cmd_e, 10);
+ if (errno || val == 0) val = 1;
+ else cmd = cmd_e;
+ TT.count1 = val;
+
+ for (i = 0; i < 12; i++) {
+ if (!strncmp(cmd, vi_movs[i].mov, strlen(vi_movs[i].mov))) {
+ vi_mov = vi_movs[i].vi_mov;
+ TT.vi_mov_flag = vi_movs[i].flags;
+ cmd++;
+ if (TT.vi_mov_flag&1 && !(*cmd)) return 0;
+ break;
}
}
+ if (vi_mov) {
+ int prev_col = TT.cur_col;
+ struct linelist *pos = c_r;
+ if (vi_mov(TT.count0, TT.count1, cmd)) {
+ if (vi_cmd) return (vi_cmd(TT.vi_reg, pos, prev_col, TT.vi_mov_flag));
+ else return 1;
+ } else return 0; //return some error
+ }
return 0;
-
}
int search_str(char *s)
@@ -669,6 +913,7 @@ void vi_main(void)
}
cleanup_vi:
+ linelist_unload();
tty_reset();
tty_esc("?1049l");
}
@@ -858,8 +1103,8 @@ static void check_cursor_bounds()
{
if (c_r->line->str_len == 0) TT.cur_col = 0;
else if (c_r->line->str_len-1 < TT.cur_col) TT.cur_col = c_r->line->str_len-1;
- if(utf8_width(&c_r->line->str_data[TT.cur_col], c_r->line->str_len-TT.cur_col) <= 0)
- cur_left(1);
+ if (utf8_width(&c_r->line->str_data[TT.cur_col], c_r->line->str_len-TT.cur_col) <= 0)
+ cur_left(1, 1, 0);
}
static void adjust_screen_buffer()
@@ -889,7 +1134,7 @@ static void adjust_screen_buffer()
//for each iteration
if (distance >= (int)TT.screen_height) {
int adj = distance - TT.screen_height;
- while(adj--) {
+ while (adj--) {
scr_r = scr_r->down;
}
}
@@ -1025,8 +1270,9 @@ write_bytes:
return max_width-width;
}
-static int cur_left(int count)
+static int cur_left(int count0, int count1, char* unused)
{
+ int count = count0*count1;
for (;count--;) {
if (!TT.cur_col) return 1;
@@ -1036,8 +1282,9 @@ static int cur_left(int count)
return 1;
}
-static int cur_right(int count)
+static int cur_right(int count0, int count1, char* unused)
{
+ int count = count0*count1;
for (;count--;) {
if (c_r->line->str_len <= 1) return 1;
if (TT.cur_col >= c_r->line->str_len-1) {
@@ -1048,13 +1295,14 @@ static int cur_right(int count)
TT.cur_col++;
if (utf8_width(&c_r->line->str_data[TT.cur_col],
c_r->line->str_len-TT.cur_col) <= 0)
- cur_right(1);
+ cur_right(1, 1, 0);
}
return 1;
}
-static int cur_up(int count)
+static int cur_up(int count0, int count1, char* unused)
{
+ int count = count0*count1;
for (;count-- && c_r->up;)
c_r = c_r->up;
@@ -1063,8 +1311,9 @@ static int cur_up(int count)
return 1;
}
-static int cur_down(int count)
+static int cur_down(int count0, int count1, char* unused)
{
+ int count = count0*count1;
for (;count-- && c_r->down;)
c_r = c_r->down;
@@ -1072,3 +1321,4 @@ static int cur_down(int count)
adjust_screen_buffer();
return 1;
}
+