tImplement Y and r - 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 <[email protected]> | |
Date: Wed, 10 Nov 2021 20:01:13 +0100 | |
Implement Y and r | |
Diffstat: | |
M keys_basic.c | 111 +++++++++++++++++++++++++----… | |
M keys_basic_config.h | 4 ++++ | |
2 files changed, 94 insertions(+), 21 deletions(-) | |
--- | |
diff --git a/keys_basic.c b/keys_basic.c | |
t@@ -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) { | |
t@@ -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; | |
t@@ -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->commo… | |
+ buffer->undo, buf, del_range, cur_range, 1, buffer->common->mode | |
); | |
+ if (!copy_to_buffer) | |
+ txtbuf_destroy(buf); | |
} | |
static void | |
t@@ -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? */ | |
t@@ -453,7 +464,7 @@ delete_chars_forwards(ledit_buffer *buffer, char *text, in… | |
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( | |
t@@ -480,7 +491,7 @@ delete_chars_backwards(ledit_buffer *buffer, char *text, i… | |
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 | |
t@@ -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( | |
t@@ -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); | |
t@@ -880,7 +891,7 @@ change_cb(ledit_buffer *buffer, int line, int char_pos, en… | |
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); | |
t@@ -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_s… | |
+ 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; | |
t@@ -1019,7 +1051,7 @@ key_d_cb(ledit_buffer *buffer, int line, int char_pos, e… | |
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->c… | |
t@@ -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 gr… | |
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-… | |
- delete_range(buffer, 0, 0, buffer->cur_line - 1, l1->l… | |
+ delete_range(buffer, 0, 0, buffer->cur_line - 1, l1->l… | |
} | |
} 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… | |
+ delete_range(buffer, 0, 0, buffer->cur_line, buffer->cur_index… | |
} | |
ledit_buffer_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->c… | |
return (struct action){ACTION_NONE, NULL}; | |
t@@ -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-… | |
+ delete_range(buffer, 0, 0, buffer->cur_line, cur_line-… | |
} | |
} else { | |
int i = ledit_line_next_utf8(cur_line, buffer->cur_index); | |
- delete_range(buffer, 0, 0, buffer->cur_line, buffer->cur_index… | |
+ delete_range(buffer, 0, 0, buffer->cur_line, buffer->cur_index… | |
} | |
ledit_buffer_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->c… | |
return (struct action){ACTION_NONE, NULL}; | |
t@@ -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… | |
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 | |
t@@ -88,6 +88,8 @@ static struct action delete_to_eol(ledit_buffer *buffer, cha… | |
static struct action delete_chars_forwards(ledit_buffer *buffer, char *text, i… | |
static struct action delete_chars_backwards(ledit_buffer *buffer, char *text, … | |
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 */ | |
t@@ -125,6 +127,7 @@ static struct key keys_en[] = { | |
{"X", 0, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &delete_chars_backwar… | |
{"d", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION|KEY_NUMBERALLOWED, &ke… | |
{"y", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION|KEY_NUMBERALLOWED, &ya… | |
+ {"Y", 0, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &yank_lines}, | |
{"c", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION|KEY_NUMBERALLOWED, &ch… | |
{"v", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &enter_visual}, | |
{"o", 0, 0, VISUAL, KEY_ANY, KEY_ANY, &switch_selection_end}, | |
t@@ -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_cha… | |
{"T", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBERALLOWED, &find_next_cha… | |
{"f", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBERALLOWED, &find_char_for… |