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 b113e1224270deb100329dec7cc42e05d8aead63
parent 2e039562f045bbcb2a7b29bd39031f0597953460
Author: lumidify <nobody@lumidify.org>
Date:   Wed, 10 Nov 2021 20:01:13 +0100

Implement Y and r

Diffstat:
Mkeys_basic.c | 111++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Mkeys_basic_config.h | 4++++
2 files changed, 94 insertions(+), 21 deletions(-)

diff --git a/keys_basic.c b/keys_basic.c @@ -179,6 +179,14 @@ clear_key_stack(void) { key_stack.len = 0; } +static struct action +err_invalid_key(ledit_buffer *buffer) { + ledit_window_show_message(buffer->window, "Invalid key", -1); + clear_key_stack(); + discard_repetition_stack(); + return (struct action){ACTION_NONE, NULL}; +} + /* FIXME: error if no motion cb and not number key */ static int get_key_repeat_and_motion_cb(motion_callback *cb_ret) { @@ -326,10 +334,11 @@ delete_range( ledit_buffer *buffer, int line_based, int selected, int line_index1, int byte_index1, - int line_index2, int byte_index2) { + int line_index2, int byte_index2, int copy_to_buffer) { (void)selected; /* FIXME */ - if (!paste_buffer) + if (copy_to_buffer && !paste_buffer) paste_buffer = txtbuf_new(); + txtbuf *buf = copy_to_buffer ? paste_buffer : txtbuf_new(); ledit_range cur_range, del_range; cur_range.line1 = buffer->cur_line; cur_range.byte1 = buffer->cur_index; @@ -338,13 +347,15 @@ delete_range( line_index1, byte_index1, line_index2, byte_index2, &buffer->cur_line, &buffer->cur_index, - &del_range, paste_buffer + &del_range, buf ); cur_range.line2 = buffer->cur_line; cur_range.byte2 = buffer->cur_index; ledit_push_undo_delete( - buffer->undo, paste_buffer, del_range, cur_range, 1, buffer->common->mode + buffer->undo, buf, del_range, cur_range, 1, buffer->common->mode ); + if (!copy_to_buffer) + txtbuf_destroy(buf); } static void @@ -395,7 +406,7 @@ delete_selection(ledit_buffer *buffer) { delete_range( buffer, 0, 0, buffer->sel.line1, buffer->sel.byte1, - buffer->sel.line2, buffer->sel.byte2 + buffer->sel.line2, buffer->sel.byte2, 1 ); paste_buffer_line_based = 0; /* FIXME: maybe just set this to the current cursor pos? */ @@ -453,7 +464,7 @@ delete_chars_forwards(ledit_buffer *buffer, char *text, int len) { delete_range( buffer, 0, 0, buffer->cur_line, buffer->cur_index, - buffer->cur_line, end_index + buffer->cur_line, end_index, 1 ); paste_buffer_line_based = 0; buffer->cur_index = ledit_buffer_get_legal_normal_pos( @@ -480,7 +491,7 @@ delete_chars_backwards(ledit_buffer *buffer, char *text, int len) { delete_range( buffer, 0, 0, buffer->cur_line, start_index, - buffer->cur_line, buffer->cur_index + buffer->cur_line, buffer->cur_index, 1 ); paste_buffer_line_based = 0; /* I guess this is technically unnecessary since only @@ -777,7 +788,7 @@ delete_to_eol(ledit_buffer *buffer, char *text, int len) { delete_range( buffer, 0, 0, buffer->cur_line, buffer->cur_index, - buffer->cur_line, sl->start_index + sl->length + buffer->cur_line, sl->start_index + sl->length, 1 ); paste_buffer_line_based = 0; buffer->cur_index = ledit_buffer_get_legal_normal_pos( @@ -804,7 +815,7 @@ change_to_eol(ledit_buffer *buffer, char *text, int len) { delete_range( buffer, 0, 0, buffer->cur_line, buffer->cur_index, - buffer->cur_line, sl->start_index + sl->length + buffer->cur_line, sl->start_index + sl->length, 1 ); paste_buffer_line_based = 0; ledit_buffer_wipe_line_cursor_attrs(buffer, buffer->cur_line); @@ -880,7 +891,7 @@ change_cb(ledit_buffer *buffer, int line, int char_pos, enum key_type type) { delete_range( buffer, 0, 0, buffer->cur_line, pos1, - line, pos2 + line, pos2, 1 ); paste_buffer_line_based = line_based; ledit_buffer_wipe_line_cursor_attrs(buffer, buffer->cur_line); @@ -936,6 +947,27 @@ yank(ledit_buffer *buffer, char *text, int len) { return (struct action){ACTION_NONE, NULL}; } +static struct action +yank_lines(ledit_buffer *buffer, char *text, int len) { + (void)text; + (void)len; + int num = get_key_repeat(); + if (num == -1) + return err_invalid_key(buffer); + else if (num == 0) + num = 1; + int new_line, new_softline; + get_new_line_softline( + buffer, buffer->cur_line, buffer->cur_index, + num - 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); + yank_cb(buffer, new_line, pl->start_index, KEY_MOTION_LINE); + clear_key_stack(); + return (struct action){ACTION_NONE, NULL}; +} + static void yank_cb(ledit_buffer *buffer, int line, int char_pos, enum key_type type) { int line_based = type == KEY_MOTION_LINE ? 1 : 0; @@ -1019,7 +1051,7 @@ key_d_cb(ledit_buffer *buffer, int line, int char_pos, enum key_type type) { delete_range( buffer, line_based, 0, buffer->cur_line, buffer->cur_index, - line, char_pos + line, char_pos, 1 ); paste_buffer_line_based = line_based; ledit_buffer_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->cur_index); @@ -1242,17 +1274,18 @@ static struct action backspace(ledit_buffer *buffer, char *text, int len) { (void)text; (void)len; + /* FIXME: don't copy to paste buffer on del_sel here; delete entire grapheme */ if (delete_selection(buffer)) { /* NOP */ } else if (buffer->cur_index == 0) { if (buffer->cur_line != 0) { ledit_line *l1 = ledit_buffer_get_line(buffer, buffer->cur_line - 1); - delete_range(buffer, 0, 0, buffer->cur_line - 1, l1->len, buffer->cur_line, 0); + delete_range(buffer, 0, 0, buffer->cur_line - 1, l1->len, buffer->cur_line, 0, 0); } } else { ledit_line *l = ledit_buffer_get_line(buffer, buffer->cur_line); int i = ledit_line_prev_utf8(l, buffer->cur_index); - delete_range(buffer, 0, 0, buffer->cur_line, buffer->cur_index, buffer->cur_line, i); + delete_range(buffer, 0, 0, buffer->cur_line, buffer->cur_index, buffer->cur_line, i, 0); } ledit_buffer_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->cur_index); return (struct action){ACTION_NONE, NULL}; @@ -1267,11 +1300,11 @@ delete_key(ledit_buffer *buffer, char *text, int len) { /* NOP */ } else if (buffer->cur_index == cur_line->len) { if (buffer->cur_line != buffer->lines_num - 1) { - delete_range(buffer, 0, 0, buffer->cur_line, cur_line->len, buffer->cur_line + 1, 0); + delete_range(buffer, 0, 0, buffer->cur_line, cur_line->len, buffer->cur_line + 1, 0, 0); } } else { int i = ledit_line_next_utf8(cur_line, buffer->cur_index); - delete_range(buffer, 0, 0, buffer->cur_line, buffer->cur_index, buffer->cur_line, i); + delete_range(buffer, 0, 0, buffer->cur_line, buffer->cur_index, buffer->cur_line, i, 0); } ledit_buffer_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->cur_index); return (struct action){ACTION_NONE, NULL}; @@ -1923,16 +1956,52 @@ GEN_MOVE_TO_CHAR( ) static struct action +replace_cb(ledit_buffer *buffer, char *text, int len) { + int start_index = buffer->cur_index; + /* FIXME: replace with (key repeat) * text instead of just text */ + int end_index = ledit_buffer_next_cursor_pos( + buffer, buffer->cur_line, buffer->cur_index, 1 + ); + delete_range( + buffer, 0, 0, + buffer->cur_line, start_index, buffer->cur_line, end_index, 0 + ); + insert_text( + buffer, buffer->cur_line, start_index, text, len, + buffer->cur_line, start_index, buffer->cur_line, start_index, 0 + ); + /* this should not be necessary, but just in case */ + buffer->cur_index = ledit_buffer_get_legal_normal_pos( + buffer, buffer->cur_line, buffer->cur_index + ); + push_undo_empty_insert(buffer, buffer->cur_line, buffer->cur_index, 0); + grab_char_cb = NULL; + return (struct action){ACTION_NONE, NULL}; +} + +static struct action +replace(ledit_buffer *buffer, char *text, int len) { + (void)buffer; + (void)text; + (void)len; + int num = get_key_repeat(); + if (num != 0) + return err_invalid_key(buffer); + grab_char_cb = &replace_cb; + return (struct action){ACTION_NONE, NULL}; +} + +static struct action handle_key(ledit_buffer *buffer, char *key_text, int len, KeySym sym, unsigned int key_state, int lang_index, int *found) { struct key *cur_keys = keys[lang_index].keys; int num_keys = keys[lang_index].num_keys; struct key_stack_elem *e = peek_key_stack(); - /* FIXME: allow to escape this grabbing somehow */ - /* -> I guess escape *does* actually work because it - results in ascii 1b (escape) in this string, which - will usually not be found in the text (but this is - a bit of a hack) */ - if (len > 0 && grab_char_cb) { + /* FIXME: check if control chars in text */ + /* FIXME: this is a bit of a hack because it's hardcoded */ + if (grab_char_cb && sym == XK_Escape) { + grab_char_cb = NULL; + return (struct action){ACTION_NONE, NULL}; + } else if (len > 0 && grab_char_cb) { *found = 1; return grab_char_cb(buffer, key_text, len); } diff --git a/keys_basic_config.h b/keys_basic_config.h @@ -88,6 +88,8 @@ static struct action delete_to_eol(ledit_buffer *buffer, char *text, int len); static struct action delete_chars_forwards(ledit_buffer *buffer, char *text, int len); static struct action delete_chars_backwards(ledit_buffer *buffer, char *text, int len); static struct action yank(ledit_buffer *buffer, char *text, int len); +static struct action yank_lines(ledit_buffer *buffer, char *text, int len); +static struct action replace(ledit_buffer *buffer, char *text, int len); /* FIXME: maybe sort these and use binary search -> but that would mess with the catch-all keys */ @@ -125,6 +127,7 @@ static struct key keys_en[] = { {"X", 0, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &delete_chars_backwards}, {"d", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION|KEY_NUMBERALLOWED, &key_d}, {"y", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION|KEY_NUMBERALLOWED, &yank}, + {"Y", 0, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &yank_lines}, {"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}, @@ -165,6 +168,7 @@ static struct key keys_en[] = { {"'", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &jump_to_mark}, {"C", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &change_to_eol}, {"D", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &delete_to_eol}, + {"r", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &replace}, {"t", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBERALLOWED, &find_next_char_forwards}, {"T", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBERALLOWED, &find_next_char_backwards}, {"f", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBERALLOWED, &find_char_forwards},