ledit

Text editor (WIP)
git clone git://lumidify.org/ledit.git (fast, but not encrypted)
git clone https://lumidify.org/git/ledit.git (encrypted, but very slow)
Log | Files | Refs | README | LICENSE

commit 67de119de536bb598da9aba39ecfdde09562a8d3
parent 5c1f64919a8a2974c107614f144fd932aa6db1bf
Author: lumidify <nobody@lumidify.org>
Date:   Mon,  1 Nov 2021 19:04:48 +0100

Add change command ('c')

Diffstat:
Mbuffer.c | 3+++
Mkeys_basic.c | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mkeys_basic_config.h | 2++
3 files changed, 80 insertions(+), 0 deletions(-)

diff --git a/buffer.c b/buffer.c @@ -1037,6 +1037,7 @@ ledit_buffer_delete_range( ledit_buffer_recalc_from_line(buffer, min > 0 ? min - 1 : min); } +/* Note: line_index* and byte_index* don't need to be sorted */ /* FIXME: use at least somewhat sensible variable names */ void ledit_buffer_delete_range_base( @@ -1049,6 +1050,8 @@ ledit_buffer_delete_range_base( /* range line x, range byte x */ int rgl1 = 0, rgb1 = 0, rgl2 = 0, rgb2 = 0; int new_line = 0, new_byte = 0; + /* FIXME: could this be simplified by just calculating the range and then using + the non-line-based version? */ if (line_based) { int x, softline1, softline2; ledit_line *line1 = ledit_buffer_get_line(buffer, line_index1); diff --git a/keys_basic.c b/keys_basic.c @@ -102,6 +102,7 @@ static void get_new_line_softline( int movement, int *new_line_ret, int *new_softline_ret ); static void move_cursor_logically(ledit_buffer *buffer, int movement_dir, int allow_illegal_index); +static void change_cb(ledit_buffer *buffer, int line, int char_pos, enum key_type type); /* FIXME: move to common */ static void @@ -587,6 +588,80 @@ screen_down(ledit_buffer *buffer, char *text, int len) { return (struct action){ACTION_NONE, NULL}; } +/* FIXME: clear selection on most commands */ +static struct action +change(ledit_buffer *buffer, char *text, int len) { + (void)text; + (void)len; + int num = 0; + struct key_stack_elem *e = pop_key_stack(); + if (buffer->sel.line1 != buffer->sel.line2 || buffer->sel.byte1 != buffer->sel.byte2) { + ledit_buffer_set_mode(buffer, INSERT); + delete_selection(buffer); + ledit_buffer_wipe_line_cursor_attrs(buffer, buffer->cur_line); + clear_key_stack(); + } else { + if (e != NULL) { + if (e->key & KEY_NUMBER) { + num = e->count; + e = pop_key_stack(); + } + if (e != NULL && e->motion_cb == &change_cb) { + int prevnum = e->count > 0 ? e->count : 1; + num = num > 0 ? num : 1; + int lines = num * prevnum; + int new_line, new_softline; + get_new_line_softline( + buffer, buffer->cur_line, buffer->cur_index, + lines - 1, &new_line, &new_softline + ); + ledit_line *ll = ledit_buffer_get_line(buffer, new_line); + PangoLayoutLine *pl = pango_layout_get_line_readonly(ll->layout, new_softline); + e->motion_cb(buffer, new_line, pl->start_index, KEY_MOTION_LINE); + clear_key_stack(); + } else if (e != NULL) { + /* FIXME: show message? */ + clear_key_stack(); + } + } + if (e == NULL) { + e = push_key_stack(); + e->key = KEY_MOTION; /* ? */ + e->count = num; + e->motion_cb = &change_cb; + } + } + return (struct action){ACTION_NONE, NULL}; +} + +static void +change_cb(ledit_buffer *buffer, int line, int char_pos, enum key_type type) { + /* set mode first so the deletion is included in the undo group */ + ledit_buffer_set_mode(buffer, INSERT); + int line_based = type == KEY_MOTION_LINE ? 1 : 0; + /* this hackery is needed to avoid deleting the entire last line and + instead leave an empty line - this should be made nicer (FIXME) */ + int pos1 = buffer->cur_index, pos2 = char_pos, x, sli; + if (line_based) { + ledit_line *ll = ledit_buffer_get_line(buffer, buffer->cur_line); + pango_layout_index_to_line_x(ll->layout, buffer->cur_index, 0, &sli, &x); + PangoLayoutLine *sl = pango_layout_get_line_readonly(ll->layout, sli); + pos1 = sl->start_index; + ll = ledit_buffer_get_line(buffer, line); + pango_layout_index_to_line_x(ll->layout, char_pos, 0, &sli, &x); + sl = pango_layout_get_line_readonly(ll->layout, sli); + pos2 = sl->start_index + sl->length; + } + /* force line_based to 0 (see comment about hackery above) */ + delete_range( + buffer, 0, 0, + buffer->cur_line, pos1, + line, pos2 + ); + paste_buffer_line_based = line_based; + ledit_buffer_wipe_line_cursor_attrs(buffer, buffer->cur_line); +} + static struct action key_d(ledit_buffer *buffer, char *text, int len) { (void)text; diff --git a/keys_basic_config.h b/keys_basic_config.h @@ -66,6 +66,7 @@ static struct action scroll_lines_down(ledit_buffer *buffer, char *text, int len static struct action move_to_line(ledit_buffer *buffer, char *text, int len); static struct action paste_normal(ledit_buffer *buffer, char *text, int len); static struct action paste_normal_backwards(ledit_buffer *buffer, char *text, int len); +static struct action change(ledit_buffer *buffer, char *text, int len); /* FIXME: maybe sort these and use binary search -> but that would mess with the catch-all keys */ @@ -101,6 +102,7 @@ static struct key keys_en[] = { {"9", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_9}, {"x", 0, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &key_x}, {"d", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION|KEY_NUMBERALLOWED, &key_d}, + {"c", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION|KEY_NUMBERALLOWED, &change}, {"v", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &enter_visual}, {"o", 0, 0, VISUAL, KEY_ANY, KEY_ANY, &switch_selection_end}, {"c", ControlMask, 0, INSERT|VISUAL, KEY_ANY, KEY_ANY, &clipcopy},