diff options
author | Jarno Mäkipää <jmakip87@gmail.com> | 2019-04-03 21:44:59 +0300 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2019-04-03 19:49:36 -0500 |
commit | 5ec4aa7ee58cdf209db31e8dda53224026d1167f (patch) | |
tree | 36acb82cfabf0578923e6f61c4572aba4028754e /toys | |
parent | 7b11e55921aa4e5d3265e96756436ee97641ccf5 (diff) | |
download | toybox-5ec4aa7ee58cdf209db31e8dda53224026d1167f.tar.gz |
VI rewrote char delete and hjkl movements
Reimplemented basic cursor movements and char delete.
In order to work more correctly with utf-8 data.
x,h,j,k,l seems to work now with test data such as
tests/files/utf8/test2.txt
hjkl now accept count parameter so 1000j will scroll file 1000 lines
relative move to bottom
word movements w,e,b... still need to be still reimplemented in order to
step correctly on utf-8 data
Diffstat (limited to 'toys')
-rw-r--r-- | toys/pending/vi.c | 154 |
1 files changed, 100 insertions, 54 deletions
diff --git a/toys/pending/vi.c b/toys/pending/vi.c index c5c87507..31516b55 100644 --- a/toys/pending/vi.c +++ b/toys/pending/vi.c @@ -63,12 +63,13 @@ 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 void cur_left(); -static void cur_right(); -static void cur_up(); -static void cur_down(); +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 void check_cursor_bounds(); static void adjust_screen_buffer(); @@ -252,29 +253,57 @@ int ex_deol(int count) return 1; } -//does not work with utf8 yet int vi_x(int count) { char *s; + char *last; int *l; - int *p; + int length = 0; + int width = 0; + int remaining = 0; + char *end; + char *start; if (!c_r) return 0; s = c_r->line->str_data; l = &c_r->line->str_len; - p = &TT.cur_col; - if (!(*l)) return 0; - if ((*p) == (*l)-1) { - s[*p] = 0; - if (*p) (*p)--; - (*l)--; + + last = utf8_last(s,*l); + if (last == s+TT.cur_col) { + memset(last, 0, (*l)-TT.cur_col); + *l = TT.cur_col; + if (!TT.cur_col) return 1; + last = utf8_last(s, TT.cur_col); + TT.cur_col = last-s; + return 1; + } + + start = s+TT.cur_col; + end = start; + remaining = (*l)-TT.cur_col; + for (;remaining;) { + int next = utf8_lnw(&width, end, remaining); + if (next && width) { + if (!count) break; + count--; + } if (!next) break; + length += next; + end += next; + remaining -= next; + } + if (remaining) { + memmove(start, end, remaining); + memset(end+remaining,0,end-start); } else { - memmove(s+(*p), s+(*p)+1, (*l)-(*p)); - s[*l] = 0; - (*l)--; + memset(start,0,(*l)-TT.cur_col); } - count--; - return (count) ? vi_x(count) : 1; + *l -= end-start; + if (!TT.cur_col) return 1; + if (TT.cur_col == (*l)) { + last = utf8_last(s, TT.cur_col); + TT.cur_col = last-s; + } + return 1; } //move commands does not behave correct way yet. @@ -402,7 +431,7 @@ struct vi_cmd_param { int (*vi_cmd_ptr)(int); }; -struct vi_cmd_param vi_cmds[7] = +struct vi_cmd_param vi_cmds[11] = { {"dd", &ex_dd}, {"dw", &ex_dw}, @@ -411,6 +440,10 @@ struct vi_cmd_param vi_cmds[7] = {"b", &vi_movb}, {"e", &vi_move}, {"x", &vi_x}, + {"h", &cur_left}, + {"j", &cur_down}, + {"k", &cur_up}, + {"l", &cur_right}, }; int run_vi_cmd(char *cmd) @@ -426,7 +459,7 @@ int run_vi_cmd(char *cmd) else { cmd = cmd_e; } - for (; i<7; i++) { + for (; i < 11; i++) { if (strstr(cmd, vi_cmds[i].cmd)) { return vi_cmds[i].vi_cmd_ptr(val); } @@ -440,7 +473,7 @@ int search_str(char *s) struct linelist *lst = c_r; char *c = strstr(&c_r->line->str_data[TT.cur_col], s); if (c) { - TT.cur_col = c_r->line->str_data-c; + TT.cur_col = c_r->line->str_data-c; //TODO ?? TT.cur_col = c-c_r->line->str_data; } else for (; !c;) { @@ -523,18 +556,6 @@ void vi_main(void) } if (TT.vi_mode == 1) { //NORMAL switch (key) { - case 'h': - cur_left(); - break; - case 'j': - cur_down(); - break; - case 'k': - cur_up(); - break; - case 'l': - cur_right(); - break; case '/': case '?': case ':': @@ -554,7 +575,7 @@ void vi_main(void) break; default: if (key > 0x20 && key < 0x7B) { - vi_buf[vi_buf_pos] = key; + vi_buf[vi_buf_pos] = key;//TODO handle input better vi_buf_pos++; if (run_vi_cmd(vi_buf)) { memset(vi_buf, 0, 16); @@ -562,6 +583,7 @@ void vi_main(void) } else if (vi_buf_pos == 16) { vi_buf_pos = 0; + memset(vi_buf, 0, 16); } } @@ -834,12 +856,10 @@ static int draw_rune(char *c, int x, int y, int highlight) static void check_cursor_bounds() { - if (c_r->line->str_len-1 < TT.cur_col) { - if (c_r->line->str_len == 0) - TT.cur_col = 0; - else - TT.cur_col = c_r->line->str_len-1; - } + 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); } static void adjust_screen_buffer() @@ -963,6 +983,20 @@ static int utf8_dec(char key, char *utf8_scratch, int *sta_p) return 0; } +static char* utf8_last(char* str, int size) +{ + char* end = str+size; + int pos = size; + int len = 0; + int width = 0; + while (pos >= 0) { + len = utf8_lnw(&width, end, size-pos); + if (len && width) return end; + end--; pos--; + } + return 0; +} + static int draw_str_until(int *drawn, char *str, int width, int bytes) { int rune_width = 0; @@ -991,38 +1025,50 @@ write_bytes: return max_width-width; } -static void cur_left() +static int cur_left(int count) { - if (!TT.cur_col) return; - TT.cur_col--; + for (;count--;) { + if (!TT.cur_col) return 1; - if (!utf8_len(&c_r->line->str_data[TT.cur_col])) cur_left(); + TT.cur_col--; + check_cursor_bounds();//has bit ugly recursion hidden here + } + return 1; } -static void cur_right() +static int cur_right(int count) { - if (c_r->line->str_len <= 1) return; - if (TT.cur_col == c_r->line->str_len-1) return; - TT.cur_col++; - if (!utf8_len(&c_r->line->str_data[TT.cur_col])) cur_right(); + for (;count--;) { + if (c_r->line->str_len <= 1) return 1; + if (TT.cur_col >= c_r->line->str_len-1) { + TT.cur_col = utf8_last(c_r->line->str_data, c_r->line->str_len) + - c_r->line->str_data; + return 1; + } + 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); + } + return 1; } -static void cur_up() +static int cur_up(int count) { - if (c_r->up != 0) + for (;count-- && c_r->up;) c_r = c_r->up; - if (!utf8_len(&c_r->line->str_data[TT.cur_col])) cur_left(); check_cursor_bounds(); adjust_screen_buffer(); + return 1; } -static void cur_down() +static int cur_down(int count) { - if (c_r->down != 0) + for (;count-- && c_r->down;) c_r = c_r->down; - if (!utf8_len(&c_r->line->str_data[TT.cur_col])) cur_left(); check_cursor_bounds(); adjust_screen_buffer(); + return 1; } |