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