tAdd change command ('c') - 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 <[email protected]> | |
Date: Mon, 1 Nov 2021 19:04:48 +0100 | |
Add change command ('c') | |
Diffstat: | |
M buffer.c | 3 +++ | |
M keys_basic.c | 75 +++++++++++++++++++++++++++++… | |
M keys_basic_config.h | 2 ++ | |
3 files changed, 80 insertions(+), 0 deletions(-) | |
--- | |
diff --git a/buffer.c b/buffer.c | |
t@@ -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( | |
t@@ -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 t… | |
+ 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 | |
t@@ -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 … | |
+static void change_cb(ledit_buffer *buffer, int line, int char_pos, enum key_t… | |
/* FIXME: move to common */ | |
static void | |
t@@ -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 != buf… | |
+ 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_inde… | |
+ lines - 1, &new_line, &new_softline | |
+ ); | |
+ ledit_line *ll = ledit_buffer_get_line(buffer,… | |
+ PangoLayoutLine *pl = pango_layout_get_line_re… | |
+ e->motion_cb(buffer, new_line, pl->start_index… | |
+ 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_lin… | |
+ pango_layout_index_to_line_x(ll->layout, buffer->cur_index, 0,… | |
+ PangoLayoutLine *sl = pango_layout_get_line_readonly(ll->layou… | |
+ 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 | |
t@@ -66,6 +66,7 @@ static struct action scroll_lines_down(ledit_buffer *buffer,… | |
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, … | |
+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 */ | |
t@@ -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, &ke… | |
+ {"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}, | |
{"c", ControlMask, 0, INSERT|VISUAL, KEY_ANY, KEY_ANY, &clipcopy}, |