commit 920ff77cf2e64f74df86d0a415cd6e3180a36c8d
parent 250e61a764d867385a09548558b0df6c28af8036
Author: lumidify <nobody@lumidify.org>
Date: Sun, 7 Nov 2021 21:21:36 +0100
Implement x, X, D, C; fix issue with undo
Diffstat:
5 files changed, 218 insertions(+), 68 deletions(-)
diff --git a/buffer.c b/buffer.c
@@ -902,35 +902,45 @@ line_byte_to_char(ledit_line *line, int byte) {
}
int
-ledit_buffer_next_cursor_pos(ledit_buffer *buffer, int line, int byte) {
+ledit_buffer_next_cursor_pos(ledit_buffer *buffer, int line, int byte, int num) {
int nattrs;
ledit_line *ll = ledit_buffer_get_line(buffer, line);
int c = line_byte_to_char(ll, byte);
- int cur_byte = ledit_line_next_utf8(ll, byte);
+ int cur_byte = byte;
const PangoLogAttr *attrs =
pango_layout_get_log_attrs_readonly(ll->layout, &nattrs);
- for (int i = c + 1; i < nattrs; i++) {
- if (attrs[i].is_cursor_position)
- return cur_byte;
- cur_byte = ledit_line_next_utf8(ll, cur_byte);
+ for (int i = 0; i < num; i++) {
+ cur_byte = ledit_line_next_utf8(ll, byte);
+ for (c++; c < nattrs; c++) {
+ if (attrs[c].is_cursor_position)
+ break;
+ cur_byte = ledit_line_next_utf8(ll, cur_byte);
+ }
+ if (cur_byte >= ll->len)
+ break;
}
- return ll->len;
+ return cur_byte <= ll->len ? cur_byte : ll->len;
}
int
-ledit_buffer_prev_cursor_pos(ledit_buffer *buffer, int line, int byte) {
+ledit_buffer_prev_cursor_pos(ledit_buffer *buffer, int line, int byte, int num) {
int nattrs;
ledit_line *ll = ledit_buffer_get_line(buffer, line);
int c = line_byte_to_char(ll, byte);
- int cur_byte = ledit_line_prev_utf8(ll, byte);
+ int cur_byte = byte;
const PangoLogAttr *attrs =
pango_layout_get_log_attrs_readonly(ll->layout, &nattrs);
- for (int i = c - 1; i >= 0; i--) {
- if (attrs[i].is_cursor_position)
- return cur_byte;
+ for (int i = 0; i < num; i++) {
cur_byte = ledit_line_prev_utf8(ll, cur_byte);
+ for (c--; c >= 0; c--) {
+ if (attrs[c].is_cursor_position)
+ break;
+ cur_byte = ledit_line_prev_utf8(ll, cur_byte);
+ }
+ if (cur_byte <= 0)
+ break;
}
- return 0;
+ return cur_byte > 0 ? cur_byte : 0;
}
static int
diff --git a/buffer.h b/buffer.h
@@ -57,8 +57,8 @@ void ledit_pos_to_x_softline(ledit_line *line, int pos, int *x_ret, int *softlin
void ledit_x_softline_to_pos(ledit_line *line, int x, int softline, int *pos_ret);
int ledit_line_next_utf8(ledit_line *line, int index);
int ledit_line_prev_utf8(ledit_line *line, int index);
-int ledit_buffer_next_cursor_pos(ledit_buffer *buffer, int line, int byte);
-int ledit_buffer_prev_cursor_pos(ledit_buffer *buffer, int line, int byte);
+int ledit_buffer_next_cursor_pos(ledit_buffer *buffer, int line, int byte, int num);
+int ledit_buffer_prev_cursor_pos(ledit_buffer *buffer, int line, int byte, int num);
void ledit_buffer_next_word(ledit_buffer *buffer, int line, int byte, int num_repeat, int *line_ret, int *byte_ret, int *real_byte_ret);
void ledit_buffer_next_word_end(ledit_buffer *buffer, int line, int byte, int num_repeat, int *line_ret, int *byte_ret, int *real_byte_ret);
diff --git a/keys_basic.c b/keys_basic.c
@@ -101,6 +101,7 @@ static void unwind_repetition_stack(void);
static void advance_repetition_stack(void);
static void discard_repetition_stack(void);
+static int key_stack_empty(void);
static struct key_stack_elem *push_key_stack(void);
static struct key_stack_elem *peek_key_stack(void);
static struct key_stack_elem *pop_key_stack(void);
@@ -117,6 +118,7 @@ static void get_new_line_softline(
static void move_cursor_in_line_dir(ledit_buffer *buffer, int dir, int allow_illegal_index);
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);
+static void push_undo_empty_insert(ledit_buffer *buffer, int line, int index, int start_group);
/* FIXME: move to common */
static void
@@ -126,6 +128,11 @@ swap(int *a, int *b) {
*b = tmp;
}
+static int
+key_stack_empty(void) {
+ return key_stack.len == 0;
+}
+
static struct key_stack_elem *
push_key_stack(void) {
struct key_stack_elem *e;
@@ -322,14 +329,24 @@ delete_range(
}
static void
-insert_text(ledit_buffer *buffer, int line, int index, char *text, int len, int new_line, int new_index, int start_group) {
+insert_text(
+ ledit_buffer *buffer,
+ int line, int index,
+ char *text, int len,
+ int cur_line1, int cur_index1,
+ int cur_line2, int cur_index2, int start_group) {
if (len < 0)
len = strlen(text);
/* FIXME: this is kind of hacky... */
txtbuf ins_buf = {.text = text, .len = len, .cap = len};
ledit_range cur_range, del_range;
- cur_range.line1 = buffer->cur_line;
- cur_range.byte1 = buffer->cur_index;
+ if (cur_line1 >= 0 && cur_index1 >= 0) {
+ cur_range.line1 = cur_line1;
+ cur_range.byte1 = cur_index1;
+ } else {
+ cur_range.line1 = buffer->cur_line;
+ cur_range.byte1 = buffer->cur_index;
+ }
del_range.line1 = line;
del_range.byte1 = index;
int cur_line, cur_index;
@@ -339,9 +356,9 @@ insert_text(ledit_buffer *buffer, int line, int index, char *text, int len, int
);
/* this is mainly for pasting, where the new line and index
should not be at the end of the pasted text */
- if (new_line >= 0 && new_index >= 0) {
- cur_range.line2 = buffer->cur_line = new_line;
- cur_range.byte2 = buffer->cur_index = new_index;
+ if (cur_line2 >= 0 && cur_index2 >= 0) {
+ cur_range.line2 = buffer->cur_line = cur_line2;
+ cur_range.byte2 = buffer->cur_index = cur_index2;
} else {
cur_range.line2 = buffer->cur_line = cur_line;
cur_range.byte2 = buffer->cur_index = cur_index;
@@ -401,6 +418,73 @@ get_key_repeat(void) {
}
static struct action
+delete_chars_forwards(ledit_buffer *buffer, char *text, int len) {
+ (void)text;
+ (void)len;
+ int num = get_key_repeat();
+ if (num == -1) {
+ ledit_window_show_message(buffer->window, "Invalid key", -1);
+ return (struct action){ACTION_NONE, NULL};
+ } else if (num == 0) {
+ num = 1;
+ }
+ int end_index = ledit_buffer_next_cursor_pos(
+ buffer, buffer->cur_line, buffer->cur_index, num
+ );
+ delete_range(
+ buffer, 0, 0,
+ buffer->cur_line, buffer->cur_index,
+ buffer->cur_line, end_index
+ );
+ paste_buffer_line_based = 0;
+ buffer->cur_index = ledit_buffer_get_legal_normal_pos(
+ buffer, buffer->cur_line, buffer->cur_index
+ );
+ ledit_buffer_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->cur_index);
+ return (struct action){ACTION_NONE, NULL};
+}
+
+static struct action
+delete_chars_backwards(ledit_buffer *buffer, char *text, int len) {
+ (void)text;
+ (void)len;
+ int num = get_key_repeat();
+ if (num == -1) {
+ ledit_window_show_message(buffer->window, "Invalid key", -1);
+ return (struct action){ACTION_NONE, NULL};
+ } else if (num == 0) {
+ num = 1;
+ }
+ int start_index = ledit_buffer_prev_cursor_pos(
+ buffer, buffer->cur_line, buffer->cur_index, num
+ );
+ delete_range(
+ buffer, 0, 0,
+ buffer->cur_line, start_index,
+ buffer->cur_line, buffer->cur_index
+ );
+ paste_buffer_line_based = 0;
+ /* I guess this is technically unnecessary since only
+ text before the current position is deleted */
+ buffer->cur_index = ledit_buffer_get_legal_normal_pos(
+ buffer, buffer->cur_line, start_index
+ );
+ ledit_buffer_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->cur_index);
+ return (struct action){ACTION_NONE, NULL};
+}
+
+/* used to set cursor - I guess this is sort of a hack */
+static void
+push_undo_empty_insert(ledit_buffer *buffer, int line, int index, int start_group) {
+ txtbuf ins_buf = {.text = "", .len = 0, .cap = 0};
+ ledit_range ins_range = {.line1 = line, .byte1 = index, .line2 = line, .byte2 = index};
+ ledit_range cur_range = {.line1 = line, .byte1 = index, .line2 = line, .byte2 = index};
+ ledit_push_undo_insert(
+ buffer->undo, &ins_buf, ins_range, cur_range, start_group, buffer->common->mode
+ );
+}
+
+static struct action
append_line_above(ledit_buffer *buffer, char *text, int len) {
int sli, x;
/* do this here already so the mode group is the same for the newline insertion */
@@ -408,10 +492,10 @@ append_line_above(ledit_buffer *buffer, char *text, int len) {
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);
if (sli == 0) {
- insert_text(buffer, buffer->cur_line, 0, "\n", -1, buffer->cur_line, 0, 1);
+ insert_text(buffer, buffer->cur_line, 0, "\n", -1, -1, -1, buffer->cur_line, 0, 1);
} else {
PangoLayoutLine *sl = pango_layout_get_line_readonly(ll->layout, sli);
- insert_text(buffer, buffer->cur_line, sl->start_index, "\n\n", -1, buffer->cur_line + 1, 0, 1);
+ insert_text(buffer, buffer->cur_line, sl->start_index, "\n\n", -1, -1, -1, buffer->cur_line + 1, 0, 1);
}
return (struct action){ACTION_NONE, NULL};
}
@@ -424,29 +508,35 @@ append_line_below(ledit_buffer *buffer, char *text, int len) {
pango_layout_index_to_line_x(ll->layout, buffer->cur_index, 0, &sli, &x);
PangoLayoutLine *sl = pango_layout_get_line_readonly(ll->layout, sli);
if (sl->start_index + sl->length == ll->len) {
- insert_text(buffer, buffer->cur_line, ll->len, "\n", -1, buffer->cur_line + 1, 0, 1);
+ insert_text(buffer, buffer->cur_line, ll->len, "\n", -1, -1, -1, buffer->cur_line + 1, 0, 1);
} else {
- insert_text(buffer, buffer->cur_line, sl->start_index + sl->length, "\n\n", -1, buffer->cur_line + 1, 0, 1);
+ insert_text(buffer, buffer->cur_line, sl->start_index + sl->length, "\n\n", -1, -1, -1, buffer->cur_line + 1, 0, 1);
}
return (struct action){ACTION_NONE, NULL};
}
static struct action
append_after_cursor(ledit_buffer *buffer, char *text, int len) {
+ enter_insert(buffer, text, len);
+ /* make cursor jump back to original position on undo */
+ push_undo_empty_insert(buffer, buffer->cur_line, buffer->cur_index, 1);
buffer->cur_index = ledit_buffer_next_cursor_pos(
- buffer, buffer->cur_line, buffer->cur_index
+ buffer, buffer->cur_line, buffer->cur_index, 1
);
- return enter_insert(buffer, text, len);
+ return (struct action){ACTION_NONE, NULL};
}
static struct action
append_after_eol(ledit_buffer *buffer, char *text, int len) {
int sli, x;
+ enter_insert(buffer, text, len);
+ /* make cursor jump back to original position on undo */
+ push_undo_empty_insert(buffer, buffer->cur_line, buffer->cur_index, 1);
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);
buffer->cur_index = sl->start_index + sl->length;
- return enter_insert(buffer, text, len);
+ return (struct action){ACTION_NONE, NULL};
}
/* FIXME: allow motion callback! */
@@ -651,6 +741,57 @@ screen_down(ledit_buffer *buffer, char *text, int len) {
return (struct action){ACTION_NONE, NULL};
}
+static struct action
+delete_to_eol(ledit_buffer *buffer, char *text, int len) {
+ (void)text;
+ (void)len;
+ /* FIXME: move to separate function */
+ if (!key_stack_empty()) {
+ clear_key_stack();
+ ledit_window_show_message(buffer->window, "Invalid key", -1);
+ return (struct action){ACTION_NONE, NULL};
+ }
+ int x, sli;
+ 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);
+ delete_range(
+ buffer, 0, 0,
+ buffer->cur_line, buffer->cur_index,
+ buffer->cur_line, sl->start_index + sl->length
+ );
+ paste_buffer_line_based = 0;
+ buffer->cur_index = ledit_buffer_get_legal_normal_pos(
+ buffer, buffer->cur_line, buffer->cur_index
+ );
+ ledit_buffer_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->cur_index);
+ return (struct action){ACTION_NONE, NULL};
+}
+
+static struct action
+change_to_eol(ledit_buffer *buffer, char *text, int len) {
+ (void)text;
+ (void)len;
+ if (!key_stack_empty()) {
+ clear_key_stack();
+ ledit_window_show_message(buffer->window, "Invalid key", -1);
+ return (struct action){ACTION_NONE, NULL};
+ }
+ ledit_buffer_set_mode(buffer, INSERT);
+ int x, sli;
+ 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);
+ delete_range(
+ buffer, 0, 0,
+ buffer->cur_line, buffer->cur_index,
+ buffer->cur_line, sl->start_index + sl->length
+ );
+ paste_buffer_line_based = 0;
+ ledit_buffer_wipe_line_cursor_attrs(buffer, buffer->cur_line);
+ return (struct action){ACTION_NONE, NULL};
+}
+
/* FIXME: clear selection on most commands */
/* FIXME: don't include escape when repeating change with '.'? */
static struct action
@@ -808,7 +949,7 @@ paste_normal(ledit_buffer *buffer, char *text, int len) {
PangoLayoutLine *sl = pango_layout_get_line_readonly(ll->layout, softline);
insert_text(
buffer, buffer->cur_line, sl->start_index + sl->length,
- "\n", -1, buffer->cur_line, buffer->cur_index, 1
+ "\n", -1, -1, -1, buffer->cur_line, buffer->cur_index, 1
);
int text_len = paste_buffer->len;
ll = ledit_buffer_get_line(buffer, buffer->cur_line + 1);
@@ -820,19 +961,22 @@ paste_normal(ledit_buffer *buffer, char *text, int len) {
/* ensure pasted text is on its own hard line */
insert_text(
buffer, buffer->cur_line + 1, 0,
- "\n", -1, buffer->cur_line, buffer->cur_index, 0
+ "\n", -1, -1, -1, buffer->cur_line, buffer->cur_index, 0
);
}
insert_text(
buffer, buffer->cur_line + 1, 0,
- paste_buffer->text, text_len, buffer->cur_line + 1, 0, 0
+ paste_buffer->text, text_len, -1, -1, buffer->cur_line + 1, 0, 0
);
} else {
+ int old_line = buffer->cur_line;
+ int old_index = buffer->cur_index;
/* must allow illegal index so text can be pasted at end of line */
move_cursor_logically(buffer, 1, 1);
insert_text(
buffer, buffer->cur_line, buffer->cur_index,
- paste_buffer->text, paste_buffer->len, buffer->cur_line, buffer->cur_index, 1
+ paste_buffer->text, paste_buffer->len,
+ old_line, old_index, buffer->cur_line, buffer->cur_index, 1
);
}
ledit_buffer_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->cur_index);
@@ -857,7 +1001,7 @@ paste_normal_backwards(ledit_buffer *buffer, char *text, int len) {
PangoLayoutLine *sl = pango_layout_get_line_readonly(ll->layout, softline);
insert_text(
buffer, buffer->cur_line, sl->start_index,
- "\n", -1, buffer->cur_line, buffer->cur_index, 1
+ "\n", -1, -1, -1, buffer->cur_line, buffer->cur_index, 1
);
int text_len = paste_buffer->len;
ll = ledit_buffer_get_line(buffer, buffer->cur_line);
@@ -871,18 +1015,19 @@ paste_normal_backwards(ledit_buffer *buffer, char *text, int len) {
/* ensure pasted text is on its own hard line */
insert_text(
buffer, buffer->cur_line, ll->len,
- "\n", -1, buffer->cur_line, buffer->cur_index, 0
+ "\n", -1, -1, -1, buffer->cur_line, buffer->cur_index, 0
);
new_line = buffer->cur_line + 1;
}
insert_text(
buffer, new_line, 0,
- paste_buffer->text, text_len, new_line, 0, 0
+ paste_buffer->text, text_len, -1, -1, new_line, 0, 0
);
} else {
insert_text(
buffer, buffer->cur_line, buffer->cur_index,
- paste_buffer->text, paste_buffer->len, buffer->cur_line, buffer->cur_index, 1
+ paste_buffer->text, paste_buffer->len,
+ -1, -1, buffer->cur_line, buffer->cur_index, 1
);
}
ledit_buffer_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->cur_index);
@@ -890,24 +1035,6 @@ paste_normal_backwards(ledit_buffer *buffer, char *text, int len) {
return (struct action){ACTION_NONE, NULL};
}
-static struct action
-key_x(ledit_buffer *buffer, char *text, int len) {
- (void)buffer;
- (void)text;
- (void)len;
- struct key_stack_elem *e = pop_key_stack();
- int num = 1;
- clear_key_stack();
- if (e && !(e->key & KEY_NUMBER))
- return (struct action){ACTION_NONE, NULL};
- if (e)
- num = e->count;
- if (num <= 0)
- num = 1;
- /* FIXME: actually do something */
- return (struct action){ACTION_NONE, NULL};
-}
-
static void
push_num(int num) {
struct key_stack_elem *e = peek_key_stack();
@@ -1245,7 +1372,7 @@ return_key(ledit_buffer *buffer, char *text, int len) {
int start_group = 1;
if (delete_selection(buffer))
start_group = 0;
- insert_text(buffer, buffer->cur_line, buffer->cur_index, "\n", -1, -1, -1, start_group);
+ insert_text(buffer, buffer->cur_line, buffer->cur_index, "\n", -1, -1, -1, -1, -1, start_group);
/* FIXME: these aren't needed, right? This only works in insert mode
* anyways, so there's nothing to wipe */
/* ledit_buffer_wipe_line_cursor_attrs(buffer, buffer->cur_line);
@@ -1571,7 +1698,7 @@ redo(ledit_buffer *buffer, char *text, int len) {
static struct action
insert_mode_insert_text(ledit_buffer *buffer, char *text, int len) {
delete_selection(buffer);
- insert_text(buffer, buffer->cur_line, buffer->cur_index, text, len, -1, -1, 1);
+ insert_text(buffer, buffer->cur_line, buffer->cur_index, text, len, -1, -1, -1, -1, 1);
return (struct action){ACTION_NONE, NULL};
}
@@ -1642,9 +1769,10 @@ search_str_forwards(char *haystack, int hlen, char *needle, int nlen, int start_
/* just to make the macro below works for all cases */
/* FIXME: is there a more elegant way to do this? */
static int
-dummy_cursor_helper(ledit_buffer *buffer, int line, int index) {
+dummy_cursor_helper(ledit_buffer *buffer, int line, int index, int num) {
(void)buffer;
(void)line;
+ (void)num;
return index;
}
@@ -1674,13 +1802,13 @@ name##_cb(ledit_buffer *buffer, char *text, int len) {
if (new_index >= 0) { \
if (cb != NULL) { \
new_index = cur_funcm( \
- buffer, buffer->cur_line, new_index \
+ buffer, buffer->cur_line, new_index, 1 \
); \
cb(buffer, buffer->cur_line, new_index, KEY_MOTION_CHAR); \
} else { \
if (buffer->common->mode == VISUAL) { \
buffer->cur_index = cur_funcv( \
- buffer, buffer->cur_line, new_index \
+ buffer, buffer->cur_line, new_index, 1 \
); \
ledit_buffer_set_selection( \
buffer, \
@@ -1689,7 +1817,7 @@ name##_cb(ledit_buffer *buffer, char *text, int len) {
); \
} else { \
buffer->cur_index = cur_funcn( \
- buffer, buffer->cur_line, new_index \
+ buffer, buffer->cur_line, new_index, 1 \
); \
ledit_buffer_set_line_cursor_attrs( \
buffer, buffer->cur_line, buffer->cur_index \
diff --git a/keys_basic_config.h b/keys_basic_config.h
@@ -41,7 +41,6 @@ static struct action push_6(ledit_buffer *buffer, char *text, int len);
static struct action push_7(ledit_buffer *buffer, char *text, int len);
static struct action push_8(ledit_buffer *buffer, char *text, int len);
static struct action push_9(ledit_buffer *buffer, char *text, int len);
-static struct action key_x(ledit_buffer *buffer, char *text, int len);
static struct action key_d(ledit_buffer *buffer, char *text, int len);
static struct action enter_visual(ledit_buffer *buffer, char *text, int len);
static struct action switch_selection_end(ledit_buffer *buffer, char *text, int len);
@@ -84,6 +83,10 @@ static struct action find_next_char_forwards(ledit_buffer *buffer, char *text, i
static struct action find_next_char_backwards(ledit_buffer *buffer, char *text, int len);
static struct action find_char_forwards(ledit_buffer *buffer, char *text, int len);
static struct action find_char_backwards(ledit_buffer *buffer, char *text, int len);
+static struct action change_to_eol(ledit_buffer *buffer, char *text, int len);
+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);
/* FIXME: maybe sort these and use binary search
-> but that would mess with the catch-all keys */
@@ -117,7 +120,8 @@ static struct key keys_en[] = {
{"7", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_7},
{"8", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_8},
{"9", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_9},
- {"x", 0, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &key_x},
+ {"x", 0, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &delete_chars_forwards},
+ {"X", 0, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &delete_chars_backwards},
{"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},
@@ -157,6 +161,8 @@ static struct key keys_en[] = {
{"o", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &append_line_below},
{"m", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &mark_line},
{"'", 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},
{"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},
diff --git a/undo.c b/undo.c
@@ -84,8 +84,8 @@ push_undo(
ledit_undo_stack *undo, txtbuf *text,
ledit_range insert_range,
ledit_range cursor_range,
- int start_group, enum operation type,
- enum ledit_mode mode) {
+ int start_group,
+ enum operation type, enum ledit_mode mode) {
undo_elem *old = peek_undo_elem(undo);
int last_group = old == NULL ? 0 : old->group;
int last_mode_group = old == NULL ? 0 : old->mode_group;
@@ -106,8 +106,7 @@ push_undo(
void
ledit_push_undo_insert(
ledit_undo_stack *undo, txtbuf *text,
- ledit_range insert_range,
- ledit_range cursor_range,
+ ledit_range insert_range, ledit_range cursor_range,
int start_group, enum ledit_mode mode) {
push_undo(
undo, text, insert_range, cursor_range,
@@ -118,8 +117,7 @@ ledit_push_undo_insert(
void
ledit_push_undo_delete(
ledit_undo_stack *undo, txtbuf *text,
- ledit_range insert_range,
- ledit_range cursor_range,
+ ledit_range insert_range, ledit_range cursor_range,
int start_group, enum ledit_mode mode) {
push_undo(
undo, text, insert_range, cursor_range,
@@ -132,6 +130,10 @@ ledit_undo(ledit_undo_stack *undo, enum ledit_mode mode, void *callback_data,
undo_insert_callback insert_cb, undo_delete_callback delete_cb,
int *cur_line_ret, int *cur_index_ret, int *min_line_ret) {
undo_elem *e;
+ /* skip empty elements */
+ while (undo->cur >= 0 && undo->stack[undo->cur].text->len == 0) {
+ undo->cur--;
+ }
if (undo->cur < 0)
return UNDO_OLDEST_CHANGE;
int group = undo->stack[undo->cur].group;
@@ -188,6 +190,10 @@ ledit_redo(ledit_undo_stack *undo, enum ledit_mode mode, void *callback_data,
undo_insert_callback insert_cb, undo_delete_callback delete_cb,
int *cur_line_ret, int *cur_index_ret, int *min_line_ret) {
undo_elem *e;
+ /* skip elements where no text is changed */
+ while (undo->cur < undo->len - 1 && undo->stack[undo->cur + 1].text->len == 0) {
+ undo->cur++;
+ }
if (undo->cur >= undo->len - 1)
return UNDO_NEWEST_CHANGE;
undo->cur++;